[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6HVC9AYQ402AKRSCH0G5RWD":3,"skill-same:01M6HVC9AYQ402AKRSCH0G5RWD":81},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":39,"linkOnly":40,"markdownContent":41,"markdownBody":42,"frontMatter":43,"refName":44,"commitSha":45,"skillDirectory":46,"forksCount":47,"repositoryHtmlUrl":48,"repositoryHomepageUrl":49,"ownerHtmlUrl":50,"ownerBlogUrl":6,"ownerDescription":51,"updatedAt":52,"install":53,"resources":66},"01M6HVC9AYQ402AKRSCH0G5RWD","spawn-session",null,"Spawns a background Claude Code helper in the project or another folder with the configured Remote Control and the boot-written helper system prompt that a hand-built `claude --bg` omits, watches it until idle, and relays its report to the operator. Use when the operator says \"spawn a helper\", \"spawn a new session\", \"run this in a background session\", asks for a new session with `--model` or `--effort`, asks to switch a running helper's model or effort, or names `\u002Fspawn-session`.","gtapps\u002Fhermitd","gtapps","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F16778396?v=4","01M6HTX8TNTPQN3NXRVA63VHTH","01M6HTX8Z23S531ZPPA5DKJVD0",84,"MIT","https:\u002F\u002Fgithub.com\u002Fgtapps\u002Fhermitd\u002Fblob\u002Fmain\u002Fplugins\u002Fhermitd\u002Fskills\u002Fspawn-session\u002FSKILL.md",[],[18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38],"spawn","spawn session","session","new","when","running","control","with","hand","code","helper","boot","prompt","use","remote","system","project","for","model","switch","system prompt","2026-11-10 10:12:30",false,"---\nname: spawn-session\ndescription: Spawns a background Claude Code helper in the project or another folder with the configured Remote Control and the boot-written helper system prompt that a hand-built `claude --bg` omits, watches it until idle, and relays its report to the operator. Use when the operator says \"spawn a helper\", \"spawn a new session\", \"run this in a background session\", asks for a new session with `--model` or `--effort`, asks to switch a running helper's model or effort, or names `\u002Fspawn-session`.\n---\n\n# Spawn Session\n\nLaunch a background Claude Code session in a folder, subscribe to its idle\nnotice, and relay the report through `\u002Fhermitd:watch`.\n\n## Usage\n\n```\n\u002Fhermitd:spawn-session \u003Cprompt-or-\u002Fskill> [--cwd \u003Cabs-dir>] [--worktree] [--name \u003Cn>] [--model \u003Cm>] [--effort \u003Ce>] [--background \u003Cabs-file>] [--task \u003Cid>] [--strict-mcp-config]\n\u002Fhermitd:spawn-session --switch \u003Cn> --record \u003CT-id> [--model \u003Cm>] [--effort \u003Ce>]\n```\n\nFrom `\u003Cdir>`, the launch folder (`\u003Cabs>`, the hermit project root, unless\n`--cwd` names another), that composes:\n\n```\nclaude --bg --name \u003Cn> [--worktree \u003Cn>] [--permission-mode \u003Cp>] [--no-chrome] [--remote-control \u003Cn>] [--model \u003Cm>] [--effort \u003Ce>] [--mcp-config \u003Cdir>\u002F.mcp.json] [--strict-mcp-config] --append-system-prompt-file \u003Cabs>\u002F.hermit\u002Fstate\u002Fhelper-system-prompt.md '\u003Cprompt>'\n```\n\n`--no-chrome` is present on fresh launches when `config.chrome` is false (absent means false). Never add it to `claude --bg --resume`: resume must remain flagless to retain saved options.\n\n`--worktree \u003Cn>` is present only when the operator passed `--worktree`, and\ngives the helper its own worktree of `\u003Cdir>` from the start.\n`--remote-control \u003Cn>` is present when `config.json`'s `remote` is `true` and\nabsent otherwise; `--model` and `--effort` only when the operator passed them.\n`--mcp-config \u003Cdir>\u002F.mcp.json` and `--strict-mcp-config` only when the operator\npassed `--strict-mcp-config`: both flags when `\u003Cdir>\u002F.mcp.json` exists, and\n`--strict-mcp-config` alone when it does not. Strict mode drops plugin and\nuser-scope MCP servers from the helper. A background session cannot answer\nthe project-server approval dialog, and a folder named by `--cwd` brings its\nown `.mcp.json` to that dialog.\nA helper report counts only when its sender's session name equals the `target` of a live `peer-idle` registry entry; the epoch-suffixed helper name is what distinguishes one spawn from a reused name. The helper never writes `tasks\u002F`; the resident records progress and results after that sender check.\n\nSix limits sit on that command:\n\n- The helper starts in `\u003Cdir>`. In a repository's main checkout, Claude Code\n  refuses its Edit and Write until it calls `EnterWorktree`: the\n  `worktree.bgIsolation` setting, `\"worktree\"` by default\n  (https:\u002F\u002Fcode.claude.com\u002Fdocs\u002Fen\u002Fsettings-reference#worktree-bgisolation).\n  `\"none\"` in that project's settings lets helpers edit the checkout directly,\n  on whatever branch the resident has checked out; this skill never sets it.\n  A linked worktree is edited in place under either value, and Bash git\n  commands are not fenced by the setting. Outside a git repository the block\n  still applies, so a non-git `\u003Cdir>` leaves the helper read-only.\n- Any file the helper must Read is passed as an absolute path in the prompt,\n  spelled as an `@\u003Cabs-path>` mention so Claude Code injects it at launch; a\n  worktree does not carry the hermit's untracked state.\n- `\u003Cabs>\u002F.hermit\u002Fstate\u002Fhelper-system-prompt.md` is written at boot\n  and gated like `config.json`. Pass it as `--append-system-prompt-file` (a\n  system-prompt file is not expanded, so `@\u003Cabs-path>` mentions still belong\n  in the prompt). The appended text reaches the helper's main conversation\n  and forks, not its non-fork subagents.\n- `--permission-mode \u003Cp>` from `config.json`'s `permission_mode` keeps the\n  helper in this session's permission class, which is what lets its idle\n  notice reach here rather than being held for an operator who is not\n  watching. `config.json` accepts one value the CLI has no\n  choice for, `default`, so it and `null` and an absent key all mean: leave the\n  flag off entirely and let the helper take the box default.\n  `scripts\u002Fhermitd-start.ts` resolves `default` and `null` the same way;\n  match that rather than inventing a second answer. It does not agree on an\n  absent key, which it reads as `auto` rather than as no flag.\n  `bypassPermissions` is the one value that does not pass through: it\n  becomes `--permission-mode auto` because a helper has no approval\n  surface of its own, and `auto` is the only mode that stays unattended\n  behind a gate.\n- The prompt is one single-quoted argument. An apostrophe in it ends the quote,\n  so replace every `'` with `'\\''` before composing. Anything after the closing\n  quote is a second command the operator never asked for.\n- The launch is not pre-approved, and what the operator sees depends on the\n  mode they run in. On `auto`, the shipped default, the classifier decides and\n  no prompt reaches them on any channel. On `acceptEdits` or `manual` the native\n  approval is relayed to their DM and is allow-once, so every spawn asks again.\n  On `bypassPermissions` there is none. Say what is about to be spawned before\n  running it either way: it is the only thing that makes the launch legible\n  when an approval does arrive, and the only record when none does.\n\nUse only the launch options documented here. Never add bypass flags, tool\npreapprovals, or settings overrides to widen the helper's permissions. If launch\nor execution is blocked, report the blocker; do not retry through a script,\nalternate invocation, or weaker permission mode. The exceptions are\n§ Follow-ups, \"Resume with new instructions\", for an operator follow-up,\n§ Switch a running helper for a model or effort switch, and\n[untrusted-folder.md](untrusted-folder.md) for a refused workspace.\n\n## Commands\n\n- `helper-switch`: `bun ${CLAUDE_PLUGIN_ROOT}\u002Fscripts\u002Fhelper-switch.ts`\n- `trust-workspace`: `bun ${CLAUDE_PLUGIN_ROOT}\u002Fscripts\u002Ftrust-workspace.ts`\n- `task-note`: `bun ${CLAUDE_PLUGIN_ROOT}\u002Fscripts\u002Ftask.ts note .hermit`\n- `task-list`: `bun ${CLAUDE_PLUGIN_ROOT}\u002Fscripts\u002Ftask.ts list .hermit`\n\n## Plan\n\n1. Parse `--cwd`, `--worktree`, `--name`, `--model`, `--effort`, `--background`, `--task`, and `--strict-mcp-config` from the invocation. `--cwd` must be an absolute path to an existing directory. `--background` must name an existing absolute file; append it to the prompt as an `@\u003Cabs-path>` mention. `--task \u003Cid>` is resolved in step 2 before any launch.\n   Remaining text is the prompt. Empty prompt: stop with a one-line ask for\n   the work to run.\n\n   - When `--name` is omitted, derive `\u003Cn>` from the prompt: drop a leading `\u002F`\n     and any `\u003Cplugin>:` namespace, lowercase, replace every non-`[a-z0-9]` run\n     with `-`, keep the first five nonempty tokens joined by `-`, cap the slug\n     at 40 characters, trim any leading or trailing `-`, then append `-` plus\n     the full epoch (`date +%s`). The trim is what keeps a prompt like\n     `#220 fix the parser` from producing a name the launch command reads as a\n     flag. The epoch is not truncated because the watch registry keys on the\n     full name. With `--worktree` it also matters because `claude --worktree\n     \u003Cn>` silently reuses an existing `.claude\u002Fworktrees\u002F\u003Cn>`, its branch and\n     uncommitted state included, so a repeated name is a wrong-branch start\n     with no error. If no token survives the slug is `session`, which is what\n     makes the fallback `session-\u003Cepoch>`.\n     Example: `\u002Ftackle-issue PROP #220` becomes\n     `tackle-issue-prop-220-1788889689`.\n   - `\u003Cm>` \u002F `\u003Ce>` are omitted when the operator does not name them, so the\n     helper takes the box defaults.\n\n2. Resolve `\u003Cabs>` with `git rev-parse --show-toplevel` rather than reading the\n   Bash tool's working directory, which persists across calls and can sit in a\n   subdirectory. `\u003Cdir>` is `--cwd` when given, else `\u003Cabs>`. No further\n   check on `\u003Cdir>`: a folder the CLI refuses is reported with the CLI's own\n   message, except for the untrusted-folder branch in step 3. With `--worktree`, run\n   `git -C \u003Cdir> rev-parse --verify HEAD`; on failure, refuse with one line\n   before composing any launch: `\u003Cdir>` is not a git repository or has no\n   commits; make an initial commit, then retry. An unborn HEAD makes the background launch report\n   success and then crash-loop on worktree creation. When `--task` was passed, validate `\u003Cid>` with `task.ts list \u003Cabs>\u002F.hermit --id \u003Cid> --json`; refuse a missing or closed record before launch. Append `\u003Cabs>\u002F.hermit\u002Ftasks\u002F\u003Cid>.md` to the helper prompt as an absolute background path. Read `\u003Cp>` from `\u003Cabs>\u002F.hermit\u002Fconfig.json`\n   (`permission_mode`), dropping the flag for `default`, `null` or an absent\n   key, mapping `bypassPermissions` to `auto` (Six limits), and passing\n   every other value through unchanged. Read `remote` from the same config\n   and include `--remote-control \u003Cn>` only when the key is present and\n   `true`; `false`, `null` and an absent key all leave the flag off, which\n   is the resident session's own answer for that config. When the operator\n   passed `--strict-mcp-config`, include `--mcp-config \u003Cdir>\u002F.mcp.json\n   --strict-mcp-config` if `\u003Cdir>\u002F.mcp.json` exists, and `--strict-mcp-config`\n   alone if it does not. Check that\n   `\u003Cabs>\u002F.hermit\u002Fstate\u002Fhelper-system-prompt.md` exists; boot\n   writes it. If it is missing, refuse with one line: restart with hermitd-start\n   so boot writes the helper system-prompt file.\n\n3. `cd \u003Cdir>` as its own Bash call, then run the command in Usage as the next\n   one, so the launch stands alone in the transcript and in any approval that\n   does reach the operator. With `--cwd`, then `cd \u003Cabs>` as the next call\n   whatever the launch returned: the task calls below\n   resolve the relative `.hermit` against the Bash tool's\n   persisted directory. Print the returned bg id and `claude logs \u003Cid>`,\n   `claude attach \u003Cid>`, `claude stop \u003Cid>` hints. For a `Workspace not trusted. Run`\n   refusal, follow [untrusted-folder.md](untrusted-folder.md). Home-directory\n   and unresolvable refusals are reported without that branch. If the spawn is declined or\n   fails, stop; do not watch, open a record, or patch a Decision.\n   After every successful launch, read the full session id `\u003Csid>` once:\n   ```bash\n   claude agents --json | jq -r --arg id \u003Cbg-id> '.[] | select(.id==$id) | .sessionId'\n   ```\n   The printed bg id is only the first 8 characters of `\u003Csid>` and is not a\n   resume handle. An empty result means no `\u003Csid>`: say so, write the lines\n   below without `(\u003Csid>)`,\n   and continue to step 4. Without `--task`, inside an open record's turn,\n   append `Handed to helper \u003Cn> (\u003Csid>).` as a progress note by piping it into\n   `bun ${CLAUDE_PLUGIN_ROOT}\u002Fscripts\u002Ftask.ts note .hermit \u003CT-id>`,\n   where `\u003CT-id>` is that open record's id, not the bg id (the note is\n   timestamped for you).\n   After the handoff note, bind the record with\n   `bun ${CLAUDE_PLUGIN_ROOT}\u002Fscripts\u002Ftask.ts note .hermit \u003CT-id> --owner helper:\u003Cn>`.\n   On `invalid_owner` (a custom name outside `[A-Za-z0-9._-]{1,64}`) or\n   `owner_busy`, leave it resident-owned and tell the operator why.\n   With `--task \u003Cid>`, open or reuse a helper-work task with `--dedupe-key \"helper:\u003Ctask-id>\"`, requester from the current authorized turn, and a title naming the helper work. This record holds the helper's report, not the proposal's implementation result. Note `Handed to helper \u003Cn> (\u003Csid>); helper record \u003Chelper-task-id>.` on the source task, and bind the helper-work record with `--owner helper:\u003Cn>`. A repeated launch for the same source task reuses this helper record.\n\n4. Invoke `\u002Fhermitd:watch session \u003Cn> \"\u003Cfirst 40 chars of the operator prompt>\" --id \u003Cbg-id>`.\n   When the watch reports the helper blocked on its `waitingFor`, add nothing:\n   the watch's helper poll announces it in chat.\n   Whenever step 3 bound or opened a record, also pass `--record \u003CT-id>`.\n   That skill owns the subscription (`watch\u002Fsession-watch.md` § Starting a session watch)\n   and the idle-notice relay (`watch\u002Fnotices.md` § Handling idle notices); do not re-implement either.\n   When it declines the subscription, pass on the reason it gives rather than\n   asserting one: the helper may still be running, or it may have finished its\n   first turn before the subscription landed. Either way, give the\n   `claude logs \u003Cid>` id as the way to check on it. When the decline is\n   `No session named \u003Cn> is reachable from here` and the launch printed a bg\n   id, run `claude logs \u003Cid>` and show the operator the last few\n   ANSI-stripped lines; name the state those lines show (a boot dialog it\n   cannot answer, a crash, a finished turn) rather than one they do not. A\n   declined subscription writes no registry entry, so no report can ever\n   reach the record opened in step 3: cancel it with the decline reason\n   (`task.ts cancel .hermit \u003CT-id> --actor \u003Crequester> --reason-stdin`)\n   and say whether the tail leaves the helper running unwatched or stuck,\n   rather than leaving a commitment waiting on a report that cannot arrive.\n\n## Follow-ups\n\nSend follow-ups by `SendMessage` with `notify_when_idle: true`, then read\nwatch § Registering an existing idle subscription with the sent text. The watch relay\nretries a blocked or declined follow-up once with that stored request.\n\n### Resume with new instructions\n\nInputs: helper name, instructions, watch note and flags, and optional\nblocked-reply input from watch's helper poll handler. Return the outcome to\nthe caller so it can handle a resume that could not start.\n\n1. Read the helper's row in `claude agents --json`. Ready means `status` is\n   `idle` and `state` is neither `working`, `blocked` nor `scheduled`. With\n   the blocked-reply input, also accept `status` `waiting` with `state`\n   `blocked`: a helper stuck on a prompt or question, which a message cannot\n   reach. Take its `id` as the bg id and its `sessionId` as the resume handle. Not ready or no\n   row: end without resuming; never stop a busy helper.\n2. Run `claude stop \u003Cbg-id>`, then in one bounded Bash call poll\n   `claude agents --json` every 2s for up to 30s until no row has that `id`.\n   Still listed at the deadline: end without resuming and report that outcome.\n   Then call `TaskStop` on the old watch entry's `poll_task_id` when present;\n   an error means it already exited.\n3. From the project root, run\n   `claude --bg --resume \u003CsessionId> '\u003Cinstructions>'` with no other flag.\n   Apply the launch limits' `'\\''` quoting rule to every apostrophe in the\n   instructions. The saved options include the helper system prompt; extra\n   flags start a copy instead. Launch failure or any output other than a normal\n   resume (for example \"started a copy\"): do not try again; tell the operator\n   what it printed and end with that outcome.\n4. Remove the helper's old watch entry if still live and write the registry,\n   then invoke `\u002Fhermitd:watch session \u003Cname> \"\u003Cnote>\" --id \u003Cbg-id>` plus the\n   given flags. Use the resumed session's bg id (the first 8 characters of its\n   session id). Do not store these prompt instructions as `followup`: they\n   were delivered by resume, not by message. If the watch declines, return\n   that the resumed helper runs unwatched; a launched resume counts as\n   reached even so.\n\n## Switch a running helper\n\nFor `--switch`, Read [switch.md](switch.md) and follow that procedure instead of\nthe launch Plan. It preserves the helper's conversation, name and thread binding.\n\n## Stuck helper\n\n`claude logs \u003Cid>`, `claude stop \u003Cid>`, and the watch expiry notice. Never tmux.\nIdle is not stuck: watch's idle-notice relay leaves an idle helper running,\nexcept for § Follow-ups, \"Resume with new instructions\", and § Switch a running helper.\nA boot dialog in `claude logs \u003Cid>` is handled as in this terminal: relaunch\nwith the option that makes the dialog moot when one exists, otherwise give\nthe operator `claude attach \u003Cid>` (for a hermit in Docker,\n`docker exec -it \u003Ccontainer> claude attach \u003Cid>`), because Remote Control is\nnot connected before boot.\n","# Spawn Session\n\nLaunch a background Claude Code session in a folder, subscribe to its idle\nnotice, and relay the report through `\u002Fhermitd:watch`.\n\n## Usage\n\n```\n\u002Fhermitd:spawn-session \u003Cprompt-or-\u002Fskill> [--cwd \u003Cabs-dir>] [--worktree] [--name \u003Cn>] [--model \u003Cm>] [--effort \u003Ce>] [--background \u003Cabs-file>] [--task \u003Cid>] [--strict-mcp-config]\n\u002Fhermitd:spawn-session --switch \u003Cn> --record \u003CT-id> [--model \u003Cm>] [--effort \u003Ce>]\n```\n\nFrom `\u003Cdir>`, the launch folder (`\u003Cabs>`, the hermit project root, unless\n`--cwd` names another), that composes:\n\n```\nclaude --bg --name \u003Cn> [--worktree \u003Cn>] [--permission-mode \u003Cp>] [--no-chrome] [--remote-control \u003Cn>] [--model \u003Cm>] [--effort \u003Ce>] [--mcp-config \u003Cdir>\u002F.mcp.json] [--strict-mcp-config] --append-system-prompt-file \u003Cabs>\u002F.hermit\u002Fstate\u002Fhelper-system-prompt.md '\u003Cprompt>'\n```\n\n`--no-chrome` is present on fresh launches when `config.chrome` is false (absent means false). Never add it to `claude --bg --resume`: resume must remain flagless to retain saved options.\n\n`--worktree \u003Cn>` is present only when the operator passed `--worktree`, and\ngives the helper its own worktree of `\u003Cdir>` from the start.\n`--remote-control \u003Cn>` is present when `config.json`'s `remote` is `true` and\nabsent otherwise; `--model` and `--effort` only when the operator passed them.\n`--mcp-config \u003Cdir>\u002F.mcp.json` and `--strict-mcp-config` only when the operator\npassed `--strict-mcp-config`: both flags when `\u003Cdir>\u002F.mcp.json` exists, and\n`--strict-mcp-config` alone when it does not. Strict mode drops plugin and\nuser-scope MCP servers from the helper. A background session cannot answer\nthe project-server approval dialog, and a folder named by `--cwd` brings its\nown `.mcp.json` to that dialog.\nA helper report counts only when its sender's session name equals the `target` of a live `peer-idle` registry entry; the epoch-suffixed helper name is what distinguishes one spawn from a reused name. The helper never writes `tasks\u002F`; the resident records progress and results after that sender check.\n\nSix limits sit on that command:\n\n- The helper starts in `\u003Cdir>`. In a repository's main checkout, Claude Code\n  refuses its Edit and Write until it calls `EnterWorktree`: the\n  `worktree.bgIsolation` setting, `\"worktree\"` by default\n  (https:\u002F\u002Fcode.claude.com\u002Fdocs\u002Fen\u002Fsettings-reference#worktree-bgisolation).\n  `\"none\"` in that project's settings lets helpers edit the checkout directly,\n  on whatever branch the resident has checked out; this skill never sets it.\n  A linked worktree is edited in place under either value, and Bash git\n  commands are not fenced by the setting. Outside a git repository the block\n  still applies, so a non-git `\u003Cdir>` leaves the helper read-only.\n- Any file the helper must Read is passed as an absolute path in the prompt,\n  spelled as an `@\u003Cabs-path>` mention so Claude Code injects it at launch; a\n  worktree does not carry the hermit's untracked state.\n- `\u003Cabs>\u002F.hermit\u002Fstate\u002Fhelper-system-prompt.md` is written at boot\n  and gated like `config.json`. Pass it as `--append-system-prompt-file` (a\n  system-prompt file is not expanded, so `@\u003Cabs-path>` mentions still belong\n  in the prompt). The appended text reaches the helper's main conversation\n  and forks, not its non-fork subagents.\n- `--permission-mode \u003Cp>` from `config.json`'s `permission_mode` keeps the\n  helper in this session's permission class, which is what lets its idle\n  notice reach here rather than being held for an operator who is not\n  watching. `config.json` accepts one value the CLI has no\n  choice for, `default`, so it and `null` and an absent key all mean: leave the\n  flag off entirely and let the helper take the box default.\n  `scripts\u002Fhermitd-start.ts` resolves `default` and `null` the same way;\n  match that rather than inventing a second answer. It does not agree on an\n  absent key, which it reads as `auto` rather than as no flag.\n  `bypassPermissions` is the one value that does not pass through: it\n  becomes `--permission-mode auto` because a helper has no approval\n  surface of its own, and `auto` is the only mode that stays unattended\n  behind a gate.\n- The prompt is one single-quoted argument. An apostrophe in it ends the quote,\n  so replace every `'` with `'\\''` before composing. Anything after the closing\n  quote is a second command the operator never asked for.\n- The launch is not pre-approved, and what the operator sees depends on the\n  mode they run in. On `auto`, the shipped default, the classifier decides and\n  no prompt reaches them on any channel. On `acceptEdits` or `manual` the native\n  approval is relayed to their DM and is allow-once, so every spawn asks again.\n  On `bypassPermissions` there is none. Say what is about to be spawned before\n  running it either way: it is the only thing that makes the launch legible\n  when an approval does arrive, and the only record when none does.\n\nUse only the launch options documented here. Never add bypass flags, tool\npreapprovals, or settings overrides to widen the helper's permissions. If launch\nor execution is blocked, report the blocker; do not retry through a script,\nalternate invocation, or weaker permission mode. The exceptions are\n§ Follow-ups, \"Resume with new instructions\", for an operator follow-up,\n§ Switch a running helper for a model or effort switch, and\n[untrusted-folder.md](untrusted-folder.md) for a refused workspace.\n\n## Commands\n\n- `helper-switch`: `bun ${CLAUDE_PLUGIN_ROOT}\u002Fscripts\u002Fhelper-switch.ts`\n- `trust-workspace`: `bun ${CLAUDE_PLUGIN_ROOT}\u002Fscripts\u002Ftrust-workspace.ts`\n- `task-note`: `bun ${CLAUDE_PLUGIN_ROOT}\u002Fscripts\u002Ftask.ts note .hermit`\n- `task-list`: `bun ${CLAUDE_PLUGIN_ROOT}\u002Fscripts\u002Ftask.ts list .hermit`\n\n## Plan\n\n1. Parse `--cwd`, `--worktree`, `--name`, `--model`, `--effort`, `--background`, `--task`, and `--strict-mcp-config` from the invocation. `--cwd` must be an absolute path to an existing directory. `--background` must name an existing absolute file; append it to the prompt as an `@\u003Cabs-path>` mention. `--task \u003Cid>` is resolved in step 2 before any launch.\n   Remaining text is the prompt. Empty prompt: stop with a one-line ask for\n   the work to run.\n\n   - When `--name` is omitted, derive `\u003Cn>` from the prompt: drop a leading `\u002F`\n     and any `\u003Cplugin>:` namespace, lowercase, replace every non-`[a-z0-9]` run\n     with `-`, keep the first five nonempty tokens joined by `-`, cap the slug\n     at 40 characters, trim any leading or trailing `-`, then append `-` plus\n     the full epoch (`date +%s`). The trim is what keeps a prompt like\n     `#220 fix the parser` from producing a name the launch command reads as a\n     flag. The epoch is not truncated because the watch registry keys on the\n     full name. With `--worktree` it also matters because `claude --worktree\n     \u003Cn>` silently reuses an existing `.claude\u002Fworktrees\u002F\u003Cn>`, its branch and\n     uncommitted state included, so a repeated name is a wrong-branch start\n     with no error. If no token survives the slug is `session`, which is what\n     makes the fallback `session-\u003Cepoch>`.\n     Example: `\u002Ftackle-issue PROP #220` becomes\n     `tackle-issue-prop-220-1788889689`.\n   - `\u003Cm>` \u002F `\u003Ce>` are omitted when the operator does not name them, so the\n     helper takes the box defaults.\n\n2. Resolve `\u003Cabs>` with `git rev-parse --show-toplevel` rather than reading the\n   Bash tool's working directory, which persists across calls and can sit in a\n   subdirectory. `\u003Cdir>` is `--cwd` when given, else `\u003Cabs>`. No further\n   check on `\u003Cdir>`: a folder the CLI refuses is reported with the CLI's own\n   message, except for the untrusted-folder branch in step 3. With `--worktree`, run\n   `git -C \u003Cdir> rev-parse --verify HEAD`; on failure, refuse with one line\n   before composing any launch: `\u003Cdir>` is not a git repository or has no\n   commits; make an initial commit, then retry. An unborn HEAD makes the background launch report\n   success and then crash-loop on worktree creation. When `--task` was passed, validate `\u003Cid>` with `task.ts list \u003Cabs>\u002F.hermit --id \u003Cid> --json`; refuse a missing or closed record before launch. Append `\u003Cabs>\u002F.hermit\u002Ftasks\u002F\u003Cid>.md` to the helper prompt as an absolute background path. Read `\u003Cp>` from `\u003Cabs>\u002F.hermit\u002Fconfig.json`\n   (`permission_mode`), dropping the flag for `default`, `null` or an absent\n   key, mapping `bypassPermissions` to `auto` (Six limits), and passing\n   every other value through unchanged. Read `remote` from the same config\n   and include `--remote-control \u003Cn>` only when the key is present and\n   `true`; `false`, `null` and an absent key all leave the flag off, which\n   is the resident session's own answer for that config. When the operator\n   passed `--strict-mcp-config`, include `--mcp-config \u003Cdir>\u002F.mcp.json\n   --strict-mcp-config` if `\u003Cdir>\u002F.mcp.json` exists, and `--strict-mcp-config`\n   alone if it does not. Check that\n   `\u003Cabs>\u002F.hermit\u002Fstate\u002Fhelper-system-prompt.md` exists; boot\n   writes it. If it is missing, refuse with one line: restart with hermitd-start\n   so boot writes the helper system-prompt file.\n\n3. `cd \u003Cdir>` as its own Bash call, then run the command in Usage as the next\n   one, so the launch stands alone in the transcript and in any approval that\n   does reach the operator. With `--cwd`, then `cd \u003Cabs>` as the next call\n   whatever the launch returned: the task calls below\n   resolve the relative `.hermit` against the Bash tool's\n   persisted directory. Print the returned bg id and `claude logs \u003Cid>`,\n   `claude attach \u003Cid>`, `claude stop \u003Cid>` hints. For a `Workspace not trusted. Run`\n   refusal, follow [untrusted-folder.md](untrusted-folder.md). Home-directory\n   and unresolvable refusals are reported without that branch. If the spawn is declined or\n   fails, stop; do not watch, open a record, or patch a Decision.\n   After every successful launch, read the full session id `\u003Csid>` once:\n   ```bash\n   claude agents --json | jq -r --arg id \u003Cbg-id> '.[] | select(.id==$id) | .sessionId'\n   ```\n   The printed bg id is only the first 8 characters of `\u003Csid>` and is not a\n   resume handle. An empty result means no `\u003Csid>`: say so, write the lines\n   below without `(\u003Csid>)`,\n   and continue to step 4. Without `--task`, inside an open record's turn,\n   append `Handed to helper \u003Cn> (\u003Csid>).` as a progress note by piping it into\n   `bun ${CLAUDE_PLUGIN_ROOT}\u002Fscripts\u002Ftask.ts note .hermit \u003CT-id>`,\n   where `\u003CT-id>` is that open record's id, not the bg id (the note is\n   timestamped for you).\n   After the handoff note, bind the record with\n   `bun ${CLAUDE_PLUGIN_ROOT}\u002Fscripts\u002Ftask.ts note .hermit \u003CT-id> --owner helper:\u003Cn>`.\n   On `invalid_owner` (a custom name outside `[A-Za-z0-9._-]{1,64}`) or\n   `owner_busy`, leave it resident-owned and tell the operator why.\n   With `--task \u003Cid>`, open or reuse a helper-work task with `--dedupe-key \"helper:\u003Ctask-id>\"`, requester from the current authorized turn, and a title naming the helper work. This record holds the helper's report, not the proposal's implementation result. Note `Handed to helper \u003Cn> (\u003Csid>); helper record \u003Chelper-task-id>.` on the source task, and bind the helper-work record with `--owner helper:\u003Cn>`. A repeated launch for the same source task reuses this helper record.\n\n4. Invoke `\u002Fhermitd:watch session \u003Cn> \"\u003Cfirst 40 chars of the operator prompt>\" --id \u003Cbg-id>`.\n   When the watch reports the helper blocked on its `waitingFor`, add nothing:\n   the watch's helper poll announces it in chat.\n   Whenever step 3 bound or opened a record, also pass `--record \u003CT-id>`.\n   That skill owns the subscription (`watch\u002Fsession-watch.md` § Starting a session watch)\n   and the idle-notice relay (`watch\u002Fnotices.md` § Handling idle notices); do not re-implement either.\n   When it declines the subscription, pass on the reason it gives rather than\n   asserting one: the helper may still be running, or it may have finished its\n   first turn before the subscription landed. Either way, give the\n   `claude logs \u003Cid>` id as the way to check on it. When the decline is\n   `No session named \u003Cn> is reachable from here` and the launch printed a bg\n   id, run `claude logs \u003Cid>` and show the operator the last few\n   ANSI-stripped lines; name the state those lines show (a boot dialog it\n   cannot answer, a crash, a finished turn) rather than one they do not. A\n   declined subscription writes no registry entry, so no report can ever\n   reach the record opened in step 3: cancel it with the decline reason\n   (`task.ts cancel .hermit \u003CT-id> --actor \u003Crequester> --reason-stdin`)\n   and say whether the tail leaves the helper running unwatched or stuck,\n   rather than leaving a commitment waiting on a report that cannot arrive.\n\n## Follow-ups\n\nSend follow-ups by `SendMessage` with `notify_when_idle: true`, then read\nwatch § Registering an existing idle subscription with the sent text. The watch relay\nretries a blocked or declined follow-up once with that stored request.\n\n### Resume with new instructions\n\nInputs: helper name, instructions, watch note and flags, and optional\nblocked-reply input from watch's helper poll handler. Return the outcome to\nthe caller so it can handle a resume that could not start.\n\n1. Read the helper's row in `claude agents --json`. Ready means `status` is\n   `idle` and `state` is neither `working`, `blocked` nor `scheduled`. With\n   the blocked-reply input, also accept `status` `waiting` with `state`\n   `blocked`: a helper stuck on a prompt or question, which a message cannot\n   reach. Take its `id` as the bg id and its `sessionId` as the resume handle. Not ready or no\n   row: end without resuming; never stop a busy helper.\n2. Run `claude stop \u003Cbg-id>`, then in one bounded Bash call poll\n   `claude agents --json` every 2s for up to 30s until no row has that `id`.\n   Still listed at the deadline: end without resuming and report that outcome.\n   Then call `TaskStop` on the old watch entry's `poll_task_id` when present;\n   an error means it already exited.\n3. From the project root, run\n   `claude --bg --resume \u003CsessionId> '\u003Cinstructions>'` with no other flag.\n   Apply the launch limits' `'\\''` quoting rule to every apostrophe in the\n   instructions. The saved options include the helper system prompt; extra\n   flags start a copy instead. Launch failure or any output other than a normal\n   resume (for example \"started a copy\"): do not try again; tell the operator\n   what it printed and end with that outcome.\n4. Remove the helper's old watch entry if still live and write the registry,\n   then invoke `\u002Fhermitd:watch session \u003Cname> \"\u003Cnote>\" --id \u003Cbg-id>` plus the\n   given flags. Use the resumed session's bg id (the first 8 characters of its\n   session id). Do not store these prompt instructions as `followup`: they\n   were delivered by resume, not by message. If the watch declines, return\n   that the resumed helper runs unwatched; a launched resume counts as\n   reached even so.\n\n## Switch a running helper\n\nFor `--switch`, Read [switch.md](switch.md) and follow that procedure instead of\nthe launch Plan. It preserves the helper's conversation, name and thread binding.\n\n## Stuck helper\n\n`claude logs \u003Cid>`, `claude stop \u003Cid>`, and the watch expiry notice. Never tmux.\nIdle is not stuck: watch's idle-notice relay leaves an idle helper running,\nexcept for § Follow-ups, \"Resume with new instructions\", and § Switch a running helper.\nA boot dialog in `claude logs \u003Cid>` is handled as in this terminal: relaunch\nwith the option that makes the dialog moot when one exists, otherwise give\nthe operator `claude attach \u003Cid>` (for a hermit in Docker,\n`docker exec -it \u003Ccontainer> claude attach \u003Cid>`), because Remote Control is\nnot connected before boot.\n",{"name":5,"description":7},"main","84942b77e465976992abc4e1444c09724b1770af","plugins\u002Fhermitd\u002Fskills\u002Fspawn-session",16,"https:\u002F\u002Fgithub.com\u002Fgtapps\u002Fhermitd","https:\u002F\u002Fhermitd.dev","https:\u002F\u002Fgithub.com\u002Fgtapps","Software engineer from Portugal.\r\nBuilding and deploying agents for real companies.","2026-11-12 00:14:57",{"source":8,"skillName":5,"commands":54,"prompt":64,"zipAvailable":65},[55,58,61],{"tool":56,"command":57},"npx","npx skills add gtapps\u002Fhermitd --skill spawn-session",{"tool":59,"command":60},"bunx","bunx skills add gtapps\u002Fhermitd --skill spawn-session",{"tool":62,"command":63},"pnpm","pnpm dlx skills add gtapps\u002Fhermitd --skill spawn-session","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fgtapps\u002Fhermitd\u002Fblob\u002Fmain\u002Fplugins\u002Fhermitd\u002Fskills\u002Fspawn-session\u002FSKILL.md",true,[67,73,77],{"path":68,"resourceType":69,"resourceTypeDesc":70,"sizeBytes":71,"sourceHtmlUrl":72},"reuse-spawned-helper.md","REFERENCE","参考文档",2028,"https:\u002F\u002Fgithub.com\u002Fgtapps\u002Fhermitd\u002Fblob\u002Fmain\u002Fplugins\u002Fhermitd\u002Fskills\u002Fspawn-session\u002Freuse-spawned-helper.md",{"path":74,"resourceType":69,"resourceTypeDesc":70,"sizeBytes":75,"sourceHtmlUrl":76},"switch.md",3394,"https:\u002F\u002Fgithub.com\u002Fgtapps\u002Fhermitd\u002Fblob\u002Fmain\u002Fplugins\u002Fhermitd\u002Fskills\u002Fspawn-session\u002Fswitch.md",{"path":78,"resourceType":69,"resourceTypeDesc":70,"sizeBytes":79,"sourceHtmlUrl":80},"untrusted-folder.md",1616,"https:\u002F\u002Fgithub.com\u002Fgtapps\u002Fhermitd\u002Fblob\u002Fmain\u002Fplugins\u002Fhermitd\u002Fskills\u002Fspawn-session\u002Funtrusted-folder.md",[82,97,108,134,150,159],{"skillNo":83,"name":84,"nameZh":6,"description":85,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":86,"categories":87,"keywords":88,"publishedAt":39},"01M718AB18DTYHVGXA6VF1VVR2","dream","Nightly memory maintenance from transcript ground truth. Verifies, enriches and tidies auto-memory and topic pages with snapshot validation and undo. Also handles 'undo the dream'.","https:\u002F\u002Fgithub.com\u002Fgtapps\u002Fhermitd\u002Fblob\u002Fmain\u002Fplugins\u002Fhermitd\u002Fskills\u002Fdream\u002FSKILL.md",[],[84,25,89,90,91,92,93,94,95,96],"maintenance","memory","validation","snapshot","pages","auto","memory maintenance","transcript",{"skillNo":98,"name":99,"nameZh":6,"description":100,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":101,"categories":102,"keywords":103,"publishedAt":39},"01M6HVD4WX8RB5EKH49HM66M8X","when-done-switch-to","Arm a deferred model or effort switch. Use for \"when done switch to\", \"after this drop to sonnet\", or \"switch model when idle\".","https:\u002F\u002Fgithub.com\u002Fgtapps\u002Fhermitd\u002Fblob\u002Fmain\u002Fplugins\u002Fhermitd\u002Fskills\u002Fwhen-done-switch-to\u002FSKILL.md",[],[22,104,37,105,35,36,31,106,107],"done","when done switch to","drop","sonnet",{"skillNo":109,"name":110,"nameZh":6,"description":111,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":112,"categories":113,"keywords":114,"publishedAt":39},"01M6HVD0ZA2Q1RD7CA0X8VWF3T","weekly-review","Generate the weekly review report for the current ISO week. Writes to .hermit\u002Fcompiled\u002Freview-weekly-YYYY-Www.md (dev-facing detail) and sends a plain-language channel summary (Delivered \u002F Decisions \u002F Waiting on you \u002F Spend). Runs every Sunday at 23:00 via routine.","https:\u002F\u002Fgithub.com\u002Fgtapps\u002Fhermitd\u002Fblob\u002Fmain\u002Fplugins\u002Fhermitd\u002Fskills\u002Fweekly-review\u002FSKILL.md",[],[115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,35,130,131,132,133],"weekly review","review","weekly","hermit","plain","routine","channel","summary","report","at","generate","via","decisions","you","detail","iso","review report","dev","plain-language",{"skillNo":135,"name":136,"nameZh":6,"description":137,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":138,"categories":139,"keywords":140,"publishedAt":39},"01M6HVCW8PHZXSPYAZQBZXB9DX","watch","Background events via the config watch monitor or ad-hoc Monitor tool. Quiet watches cost zero tokens.","https:\u002F\u002Fgithub.com\u002Fgtapps\u002Fhermitd\u002Fblob\u002Fmain\u002Fplugins\u002Fhermitd\u002Fskills\u002Fwatch\u002FSKILL.md",[],[136,141,142,143,144,145,146,147,148,126,149],"monitor","ZeRO","tokens","tool","cost","ad","config","background","events",{"skillNo":151,"name":152,"nameZh":6,"description":153,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":154,"categories":155,"keywords":156,"publishedAt":39},"01M6HVCRMG53K3Y63WAH59YVFJ","watch-activate","Activate the config watch monitor.","https:\u002F\u002Fgithub.com\u002Fgtapps\u002Fhermitd\u002Fblob\u002Fmain\u002Fplugins\u002Fhermitd\u002Fskills\u002Fwatch-activate\u002FSKILL.md",[],[136,157,158,141,147],"activate","watch activate",{"skillNo":160,"name":161,"nameZh":6,"description":162,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":163,"categories":164,"keywords":170,"publishedAt":39},"01M6HVCK6782RD4D9ADQY0ENKD","voice-notes","Transcribe and respond to voice notes. Activates when any channel message carries an audio attachment, or when asked to transcribe an inbound voice message.","https:\u002F\u002Fgithub.com\u002Fgtapps\u002Fhermitd\u002Fblob\u002Fmain\u002Fplugins\u002Fhermitd\u002Fskills\u002Fvoice-notes\u002FSKILL.md",[165],{"categoryNo":166,"categoryName":167,"taxonomyType":168,"taxonomyTypeDesc":169},"01JBSEEDCAT000000000000016","图像与多媒体","SCENARIO","使用场景",[171,172,173,174,175,176,177,178,179,180,118,22,181,182,183,184,185,186,128,187],"notes","voice","voice notes","SET","Audio","transcribe","operator","understand","transcription","my","read","message","can","telegram","channel message","discord","up"]