# Netclaw Operations

> REQUIRED when the user asks about scheduling, reminders, cron jobs, timers, background jobs, diagnostics, troubleshooting, MCP tools, daemon health, identity updates, or Netclaw capabilities and self-maintenance.

- Skill: `netclaw-dev/netclaw-operations` (Agent Skill, multi-file: 11 files)
- Install (CLI): `npx skillmds@latest add netclaw-dev/netclaw-operations`
- Raw SKILL.md: https://api.skillmd.com/api/skills/netclaw-dev/netclaw-operations/raw
- Safety review: pending (external: skill-scanner PASS, skillspector FAIL)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: netclaw-dev (https://skillmd.com/u/netclaw-dev)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/netclaw-dev/netclaw-operations

---


# Netclaw Operations

This is your operational guide. Load it when the user's request is about
Netclaw itself — what it can do, how to schedule work, how to diagnose
problems, how to update preferences, or how to maintain itself.

## Route by Intent

Safety-critical and high-frequency guidance (tool arguments, large output,
approvals, identity-vs-memory routing) is inline below. Everything else lives in
a reference file — load the one matching the user's intent with
`skill_read_resource`.

| User intent | Where |
|-------------|-------|
| Schedule reminders/cron; run background shell jobs | `skill_read_resource('netclaw-operations', 'references/scheduling.md')` |
| How tool arguments are validated | [Tool argument validation](#tool-argument-validation) |
| Handle very large tool output | [Large tool output](#large-tool-output) |
| Understand approval prompts | [Approval Prompts](#approval-prompts) |
| Update identity / where facts go (identity vs memory) | [Identity](#identity) |
| Work on a project, switch projects | `skill_read_resource('netclaw-operations', 'references/projects.md')` |
| Discover MCP / available tools | `skill_read_resource('netclaw-operations', 'references/tools.md')` |
| Authorize or diagnose an HTTP/SSE MCP server | [MCP OAuth](#mcp-oauth) |
| Manage skills and sources | `skill_read_resource('netclaw-operations', 'references/skills.md')` |
| Manage inbound webhooks / attachments | `skill_read_resource('netclaw-operations', 'references/webhooks.md')` |
| Add/switch LLM or search provider, OAuth login | `skill_read_resource('netclaw-operations', 'references/providers.md')` |
| Diagnose problems, kill switches, self-update | `skill_read_resource('netclaw-operations', 'references/diagnostics.md')` |
| Rotate or repair secrets | `skill_read_resource('netclaw-operations', 'references/secrets.md')` |
| Pair remote devices, manage access | `skill_read_resource('netclaw-operations', 'references/devices.md')` |
| Kick the tires on Netclaw end-to-end locally | `skill_read_resource('netclaw-operations', 'references/demo-apphost.md')` |

## File and Shell Selection

When available, use `file_read` for a known local file read.
When available, use `file_list` for a known local directory listing.
Use `file_search` for bounded recursive name or literal text search.
Use `file_read` for image metadata.
Use `attach_file` with the authorized source path. The tool copies it into the session when necessary.
A linked or protected destination causes a denial. Do not use shell to bypass that denial.
Issue independent `file_read` calls in parallel when several paths are known.
Use `tool_output_read` to continue a spilled result by call id.
When available, use `file_write` or `file_edit` for a known local file change.
When available, use `web_search` for external discovery and `web_fetch` for a known external page.
When available, use `shell_execute` for local search, VCS, builds, tests, processes, or requested shell behavior.
Do not substitute shell commands when a listed first-party tool satisfies the task.
Do not delegate a known file operation that an available file tool can complete.
After a successful file tool result, do not use shell only to verify it unless the user requests shell behavior.
For disposable text, use `file_write` in `temp_dir`, then use `file_read`; do not attempt a shell redirect first.
Standard temporary APIs use `temp_dir` in each shell process.
Use `load_tool` directly for a known exact tool name.
Use `search_tools` when the capability is known but its exact tool name is not.

Keep shell approval friction bounded:

1. Start with the smallest single shell operation that directly answers the request.
2. Use one operation per call. Keep independent searches and diagnostics separate; do not join them with separators or labels.
3. Add a pipeline only when the requested result requires it.
4. Do not use shell only to verify a successful structured tool result.
5. If approval is required but no interactive requester is available, do not retry or substitute the call during that turn.
6. After an access denial, do not retry that call during the same user turn.
7. Do not change its scope or substitute another tool to evade the denial.
8. A later explicit user request can start a new call. Apply the normal approval policy to that call.
9. Apply all compatible advice in a correction response before the next call.
10. A shell call can return correction advice under Auto. Auto removes approval prompts; it does not remove corrections.
11. Advice grants no authority. Every replacement call passes current policy.
12. If you require the exact platform path, retry unchanged once through normal policy.
13. Reviewed diagnostics without file output do not receive temporary relocation advice. Normal approval and denial rules still apply.

## Project Directory

`set_working_directory(path)` sets the session's project root (absolute path within
allowed roots); the project's identity file (`.netclaw/AGENTS.md`, `CLAUDE.md`,
`AGENTS.md`, or `CONTEXT.md`) then loads into the prompt. Full rules:
`skill_read_resource('netclaw-operations', 'references/projects.md')`.

Choose directories in this order:

1. For declared-project work, omit `WorkingDirectory`; the shell uses `project_dir`.
2. For one call in a named child directory, set typed `WorkingDirectory`.
3. Use `temp_dir` for disposable files. Standard temporary APIs already use this directory.
4. Use an inline directory change only when the task requests that behavior.

Typed `WorkingDirectory` and absolute operands give exact scope but add no safe-space root.
Program-specific directory options do not replace `WorkingDirectory`.
If shell advice names `use_shell_working_directory`, remove the leading `cd` from a new call.
Set `WorkingDirectory` to the suggested child directory. The original call did not run.
The new call passes normal approval policy.
If the task needs the original shell directory behavior, keep the command and set `WorkingDirectory` to `project_dir`.
That explicit project scope skips repeated advice. The original command still passes normal approval policy.

When available, call `set_working_directory` before the first tool call for
another user-named project.
This rule applies to shell tools, file tools, subagents, and absolute path operands.
Do not repeat the call when `[working-context]` already names that project. If
the tool rejects a path, declare the user-provided fallback before other tools.
Do not probe a named project path before declaring it.
Use the task's first project path exactly; do not substitute its parent first.
Honor a request to keep the current project unchanged.
A denied child-directory call does not permit a project change.

## Managed Session Storage

The `[session]` block separates five paths:

- `session_dir` is the workspace and the relative-path fallback.
- `temp_dir` is run-local storage for disposable files.
- `artifact_dir` is the run-owned output area.
- `worktree_dir` is the session area for Git worktrees.
- `log_path` is the exact raw audit log for the current run.

Use `file_read` to read the exact `log_path` for the current run.
Public and Team cannot access other sessions without explicit configured roots.
Versioned parent and child runs share the current session envelope.
Legacy runs can read their own exact log, but not separate parent or child logs.
Use a legacy child's summary and shared-workspace artifacts instead.
Directory list and search require directory authority; an exact log grants none.
Do not use shell to find session logs.
Normal audience and operation policy applies to every session path.
Attachment copies and fetched files must pass destination checks before Netclaw saves them.
A permitted copy or fetch does not enable general file-write access.
If a save fails, report the tool error; do not claim that the file exists.
Netclaw does not automatically remove managed temporary files or worktrees.

Use `shell_execute` to run Git with a destination below `worktree_dir`.
After Git succeeds, use `set_working_directory` to adopt the created path.
A failed Git command does not change project scope.

For Team and Personal sessions, `[working-context]` is refreshed at the start
of each new turn. In a Git project it includes the active worktree, branch,
HEAD, upstream divergence, and dirty counts. Treat this as turn-start
grounding: a checkout or commit performed during the current tool loop appears
in the next turn's snapshot. If Git is unavailable, the turn continues with an
explicit unavailable status rather than invented repository state. Subagents
receive a read-only project/recent-file snapshot. Successful and partial runs
return only file edits confirmed through their own tools; failed or cancelled
runs contribute no parent working-context changes.

## Scheduling & Background Jobs

Reminders: `set_reminder` with schedule type `once` / `interval` / `cron`. Always
set `delivery_kind` explicitly (`current_session` / `channel` / `none`). A reminder
that fires unattended cannot answer approval prompts, so pre-approve any shell verbs
it needs first with `netclaw approvals trust-verb <verb>`. Background shell: set
`_background: true` on `shell_execute` (max 5 concurrent; cancel servers/watchers
when done; background jobs are killed when the session passivates).

Full detail — delivery contract, proactive channel messaging, approval scoping,
job lifecycle — is in
`skill_read_resource('netclaw-operations', 'references/scheduling.md')`.

## Tool argument validation

Prefer the canonical argument names exactly as a tool declares them, and the
canonical meta keys `_rationale`, `_timeout_seconds`, `_background` (leading
underscore, snake_case). Recognition is spelling-tolerant so a near-miss is
consumed rather than dropped: declared params fold case/punctuation, and the
meta keys also accept the underscore-dropped/cased/shortened forms
(`TimeoutSeconds`, `timeout_seconds`, `Timeout` → the timeout hint; `Rationale`,
`Background` likewise). The supplied value is always *used* — never silently
defaulted.

Every tool call requires a non-empty `_rationale` string. State the call intent
and reason in one sentence. Apply this rule to each parallel call and each later
tool iteration. If a correction reports a missing rationale, fix every call
before the retry.

Three things are still rejected loudly, and when rejected the tool did NOT run —
fix and re-issue once, do not retry the same shape:

- **Unknown keys** — a key that matches no parameter and no meta field rejects
  with a `did you mean '<canonical>'?` suggestion and the list of valid names.
- **Invalid values** — a value that cannot parse as its type (`_timeout_seconds:
  "1200ms"`, `_background: "yes"`) rejects instead of falling back to a default.
- **Ambiguous meta spelling** — supplying two keys that map to the same meta
  field (e.g. both `_timeout_seconds` and `TimeoutSeconds`) rejects; send one.

A repeated action-and-outcome correction means that no requested call ran.
Choose a different action or finish the task from the available evidence.
Do not repeat the blocked batch.
Netclaw disables tools for the turn if the same blocked batch appears again.
Report incomplete work and do not claim that the blocked operation succeeded.
If validation rejects metadata, repair the reported value before the retry.
A valid metadata repair is not the same rejected action. A new user message
starts a fresh cycle window; compaction alone does not.
If a text-only response contains tool calls, Netclaw rejects those calls and reports a provider failure.
This failure does not prove that the turn exhausted its tool budget.

## Large tool output

Tool output is bounded to a small inline budget
(`Session.Tuning.MaxInlineToolResultChars`, default 2000 chars) so it never floods
the context window. When a tool's output exceeds that budget you get a head+tail
view inline plus a pointer to the full output — not the whole thing:

- **`shell_execute`** retains the full redacted output inside the current session.
  Use `tool_output_read` with the returned `CallId`, `Start`, and `Limit` values.
  Do not request a path or rerun the source tool to read more.
- **`file_read`** on a large file returns the head and steers you to read a
  specific range with `StartLine`/`Limit` or `grep` (`StartLine` is a 1-based line
  number — line 1 is the first line). Don't `cat` a huge file through
  `shell_execute` to get around it — that just spills again.
- **`background_job`** output goes to `~/.netclaw/jobs/{id}/output.log` (bounded);
  `check_background_job` returns a tail, and you can `file_read`/`grep` the log for the rest.
  Netclaw deletes a terminal job's definition and logs 24 hours after completion.

Use bounded continuation before re-running a command or re-reading a whole file.
Secret-bearing values are redacted from all tool output.

## Tool Discovery

Only a core toolset is always loaded. Use `load_tool(name)` when an exact deferred
tool name is known. Use `search_tools(query)` to find tools by capability when the
name is unknown. Full guidance:
`skill_read_resource('netclaw-operations', 'references/tools.md')`.

MCP servers can also supply workflow skills. These skills use names such as
`mcp__gigatron__month_over_month`. Review the normal skill index first. Use
`skill_load(name, arguments)` when one of these workflows matches the request.

The argument hint marks values that the MCP server requires. Supply those
values exactly. Do not invent a missing value. A loaded prompt can name MCP
tools, but it does not grant them. Use the normal `search_tools` and
`load_tool` flow for each required tool.

## MCP OAuth

For HTTP/SSE MCP servers, the Model Context Protocol .NET SDK owns PKCE,
authorization-code exchange, token refresh, and the related HTTP calls. Netclaw
owns protected-resource discovery and dynamic client registration (DCR),
presents the authorization URL, brokers the browser callback, and durably stores
active credentials. Do not fetch metadata or token endpoints by hand, build PKCE
requests, or create or repair `mcp-oauth-metadata.json`; legacy metadata files
are ignored.

Netclaw requests JSON token responses from providers that negotiate the response
format, including GitHub. This request keeps the response compatible with the
MCP SDK token decoder.

Netclaw registers rather than letting the SDK do it because the SDK hard-codes
`token_endpoint_auth_method: "client_secret_post"` and ignores what the
authorization server advertises, which fails against servers that accept public
clients only. Netclaw registers with the method the server advertises first.
Registration happens only during `netclaw mcp auth <name>`, never on a
background reconnect.

### Authorize a server

Run this with the daemon active:

```bash
netclaw mcp auth <name>
```

The command starts an unpublished client candidate, opens the authorization URL
when possible, always prints it, and waits up to five minutes. Complete the
browser flow normally. If the callback cannot reach this machine, paste the full
redirect URL into the command. Netclaw keeps exchanged credentials local to the
candidate, then commits them once and publishes the client only after tool
discovery succeeds. A failed replacement does not alter durable credentials or
displace an existing healthy connection.

The SDK redirect URI is
`http://127.0.0.1:{Daemon.Port}/api/mcp/oauth/callback`. If the provider requires
a pre-registered redirect URI, use the configured `Daemon.Port`, not a fixed
default port.

A configured `Authorization` header takes precedence over SDK OAuth. Netclaw
sends that header unchanged, does not start SDK OAuth after a challenge, and
rejects `netclaw mcp auth <name>` until the header is removed. Check or rotate the
configured header instead of trying to layer OAuth on top of it.

OAuth credentials are bound to the server's canonical configured resource
identity. If the same profile name is pointed at another resource, Netclaw
withholds its old tokens and dynamically registered client credentials, reports
`AwaitingAuth`, and preserves the old durable record until replacement succeeds.

A token record written before resource binding existed is migrated in place when
its legacy resource describes the configured endpoint, so upgrading does not
force reauthorization. A trailing slash, path case, and a bare-origin resource
indicator all still match; a different scheme, host, port, query, or sibling path
does not, and those report `AwaitingAuth` with both bindings written to the
daemon log. An explicitly configured static OAuth client ID remains
authoritative.

If a server rejects the stored client identity as `invalid_client` — usually
because the registration was deleted on their side — Netclaw discards that
identity, keeps the tokens, and registers a new client on the next
`netclaw mcp auth <name>`. No manual cleanup is needed.

If a server's authorization server publishes no `registration_endpoint`, or
rejects registration, the error names the remedy: register a client manually
with that provider and set it with `netclaw mcp add --client-id <id> ...`.

### Read connection states

| State | Meaning and action |
|-------|--------------------|
| `Connected` | A usable client generation is published. The status includes its discovered tool count. |
| `AwaitingAuth` | No usable OAuth credential is bound to this resource, or an access token expired without a refresh token. Run `netclaw mcp auth <name>`. Startup and background reconnects never open a browser or block. |
| `AuthFailed` | The server rejected credentials that were supplied. Reauthorize SDK-managed OAuth, or check the configured `Authorization` header if it owns auth. |
| `Unreachable` | A non-auth transport, network, timeout, or initialization failure prevented connection. Check the endpoint and daemon logs. |

At startup, the daemon connects enabled MCP servers concurrently. It waits
for each initial attempt before it reports ready. A failed server has its own
status; other server tools remain available. Use `netclaw mcp list` to inspect
each result.

### Diagnose failures

```bash
netclaw mcp list    # configured servers plus live daemon connection states
netclaw doctor      # MCP config and health checks
netclaw status      # daemon connector health, including MCP
```

`netclaw doctor` uses live daemon state when available. If the daemon is down, it
can probe connectivity but cannot verify SDK-managed OAuth; start the daemon for
an authoritative auth result.

OAuth failures return safe structured errors with an `error`, an `operation`,
and, when known, an HTTP `status`. The CLI prints the useful message rather than
raw JSON. A blank provider body still produces a structured daemon error from its
HTTP status. If the daemon response body is blank or malformed, the CLI falls
back to `HTTP <code> <reason>` instead of showing an empty error. Check daemon
logs for full server context; operator-facing errors omit authorization codes,
tokens, PKCE data, and client secrets.

Credential persistence fails loudly. If the durable secrets write fails,
authorization fails, active credentials do not change, and the candidate is not
published. Fix the filesystem or secrets-store error shown in daemon logs, then
run `netclaw mcp auth <name>` again; browser success alone does not mean the MCP
connection is ready.

## Approval Prompts

MCP approval prompts show a bounded, redacted preview of the call arguments.
Actual path- and URL-shaped values appear first and receive a larger preview so
the operator can verify location context without guessing from argument names.
URL credentials, query values, and fragments are redacted.
Large strings, binary data, and nested collections are summarized by size;
secret-like fields and token-shaped values are always redacted. Argument names
and values are escaped before display so server-controlled schema text cannot
break or spoof the approval prompt. MCP grants are tool-wide rather than
directory-scoped, so these prompts omit the misleading `Always here` option and
label the persistent choice `Always allow this tool` rather than the
shell-oriented `Always anywhere`. Other non-shell tools also omit `Always here`
because their approval matchers do not consume directory scope.

Shell approvals store a typed phrase and a scope in `tool-approvals.json`:

- **verb** — the command head plus subcommand chain only (e.g. `git push`,
  `grep`, `freshdesk`). No flags, no path arguments.
- **directory** — the path field for folder and global grants. Netclaw sets it from:
  - **Path argument** in the original command (`find /repo`, `ls /var/log`,
    `cat ~/.bashrc`). The path argument is the directory; for file targets
    the parent directory is used so `cat ~/.bashrc` scopes to `~`.
  - **Cwd** when no path argument is present (`git status`, `freshdesk`).
  - **`null`** for the global wildcard ("approve this verb in any
    directory") — only set by `Always anywhere`.

`This repository` stores a distinct Git repository scope. It applies to
registered worktrees of one repository. Netclaw checks Git registration for
each use. A folder grant keeps its path scope. An unapproved verb or a path
outside the worktree still needs approval.
The scope supports an ordinary `.git` directory and registered linked worktrees.
A main checkout with `--separate-git-dir` does not receive this choice.

**Folder-scoped trust compounds.** An entry on `(find, /home/user/repo)`
auto-allows `find /home/user/repo/.netclaw -name X` because the candidate's
extracted path is under the entry's directory. You don't have to call
`set_working_directory` for this — running a command with a path argument
declares scope implicitly.

For a complete static Bash list with an exact directory change, Netclaw checks
each command in each reachable exact directory. A failed `cd` can leave a later
command in the original directory. Each unapproved verb still needs approval.
Dynamic effects and linked directories retain exact approval.

The approval gate runs three layers in order:

The directory order reserves `temp_dir` for disposable output.
Preserve an explicitly required platform temporary path.
Netclaw does not automatically clean managed temporary storage yet.

1. **Hard-deny list** — system-protected paths. Always blocks.
2. **Safe-verb ∩ safe-space short-circuit** — when the verb is on the curated
   safe list AND the effective directory (path arg or cwd) is under your
   declared safe space (`session_dir` or `project_dir`), the call auto-runs
   with no prompt. The list covers demonstrably read-only verbs: file readers
   (`ls`, `grep`, `cat`, …), system/info verbs (`date`, `whoami`, `uname`,
   `uptime`, …), and read-only `git`/`gh` queries (`git status`, `git log`,
   `gh pr view`, `gh run list`, …). Mutating verbs (`git push`, `git fetch`,
   `rm`, `sed -i`), command-prefixing verbs (`env`, `xargs`, `sudo`),
   network-writing verbs (`gh api`, `curl`), and environment/process-inspection
   verbs (`printenv`, `ps`) are never on the list — the safe-space gate
   cannot scope a verb that dumps the environment or the process table.
3. **Interactive prompt** — everything else. A registered worktree can show six choices:
   - **Once** — run this one time, persist nothing.
   - **This chat** — allow the verbs in this directory for the rest of the
     session.
   - **Always here** — persist `(verb, effective directory)`. The
     "directory" is the command's path argument when present, else cwd.
   - **This repository** — persist a grant for this Git repository.
     Registered sibling worktrees can use it for the same phrase.
   - **Always anywhere** — persist `(verb, null)` global wildcard.
     Danger style.
   - **Deny** — refuse this call only.

**Side-effect-only clauses are authorized but not persisted.** When a
compound command includes pure side-effect verbs (`echo`, `printf`, `:`,
`true`, `false`) with no path argument and no redirect, those clauses are
authorized for the current call by the click but no `ApprovalEntry` is
written for them. Recording every literal `echo "==="` would be noise.

**Prompts survive passivation and restart.** Pending approval prompts are
journaled with their requester and trust context, so if the session goes idle or
the daemon restarts before the user clicks, the click is still honored when it
arrives. Completed sibling tool results are journaled per call, so recovery
re-drives unresolved calls rather than replaying the whole batch. The only case
where a click does nothing is a genuinely expired prompt (the turn already
failed or was superseded); the session then posts a visible "approval prompt has
expired" notice rather than silently dropping the click. If a user reports a
stale button, ask them to re-issue the request.

**Why you may not see a prompt at all.** If the user invokes a read-only verb
(say `grep`) with a path argument under a tree the operator has previously
trusted, the safe-verb short-circuit applies and there is no prompt. This
is intended behavior — read-only inspection of declared work surfaces is
implicit. Mutating verbs in the same directory still prompt.

**When the prompt offers fewer buttons.** Two cases:

- **Complex commands** (bash control-flow like `for/while/done`, unbalanced
  quotes/brackets) get only `Once` and `Deny`. The matcher cannot extract a
  clean verb chain to remember, so persistence is structurally impossible.
- **Shallow cwd** (e.g. `/etc/`, `/`) hides `Always here` only. Persisting a
  too-shallow root would grant the verb across most of the filesystem;
  `This chat` and `Always anywhere` remain available.

If a user keeps getting prompted in their repo on read-only verbs, the
likely cause is the commands they're running don't carry a path argument
(e.g. `git status` with no `-C`). Suggest they call
`set_working_directory <path>` so the safe-verb short-circuit treats that
tree as a safe space. If they keep getting prompted for the same mutating
verb (e.g. `git push`), suggest `Always here` to persist
`(git push, effective directory)`.

When auditing repeated prompts, check both the tool audit trail and daemon
logs. A later call satisfied by an existing grant records
`ApprovalDecision=PreviouslyApproved` and an `ApprovalPattern` like
`git push [persistent: git push in /home/user/repo]`. If the daemon prompts
despite a same-verb persisted grant, it logs an approval near-miss with the
candidate directory, cwd, persisted grant, creation time, and mismatch reason.

### Inspecting, revoking, and pre-approving grants

Use the `netclaw approvals` CLI rather than hand-editing
`tool-approvals.json`. The daemon reads the file on every approval check, so
mutations take effect on the next prompt without a daemon restart.

```bash
# Interactive TUI: see everything grouped by audience and tool
netclaw approvals

# List — human-readable. Entries print as "<verb> in <dir>" or "<verb> anywhere",
# each followed by when the grant was added ("added 3 days ago"; "added —" for
# grants saved before timestamps were tracked).
netclaw approvals list
netclaw approvals list --audience personal --tool shell_execute

# Scriptable JSON output (audiences → tools → typed entries)
netclaw approvals list --json

# Revoke by user-visible form (the same labels list emits)
netclaw approvals revoke "git remote in /home/user/repos/foo/"
netclaw approvals revoke "freshdesk anywhere"

# Pre-approve a verb as a global wildcard for unattended/scheduled tasks
netclaw approvals trust-verb freshdesk
netclaw approvals trust-verb gh --audience team

# Clear every entry for a tool (optionally scoped to one audience)
netclaw approvals revoke --tool shell_execute --all
netclaw approvals revoke --tool shell_execute --all --audience personal
```

`revoke` of a non-existent pattern exits non-zero with a clear message — the
CLI never silently succeeds. `trust-verb` is idempotent — re-running it on an
existing entry exits zero with "no changes."

### Pre-approving for unattended tasks (load-bearing)

Reminders and webhooks fire without a human present and cannot answer prompts.
When you (the agent) are helping the user set up an unattended task that needs
shell commands, **identify the verbs the task will need and proactively suggest
pre-approving them as global wildcards** before the schedule fires.

Example dialogue when the user asks you to schedule a daily Freshdesk report:

> "I'll set up a daily reminder that calls `freshdesk --since=24h`. Since
> reminders run unattended and can't prompt for approval, I need to pre-approve
> the `freshdesk` verb globally — that's a `(freshdesk, null)` entry, meaning
> it will auto-allow in any cwd. Mind if I do that with
> `netclaw approvals trust-verb freshdesk`?"

On confirmation, run the trust-verb command via `shell_execute`, then create
the reminder. The grant persists across daemon restarts.

### Last-resort recovery

If the approval file gets corrupted (the daemon will quarantine it to
`tool-approvals.json.invalid` and warn loudly), or if a v1 store gets detected
during upgrade (the daemon quarantines it to `tool-approvals.json.v1.bak`),
the active file is reset and the v2 store starts empty.

To wipe every persistent grant and start clean, delete the file directly:

macOS/Linux:

```bash
rm ~/.netclaw/config/tool-approvals.json
```

PowerShell:

```powershell
Remove-Item "$HOME/.netclaw/config/tool-approvals.json" -Force
```

Restart the daemon so in-memory session approvals are cleared too.

## Skill Management

Skills load on demand; manage skills and sources via the skill tools. Full guidance:
`skill_read_resource('netclaw-operations', 'references/skills.md')`.

## Webhooks & Inbound Attachments

Inbound webhooks are configured per route; route files are secret-bearing and
protected. Attachment handling is covered alongside. Full setup + rules:
`skill_read_resource('netclaw-operations', 'references/webhooks.md')`.

## Secret Management

Secrets live in `~/.netclaw/config/secrets.json` — **never print raw secret values**
in chat, issues, PRs, or logs. Set them via CLI (`netclaw secrets set <Path> <value>`),
never by direct file edit. Protected paths (`secrets.json`, `.netclaw/keys`,
`config/webhooks`) are always access-denied. Full rotation guidance:
`skill_read_resource('netclaw-operations', 'references/secrets.md')`.

## LLM & Search Providers

Add or switch model providers (including OAuth login) and configure search backends
(e.g. SearXNG) via provider config. Full setup:
`skill_read_resource('netclaw-operations', 'references/providers.md')`.

## Diagnostics, Kill Switches & Self-Maintenance

Headless `COMPACTION` records expose `summarized` and `tool_results_cleared` phase evidence.
A true summary flag does not prove that the summary retains every task requirement.
Older daemon or CLI versions can omit these flags from the transport and report false.
Check the actor log before you conclude that an older run skipped a phase.

When something is broken, start with `netclaw status`, then `netclaw doctor`. Feature
kill switches and self-update/health are covered in the reference. Memory embeddings
can be backfilled with `netclaw memory backfill-embeddings [--force]`; doctor checks
memory embedding availability. Full guidance:
`skill_read_resource('netclaw-operations', 'references/diagnostics.md')`.

## Identity

Your identity is defined by layered files loaded into the session prompt:

| Layer | Source | Audience |
|-------|--------|----------|
| SOUL.md | `~/.netclaw/identity/SOUL.md` (filesystem) | All |
| AGENTS.md | Embedded in the Netclaw binary (audience-specific) | Team/Personal get full version; Public gets stripped version |
| TOOLING.md | `~/.netclaw/identity/TOOLING.md` (filesystem) | Team/Personal only |
| Project instructions | `.netclaw/AGENTS.md` etc. in project directory | Team/Personal only |

**AGENTS.md is binary-owned.** The full AGENTS (Team/Personal) contains operating
rules, autonomy guidance, grounding, search policy, scheduling, background shell,
subagent delegation, skill reference, identity file paths, and memory triage. The
Public AGENTS contains only basic operating rules, autonomy, grounding, and media
attachment guidance.

SOUL.md and TOOLING.md remain editable on disk:
- To edit: read the file first with `file_read`, then write with `file_write`.
- Detail subdirectories: `identity/soul/`, `identity/tooling/`.

**Identity vs memory — what goes where:**

- **Identity files define the agent**: persona, tone, communication style, operating
  rules, and the foundational user grounding set at init (the user's name, timezone).
  Edit these only to change *how the agent itself operates*.
- **Durable facts and preferences about the user** learned or stated over time
  (favorite things, family, history, working preferences) → **memory**
  (`store_memory`); they are recalled when relevant. A user asking you to "remember"
  a preference is a memory write, **not** a SOUL.md edit.

When unsure: does it change who the agent *is* or how it operates? → identity file.
Is it a fact about the user to recall later? → memory.

## Device Pairing

Pair remote devices and manage their access via the pairing flow. Full steps:
`skill_read_resource('netclaw-operations', 'references/devices.md')`.

## Demo AppHost

To demo or kick the tires on Netclaw end-to-end locally:
`skill_read_resource('netclaw-operations', 'references/demo-apphost.md')`.

