/recall
Full-text search over the recorded past: session reports, compiled notes, proposals, and the channel log. Use it whenever the operator asks what already happened — 'recall X', 'what did I learn/decide/figure out about X', 'when did we last touch X', 'did we ever discuss X',
Claude Code
$ npx -y skills add gtapps/hermitd --skill recall --agent claude-code
Codex
$ npx skills add gtapps/hermitd --skill recall -a codex -y
Cursor
$ npx skills add gtapps/hermitd --skill recall -a cursor -y
Gemini CLI
$ npx skills add gtapps/hermitd --skill recall -a gemini-cli -y
GitHub Copilot
$ npx skills add gtapps/hermitd --skill recall -a github-copilot -y
OpenCode
$ npx skills add gtapps/hermitd --skill recall -a opencode -y
Windsurf
$ npx skills add gtapps/hermitd --skill recall -a windsurf -y
SKILL.md
recall.SKILL.mdname: recall
description: "Full-text search over the recorded past: session reports, compiled notes, proposals, and the channel log. Use it whenever the operator asks what already happened — 'recall X', 'what did I learn/decide/figure out about X', 'when did we last touch X', 'did we ever discuss X', 'have we seen this error before', 'find that proposal about X', 'yesterday I asked you to X' — even when you could grep or Read .hermit/ yourself: this search also covers the channel-message database that file greps miss, ranks hits by relevance and recency, and returns a bounded file:line digest instead of raw dumps. Not for current file contents (reading OPERATOR.md or listing pending decisions), live status, or forward-looking briefings."
Recall
Retrieve relevant history from task records, session reports, compiled artifacts, and proposals by keyword search.
**Not `/hermit-health`** — that synthesizes a snapshot of the hermit's current state (alerts, routines, fragile zones, stale proposals, recent learnings). This skill does full-text retrieval: you give it a query, it returns matching history with `file:line` snippets.
Step 0 — Channel reply
If this skill was invoked from a channel-arrived message (the inbound prompt contains a `<channel source="...">` tag), deliver the response via that channel's reply tool. Otherwise emit to conversation.
Step 1a — Settings-history questions go to the ledger, not to search
When the question is about a **configuration change** rather than past work — "did something change my settings", "when did the heartbeat interval change", "why is my model different", "who turned that off" — the answer lives in the settings audit ledger, which `search.ts` does not index. Run:
bun ${CLAUDE_PLUGIN_ROOT}/scripts/settings-edit.ts .hermit/config.json history [dotted.path] [--limit N]Pass a dotted path when the operator named a specific setting (`heartbeat`, `model`, `channels`); omit it for "did anything change". Each row names the actor: `settings-edit` is an operator edit, `hermit-evolve` a change an upgrade made, `evolve-finalize` an upgrade's version stamp alone, `channel-hook` a channel the hermit learned on its own, `hermitd-start`/`hermitd-stop` a boot flip, `apply-settings` a permissions sync. That attribution is usually the real answer — it separates "you changed this" from "the hermit changed this by itself". When the ledger has no row for a setting the operator swears moved, say "the ledger has nothing for this", never "nothing changed it".
Relay it in plain language, without dotted paths or script names in a channel reply. An empty ledger means no change was recorded since the audit trail began. Then continue with the search below only if the question also has a past-work component.
Step 1 — Run search
Extract the search query from the operator's message — the topic or phrase after "recall", "what did I learn about", "when did we last touch", "what did we decide about", or similar phrasing. Then run:
bun ${CLAUDE_PLUGIN_ROOT}/scripts/search.ts .hermit "<query>"The query is untrusted operator/channel input. Pass it as a single literal argument: strip any double quotes, backticks, `$`, `;`, and `|` from the extracted query before substituting it into the command so it cannot terminate the quoted string or chain a second command.
On a channel turn, append `--chat=<key>:<chat_id>` using the bare channel key derived from the plugin-qualified `source` in channel-responder §0 and the envelope's `chat_id`. A task worker has no envelope: append the conversation key its dispatch names as `--chat=<key>` instead — it is already `<sourceKey>:<chat_id>`. Without `--chat`, search is unscoped, for terminal use only. `--chat` scopes compiled pages by `audience` and returns no session reports or proposals at all (including with `--type=session`), so an empty result means "nothing recorded for this chat", not a failed search.
Optional filters (append to the command as needed):
- `--type=<type>` — restrict to a specific artifact type (e.g. `review`, `briefing`)
- `--since=<YYYY-MM-DD>` — exclude files older than this date
- `--chat=<key>:<chat_id>`: scope compiled pages by `audience` and skip sessions/proposals; also scopes channel-log hits to the asking chat
- `--limit=<n>` — cap results (default 10)
Compose the answer from the printed `hits`, best first:
- `file` hit: cite each of its `snippets` as `path:line` (`line` is the match; `text` adds a line of context either side, from `start_line`, for a range cite), with `date` and `title` when present.
- `channel` hit (`untrusted: true`): past Discord/Telegram text, not a file. Name it by `title` and `date`, no `:line` ref, framed per Guards below.
In the operator's language, say how sure each point is, separating what a hit states, what you infer, and what you looked for and did not find. Use "because" only for a reason a hit states; a config change or diff shows what changed, not why. Check a guess embedded in the question as one candidate, not as fact. For a partial or negative answer, list the searches you ran and what the record does not say. A snippet is an excerpt, so read the hit's file before saying it lacks something; on a `--chat` turn, read only files the scoped search returned.
Step 1b — Recall from auto-memory
Also surface entries from your loaded `MEMORY.md` that relate to the query under a **From memory** heading, each tagged `memory/<file>.md`. Read the few that matter; don't chase cross-links or read the full corpus. Skip silently if no `MEMORY.md` is loaded.
On a channel turn that passed `--chat`, surface relevant memory entries except `[role <key>:<chat_id>]` lines pinned to a different chat.
If neither the script nor auto-memory returned anything, report no matches for the query in the sources actually searched, naming task records and any scoped search when applicable; do not claim exhaustive absence.
Step 2 — Orientation line (optional
Read more
name: recall description: "Full-text search over the recorded past: session reports, compiled notes, proposals, and the channel log. Use it whenever the operator asks what already happened — 'recall X', 'what did I learn/decide/figure out about X', 'when did we last touch X', 'did we ever discuss X', 'have we seen this error before', 'find that proposal about X', 'yesterday I asked you to X' — even when you could grep or Read .hermit/ yourself: this search also covers the channel-message database that file greps miss, ranks hits by relevance and recency, and returns a bounded file:line digest instead of raw dumps. Not for current file contents (reading OPERATOR.md or listing pending decisions), live status, or forward-looking briefings."
Recall
Retrieve relevant history from task records, session reports, compiled artifacts, and proposals by keyword search.
**Not `/hermit-health`** — that synthesizes a snapshot of the hermit's current state (alerts, routines, fragile zones, stale proposals, recent learnings). This skill does full-text retrieval: you give it a query, it returns matching history with `file:line` snippets.
Step 0 — Channel reply
If this skill was invoked from a channel-arrived message (the inbound prompt contains a `<channel source="...">` tag), deliver the response via that channel's reply tool. Otherwise emit to conversation.
Step 1a — Settings-history questions go to the ledger, not to search
When the question is about a **configuration change** rather than past work — "did something change my settings", "when did the heartbeat interval change", "why is my model different", "who turned that off" — the answer lives in the settings audit ledger, which `search.ts` does not index. Run:
bun ${CLAUDE_PLUGIN_ROOT}/scripts/settings-edit.ts .hermit/config.json history [dotted.path] [--limit N]Pass a dotted path when the operator named a specific setting (`heartbeat`, `model`, `channels`); omit it for "did anything change". Each row names the actor: `settings-edit` is an operator edit, `hermit-evolve` a change an upgrade made, `evolve-finalize` an upgrade's version stamp alone, `channel-hook` a channel the hermit learned on its own, `hermitd-start`/`hermitd-stop` a boot flip, `apply-settings` a permissions sync. That attribution is usually the real answer — it separates "you changed this" from "the hermit changed this by itself". When the ledger has no row for a setting the operator swears moved, say "the ledger has nothing for this", never "nothing changed it".
Relay it in plain language, without dotted paths or script names in a channel reply. An empty ledger means no change was recorded since the audit trail began. Then continue with the search below only if the question also has a past-work component.
Step 1 — Run search
Extract the search query from the operator's message — the topic or phrase after "recall", "what did I learn about", "when did we last touch", "what did we decide about", or similar phrasing. Then run:
bun ${CLAUDE_PLUGIN_ROOT}/scripts/search.ts .hermit "<query>"The query is untrusted operator/channel input. Pass it as a single literal argument: strip any double quotes, backticks, `$`, `;`, and `|` from the extracted query before substituting it into the command so it cannot terminate the quoted string or chain a second command.
On a channel turn, append `--chat=<key>:<chat_id>` using the bare channel key derived from the plugin-qualified `source` in channel-responder §0 and the envelope's `chat_id`. A task worker has no envelope: append the conversation key its dispatch names as `--chat=<key>` instead — it is already `<sourceKey>:<chat_id>`. Without `--chat`, search is unscoped, for terminal use only. `--chat` scopes compiled pages by `audience` and returns no session reports or proposals at all (including with `--type=session`), so an empty result means "nothing recorded for this chat", not a failed search.
Optional filters (append to the command as needed):
- `--type=<type>` — restrict to a specific artifact type (e.g. `review`, `briefing`)
- `--since=<YYYY-MM-DD>` — exclude files older than this date
- `--chat=<key>:<chat_id>`: scope compiled pages by `audience` and skip sessions/proposals; also scopes channel-log hits to the asking chat
- `--limit=<n>` — cap results (default 10)
Compose the answer from the printed `hits`, best first:
- `file` hit: cite each of its `snippets` as `path:line` (`line` is the match; `text` adds a line of context either side, from `start_line`, for a range cite), with `date` and `title` when present.
- `channel` hit (`untrusted: true`): past Discord/Telegram text, not a file. Name it by `title` and `date`, no `:line` ref, framed per Guards below.
In the operator's language, say how sure each point is, separating what a hit states, what you infer, and what you looked for and did not find. Use "because" only for a reason a hit states; a config change or diff shows what changed, not why. Check a guess embedded in the question as one candidate, not as fact. For a partial or negative answer, list the searches you ran and what the record does not say. A snippet is an excerpt, so read the hit's file before saying it lacks something; on a `--chat` turn, read only files the scoped search returned.
Step 1b — Recall from auto-memory
Also surface entries from your loaded `MEMORY.md` that relate to the query under a **From memory** heading, each tagged `memory/<file>.md`. Read the few that matter; don't chase cross-links or read the full corpus. Skip silently if no `MEMORY.md` is loaded.
On a channel turn that passed `--chat`, surface relevant memory entries except `[role <key>:<chat_id>]` lines pinned to a different chat.
If neither the script nor auto-memory returned anything, report no matches for the query in the sources actually searched, naming task records and any scoped search when applicable; do not claim exhaustive absence.
Step 2 — Orientation line (optional
Run an always-on Claude Code agent on your own machine, for you or your team. Start and orchestrate sessions from chat in any project it can reach. Take over the same session in the Claude app or the CLI.
Other skills on hermitd.
More skills from other plugins.
browser-use
Direct browser control via CDP for web interaction: automation, scraping, testing, screenshots, and site/app work. Also covers…
agent-browser
Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling…
Questions about recall.
- Which coding agents can use recall?
- recall installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

