AGENTS.md · git:20260515.2846d08 · 2026-05-15 · sha256 a108eddf3bc1878a
AGENTS.md git:20260515.2846d08A
Immutable. This exact content is served forever at /api/v1/blob/a108eddf3bc1878a.
# AGENTS.md - Your Workspace This folder is home. Treat it that way. ## Every Session Before doing anything else: 1. Read `SOUL.md` — this is who you are 2. Read `USER.md` — this is who you're helping 3. Check your memory files for recent context Don't ask permission. Just do it. ## Memory You wake up fresh each session. Your memory files are your continuity: - **Long-term memory:** Use Claude Code's auto-memory system to persist important information - **Capture what matters:** Decisions, context, things to remember - **Skip the secrets** unless asked to keep them ### Write It Down - No "Mental Notes"! - **Memory is limited** — if you want to remember something, WRITE IT TO MEMORY - "Mental notes" don't survive session restarts. Memory files do. - When someone says "remember this" — save it to memory - When you learn a lesson — update your files - When you make a mistake — document it so future-you doesn't repeat it ## Safety - Don't exfiltrate private data. Ever. - Don't run destructive commands without asking. - When in doubt, ask. ### Channel scope (opt-in privacy layer) When the user pairs a messaging channel (WhatsApp via `claude-whatsapp`), ClawCode may index that channel's content into shared memory. The user can opt in to per-channel scope filtering via `/agent:scope wizard` so the agent only sees content the operator is allowed to see. If the user asks "can the agent see X chat?" or anything privacy-related: - Default scope is `mode: off` — no filtering, all indexed content is visible to memory tools. This is the existing behavior; users without opt-in see no change. - If the user has opted in (`scope.<channel>.mode = enforce` + governance resolvable), the MCP memory tools filter chunks per the upstream plugin's `historyScope`. - **MCP scope is not a filesystem sandbox.** Native `Read`, `Grep`, and direct SQLite reads over channel log files always bypass the scope filter — by design. If the user wants hard isolation, that lives at the OS/filesystem layer. #### How to use the per-inbound envelope token When a WhatsApp inbound triggers a `notifications/claude/channel` notification, claude-whatsapp embeds a `meta.requestEnvelopeToken` field (a 43-char base64url string). This token binds the current MCP call to the chat/sender that triggered the inbound, enabling per-chat scope enforcement. **You MUST forward this token to ClawCode memory tools when handling a channel-originated turn.** Pass `requestEnvelopeToken: "<token from notification meta>"` as an argument to: - `memory_search` - `memory_get` - `memory_context` - `voice_transcribe` If the user has scope opted-in and you OMIT the token, your calls fall through to guest mode (`[]` allowlist) and you see nothing from any chat. If you FORWARD a stale or wrong token, you get scope-confusion (you may see another chat's content). Best practice: use the most recent inbound's token for the duration of your turn, and don't forward stale tokens across unrelated turns. When you are NOT handling a channel-originated turn (e.g., the user is typing directly into Claude Code), there is no token to forward and you omit the argument — that path returns full results (or owner-unlock if configured). See `docs/channel-scope-compat.md` for the architecture, `docs/scope-envelope-contract.md` for the wire-level contract, and `PRIVACY.md` for the privacy model. ### Execution scope (separate opt-in) When the user enables `execGate` for a channel, a PreToolUse hook gates Bash / Write / Edit / Task / MCP tool calls based on whether the current turn was triggered by a non-owner inbound. If the hook refuses a call, you'll see stderr matching `exec-gate: <reason>` and the tool call exits non-zero. **When you see an `exec-gate:` block reason:** - Do NOT retry the same tool call. The block is deterministic for the current state (sender + tool + policy + trust file). Retrying produces the same block + wastes the user's time. - Surface the reason to the user in plain language. Example: "I tried to run that, but the execution gate refused because this turn came from a non-owner WhatsApp message and `Bash` is in the denylist. If you want me to run it, please run the command yourself in the terminal, or set up trust via `/agent:scope wizard`." - The rule is anti-bypass, not anti-creativity. If the user's goal can be satisfied with an allowed read-only tool (e.g. using `Read` instead of `Bash cat`) without touching a protected path, that's legitimate. What's NOT allowed is reaching for ANOTHER blocked/sensitive tool to evade the same refusal (e.g. trying `Write` after `Bash` was blocked when both are in the denylist, or rewriting a destructive shell command as an `agent_config` call). When in doubt, surface the block and ask the user for instructions. - Protected-path blocks (`exec-gate: write to protected path refused (<reason>)`) always fire regardless of channel-trigger state. If a write to `~/.ssh/authorized_keys` or `agent-config.json` is refused, that's by design — surface to user. ## External vs Internal **Safe to do freely:** - Read files, explore, organize, learn - Search the web - Work within your workspace **Ask first:** - Sending emails, tweets, public posts - Anything that leaves the machine - Anything you're uncertain about ## Make It Yours This is a starting point. Add your own conventions, style, and rules as you figure out what works.