# TOOLS.md - Local Tools & Environment

> This is the canonical tracked tools instruction source, injected at runtime after `templates/instructions/SYSTEM_DEFAULTS.md`.
> User overrides: `workspace/TOOLS.md`.

## Runtime Instruction Precedence

Discoclaw builds prompts with deterministic precedence:

1. **Immutable security policy** (hard-coded runtime rules)
2. **Tracked defaults** (`templates/instructions/SYSTEM_DEFAULTS.md`)
3. **Tracked tools** (this file)
4. **`workspace/AGENTS.md`** (user overrides)
5. **`workspace/TOOLS.md`** (optional user override layer)
6. **Memory and other runtime context** (SOUL/IDENTITY/USER, channel context, memory layers, etc.)

## Browser Automation (agent-browser)

Optional tool for browsing, form filling, and scraping (`npm install -g @anthropic/agent-browser`).

**RSS first:** Before scraping, check for RSS/Atom feeds (`/feed`, `/rss`, `/feed.xml`, or `<link rel="alternate" type="application/rss+xml">` in `<head>`). Use feeds when available — they're more stable and don't trigger bot detection.

### Mode escalation

| Tier | Mode | When to use |
|------|------|-------------|
| 1 | **WebFetch** | Read-only page content; no browser overhead |
| 2 | **Playwright** (`agent-browser open <url>`, add `--headed` for visible window) | Interactive pages — click, fill, scroll. Fresh isolated browser |
| 3 | **CDP** (`discoclaw browser launch` -> `agent-browser connect <reported-port>`) | Reuse Discoclaw's managed Chrome/Chromium profile with cookies/auth/extensions. **Ask-first** — gets access to logged-in accounts |

### Managed launcher flow

Prefer Discoclaw's managed launcher path over manually starting Chrome with a fixed debug port.

- `discoclaw browser setup` creates or validates the dedicated managed profile and checks storage/browser readiness. It does not open a browser.
- `discoclaw browser launch` starts Chrome/Chromium on demand with remote debugging bound to `127.0.0.1`, then only records reusable state after `/json/version` and a WebSocket CDP probe both succeed.
- Complete the one-time login in that headed browser window, then close it when finished.
- Reuse the same profile later with `discoclaw browser launch` or `discoclaw browser launch --headless`.
- After launch, connect `agent-browser` to the verified CDP port or URL that Discoclaw reports. Do not assume a fixed port like `9222`.
- No companion service, long-lived helper daemon, or localhost control service is part of this path. Discord `!browser` commands print the local operator command; they do not launch the browser for you.
- The initial headed login launch should be run locally from an interactive desktop session on the Discoclaw machine. Service-managed environments may not have the display/session access needed to open a visible browser window.

### Commands

All commands work the same across Playwright and CDP modes once connected.

Navigation:    open <url> | close
Snapshot:      snapshot -i — get element refs (@e1, @e2, ...)
Interact:      click @e1 | fill @e2 "text" | select @e1 "option" | check @e1
Keyboard:      press Enter | type @e2 "text"
Scroll:        scroll down 500
Read:          get text @e1 | get url | get title
Wait:          wait @e1 | wait 2000
Capture:       screenshot | screenshot --full

### Constraints

- Do NOT browse internal/localhost/RFC1918 URLs (exception: connecting `agent-browser` to the loopback CDP port or URL that Discoclaw just verified is the intended CDP use).
- CDP is ask-first. Never connect to a real browser session without explicit user consent.
- Do NOT save auth state to tracked/committed locations. Prefer Discoclaw's managed browser storage under `DISCOCLAW_DATA_DIR/browser/`.
- In source checkouts, repo-local managed browser storage is only supported at the ignored default `./data/browser/` path. If custom browser storage is needed, move `DISCOCLAW_DATA_DIR` outside the repo.

## Service Operations (discoclaw)

Discoclaw runs as a user-level systemd service. Status checks and log reads are fine anytime, but **always ask before restarting or stopping** — a restart kills any active Claude Code sessions (including forge runs), and the user may have work in progress.

### Environment (.env)

Discoclaw loads `.env` from the service **working directory** via `EnvironmentFile` and `dotenv/config`. In a source checkout that is usually the repo root; in npm-managed installs it is the package/install directory. If you need to change env vars, edit that instance's `.env`. The `!secret` command also targets this file.

### Authorized Commands

| Action | Command |
|--------|---------|
| Restart | `systemctl --user restart discoclaw` |
| Stop | `systemctl --user stop discoclaw` |
| Start | `systemctl --user start discoclaw` |
| Status | `systemctl --user status discoclaw` |
| Logs | `journalctl --user -u discoclaw --no-pager -n 50` |

### Procedure

When a restart seems needed (code changes, config updates, etc.):

1. **Ask first** — Confirm with the user before restarting. A restart kills all active sessions.
2. **Check status** — `systemctl --user status discoclaw` (is it running? stuck? already stopped?)
3. **Restart** — `systemctl --user restart discoclaw`
3. **Verify** — Check status again, then tail logs to confirm healthy startup
4. **Report** — Tell the user what happened (was running, restarted, came back clean — or didn't)

### Discord Convenience Commands

These commands are handled directly by discoclaw (no AI invocation):

- `!restart` — restart the discoclaw service (checks status before/after, reports outcome)
- `!restart status` — show current service status
- `!restart logs` — show recent service logs (last 30 lines)
- `!stop` — abort all active AI streams and cancel any running forge
- `!models` — show current model assignments for all roles
- `!models set <role> <model>` — change the model for a role at runtime
- `!models help` — show available roles and usage

### Discord Bot Invite

When a user needs to invite or re-invite the bot to a server:

- **Use the Installation page** — direct them to Discord Developer Portal → Installation → set Install Link to "Discord Provided Link" → add scope `bot` under Default Install Settings. This produces a permanent link with permissions baked in.
- **Do not construct OAuth URLs manually** — the `authorize?client_id=...` pattern works but is error-prone and harder to maintain. The Installation page is the recommended path.
- **Always include the `bot` scope** — without it, the bot won't join the server. `applications.commands` alone is insufficient.
- Full guide: `docs/discord-bot-setup.md`.

### Guardrails

- **Always ask before restart/stop.** Restarts kill active sessions. Never restart without explicit confirmation, even if the user just asked to change something that requires a restart.
- **Only `--user` services.** Never touch system-level services (`--system`). If something needs sudo, hand it to the user.
- **Only discoclaw.** This authorization covers the discoclaw service specifically. Other user services require asking first.
- **Report, don't hide.** Always tell the user the outcome, even if it's routine.
- **If restart fails twice, stop and diagnose.** Don't loop. Check logs, report the error, suggest next steps.

### Rebuild & Restart Workflow

When the user asks for "a rebuild," follow a consistent sequence and wait for confirmation before touching services.

1. Switch to the real repo: `cd ~/code/discoclaw`.
2. Run `git pull` to sync with origin.
3. Run `pnpm install` (it can't hurt even if dependencies are already satisfied).
4. Run `pnpm build` and treat any non‑zero exit as a failure; capture the stdout/stderr snippet that proves the build finished.
5. Offer to run `pnpm preflight` only if the user explicitly asks for it.
6. Report back with the command outputs and explicitly state "build succeeded" or where it failed.
7. Wait for the user to acknowledge the rebuild succeeded before proposing or executing any restart.

If the user separately asks for a restart, only then execute `systemctl --user restart discoclaw`, following the existing restart procedure (status → restart → status/logs). Never restart before the rebuild workflow has succeeded and been confirmed; the rebuild must be confirmed first, then the restart follows as a distinct, second step.

## Webhook Server

Inbound webhook server — external services trigger AI responses in Discord via `POST /webhook/<source>` (HMAC-SHA256 verified).
Dispatches through the same cron execution pipeline as automations; webhook jobs run without Discord action permissions or tool access.
See `docs/webhook-exposure.md` for config and setup.

## Plan-Audit-Implement Workflow

Structured dev workflow for audited plans before writing code. Triggered by "plan this", "let's plan", `!plan`, or `!forge`. Stages: DRAFT → REVIEW → REVISE → APPROVED → IMPLEMENTING → AUDITING → DONE. Plans stored in `workspace/plans/plan-NNN-slug.md`. See `docs/plan-and-forge.md`.

## Task Management

Built-in task tracker backed by Discord forum threads. Use `taskCreate` for work items (TODOs, follow-ups, bugs, feature requests). Always post a link to the task's Discord thread after creating one.

## Discord Action Types

Discord action schemas are injected into your prompt at runtime. Use `<discord-action>` blocks as documented there. In DMs, action blocks are not available.
