# Available Tools

This document describes the tools available to nanobot.

## File Operations

### read_file
Read the contents of a file.
```
read_file(path: str) -> str
```

### write_file
Write content to a file (creates parent directories if needed).
```
write_file(path: str, content: str) -> str
```

### edit_file
Edit a file by replacing specific text.
```
edit_file(path: str, old_text: str, new_text: str) -> str
```

### list_dir
List contents of a directory.
```
list_dir(path: str) -> str
```

## Shell Execution

### exec
Execute a shell command and return output.
```
exec(command: str, working_dir: str = None) -> str
```

**Safety Notes:**
- Commands have a configurable timeout (default 60s)
- Dangerous commands are blocked (rm -rf, format, dd, shutdown, etc.)
- Output is truncated at 10,000 characters
- Optional `restrictToWorkspace` config to limit paths

**Git Commands:**
- **ALWAYS use exec for git commands** (git commit, git push, git status, etc.)
- **NEVER use write_file or edit_file for git commands**
- Examples:
  - `exec(command="git commit -m 'Fix bug'")`
  - `exec(command="git status")`
  - `exec(command="git push")`

## Web Access

### web_search
Search the web using Brave Search API.
```
web_search(query: str, count: int = 5) -> str
```

Returns search results with titles, URLs, and snippets. Requires `tools.web.search.apiKey` in config.

### web_fetch
Fetch and extract main content from a URL.
```
web_fetch(url: str, extractMode: str = "markdown", maxChars: int = 50000) -> str
```

**Notes:**
- Content is extracted using readability
- Supports markdown or plain text extraction
- Output is truncated at 50,000 characters by default

## Email

### read_emails
Read emails from your configured email account via IMAP. **ALWAYS use this tool for email queries - NEVER use exec with mail commands.**
```
read_emails(limit: int = 10, unread_only: bool = False, mark_seen: bool = False) -> str
```

**CRITICAL:** For ANY question about emails (latest email, email sender, email content, etc.), you MUST use this tool. Do NOT use `exec` with `mail` command or read memory files for email information. This tool connects directly to IMAP and fetches CURRENT, real-time email data.

**Parameters:**
- `limit`: Maximum number of emails to return (1-50, default: 10)
- `unread_only`: If true, only return unread emails (default: false)
- `mark_seen`: If true, mark emails as read after fetching (default: false)

**Examples:**
- `read_emails(limit=1)` - Get the latest email
- `read_emails(unread_only=true)` - Get all unread emails
- `read_emails(limit=5, mark_seen=false)` - Get last 5 emails without marking as read

## Communication

### message
Send a message to the user (used internally).
```
message(content: str, channel: str = None, chat_id: str = None) -> str
```

## Background Tasks

### spawn
Spawn a subagent to handle a task in the background.
```
spawn(task: str, label: str = None) -> str
```

Use for complex or time-consuming tasks that can run independently. The subagent will complete the task and report back when done.

## Scheduled Reminders (Cron)

### cron
Schedule reminders and recurring tasks. **REQUIRED: Always include 'action' parameter.**
```
cron(action: str, message: str = None, in_seconds: int = None, at: str = None, every_seconds: int = None, cron_expr: str = None, tz: str = None, job_id: str = None) -> str
```

**Actions:**
- `action="add"` - Create a new reminder or recurring task
- `action="list"` - List all scheduled jobs
- `action="remove"` - Remove a job by ID

**Examples:**

Reminder in N seconds (recommended for relative time):
```
cron(action="add", message="Send a text to your son", in_seconds=25)
cron(action="add", message="Take a break", in_seconds=300)  # 5 minutes
```

One-time reminder at specific time:
```
cron(action="add", message="Meeting starts now!", at="2025-01-31T15:00:00")
```

Recurring reminder:
```
cron(action="add", message="Drink water! 💧", every_seconds=7200)  # Every 2 hours
```

Scheduled task with cron expression:
```
cron(action="add", message="Good morning! ☀️", cron_expr="0 9 * * *")  # Daily at 9am
cron(action="add", message="Standup", cron_expr="0 9 * * 1-5", tz="America/Vancouver")  # Weekdays 9am Vancouver time
```

List or remove:
```
cron(action="list")
cron(action="remove", job_id="abc123")
```

**Important:** Always include `action` parameter. For "remind me in X seconds/minutes", use `in_seconds` instead of calculating `at` manually.

## Heartbeat Task Management

The `HEARTBEAT.md` file in the workspace is checked every 30 minutes.
Use file operations to manage periodic tasks:

### Add a heartbeat task
```python
# Append a new task
edit_file(
    path="HEARTBEAT.md",
    old_text="## Example Tasks",
    new_text="- [ ] New periodic task here\n\n## Example Tasks"
)
```

### Remove a heartbeat task
```python
# Remove a specific task
edit_file(
    path="HEARTBEAT.md",
    old_text="- [ ] Task to remove\n",
    new_text=""
)
```

### Rewrite all tasks
```python
# Replace the entire file
write_file(
    path="HEARTBEAT.md",
    content="# Heartbeat Tasks\n\n- [ ] Task 1\n- [ ] Task 2\n"
)
```

---

## Adding Custom Tools

To add custom tools:
1. Create a class that extends `Tool` in `nanobot/agent/tools/`
2. Implement `name`, `description`, `parameters`, and `execute`
3. Register it in `AgentLoop._register_default_tools()`
