Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
0acdb1c
feat: catalog herdr agent integrations
codejunction Oct 3, 2026
b23afb6
feat: add agent lifecycle domain model
codejunction Oct 3, 2026
13a5fb9
expanded agent enhancement doc and task
codejunction Oct 4, 2026
c2513af
feat(agents): server-owned lifecycle, report api, waits, context store
claude Oct 4, 2026
05ded02
feat(skill): teach agents shared context workflow
claude Oct 4, 2026
d63b246
docs(agents): lifecycle, report api, waits, context cli
claude Oct 4, 2026
7428629
feat(integrations): lifecycle hooks for claude, gemini, cursor, copil…
claude Oct 4, 2026
2b70bf0
feat(agents): codex and claude lifecycle from their own logs
claude Oct 4, 2026
0e3f7ca
feat(agents): resume stored agent sessions after restart
claude Oct 4, 2026
f82b6e2
docs(readme): agent resume setting row
claude Oct 4, 2026
31260ab
feat(integrations): codex hooks, session hooks for qwen, qoder, droid…
claude Oct 4, 2026
1493df9
feat(integrations): kimi, mastracode, kilo, grok, antigravity
claude Oct 4, 2026
3e6ce1c
feat(integrations): letta session hook, hermes plugin
claude Oct 4, 2026
e37d03e
feat(integrations): pi and omp extensions
claude Oct 4, 2026
dfc69f3
feat(integrations): claude, codex, gemini, devin as supported set
claude Oct 4, 2026
10eaae7
feat(agents): attention queue and project rollups
claude Oct 4, 2026
1f547e9
feat(agents): sd agent explain diagnostics
claude Oct 4, 2026
b03feb5
feat(agents): prompt --wait, rename, event stream
claude Oct 4, 2026
5ccfa42
feat(agents): native cli flags for launch, spawn, resume
claude Oct 4, 2026
8f35e4d
feat(agents): native slash commands per agent
claude Oct 4, 2026
5264079
feat(context): context page
claude Oct 4, 2026
c474857
feat(agents): versioned detection rules with local overrides
claude Oct 4, 2026
c5937e1
feat(agents): sd switch, message action, skill update
claude Oct 4, 2026
3187b46
feat(context): agents extract their own facts on demand
claude Oct 4, 2026
f0c3842
docs(integrations): support matrix with verification source
claude Oct 4, 2026
d473cd3
fix(agents): heuristic verdict replaces the previous one
claude Oct 4, 2026
c516ac9
docs(task): record 0.0.7rc1 release
claude Oct 4, 2026
2d991fd
feat(context): deterministic capture of agent commands, tests, edits,…
claude Oct 4, 2026
c3178d1
feat(agents): devin cli commands and hooks cross-checked from web sou…
claude Oct 4, 2026
fcdb1e5
docs(task): tick ci matrix and docs items
claude Oct 4, 2026
3886969
feat(context): smart recall via agent small models, no embeddings
claude Oct 4, 2026
e4b18eb
docs(task): claude verified with real cli; prepare rc2
claude Oct 4, 2026
f9072ad
docs(task): record 0.0.7rc2 release
claude Oct 4, 2026
7f144ce
feat(ui): declutter sidebar footer
claude Oct 4, 2026
4a27bc6
feat(context): human friendly context page, pick agent and model for …
claude Oct 4, 2026
0504f11
docs(task): record 0.0.7rc3 release
claude Oct 4, 2026
f9453f5
feat(context): sd init sets up .shelldeck in a project
claude Oct 4, 2026
fdc479f
docs(readme): refresh screenshots, one actions menu per agent row
claude Oct 4, 2026
a66f521
docs(agents): restructure enhancement doc around what shipped
claude Oct 4, 2026
5150f90
chore(release): 0.0.7
claude Oct 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat(integrations): letta session hook, hermes plugin
- letta default conversation resumes per agent
- hermes python plugin + plugins.enabled yaml edit, refuses unknown layouts
- 17 installable agents; update task.md
  • Loading branch information
claude committed Oct 4, 2026
commit 3e6ce1c2fe7a618c05c5aa64def816f30268fe73
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ All notable changes to shelldeck are listed here. The format follows [Keep a Cha
- Codex and Claude Code state and session ids are also read from their own logs (rollouts, `sessions/<pid>.json`) with no install. A quiet log expires quickly, so approval prompts still come from the screen.
- Resume agent sessions after a restart: *Resumable sessions* on the AI agents page, `sd agent resume`, and the `agent_resume` setting (`ask` by default, `auto` or `never`). Only validated argv of plain words is run. Auto never resumes into an open hand-off, a missing folder or a missing CLI.
- More integrations, following herdr's formats: Codex hooks (`~/.codex/hooks.json` + `[features] hooks = true`), and session-id hooks for Qwen Code, Qoder CLI, Factory Droid and Devin CLI. Resume commands for Codex, Copilot, Cursor, Devin, Droid, Qwen and Qoder. Session-only reports (no `state`) store a resumable session without claiming lifecycle state.
- Integrations for Kimi Code (TOML block), MastraCode, Kilo Code (plugin), Grok and Antigravity CLI (session id), following herdr's formats: 15 agents in all.
- Integrations for Kimi Code (TOML block), MastraCode, Kilo Code (plugin), Grok, Antigravity CLI, Letta Code and Hermes Agent (session id), following herdr's formats: 17 agents in all.
- Hand-off files include a context snapshot, and the installed agent skill teaches the context workflow.

## [0.0.6] - 2026-10-01
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ uv tool install --force -e . # global sd/shelldeck from this checkout (th
- `input` writes the text, waits 0.3s, then sends CR: TUIs take text plus CR in one burst as a paste.
- **Terminal nicks.** `sessions.nick` is a person's name from `db.NICKS`, unique across all terminals (`_free_nick`, backfilled in `init_db`); `_session()` in cli.py resolves id, nick, name, then id prefix. PTYs get `SHELLDECK_NICK` and, for sub-agents, `SHELLDECK_PARENT` (`_attach` passes `extra_env`). `run()` exports `SHELLDECK_PORT` (and an absolute `SHELLDECK_HOME` when set), so `sd` in a terminal reaches the server that owns it.
- `shelldeck/agent_state.py`: canonical lifecycle (`unknown|idle|working|blocked|done|exited`, `blocked_reason`), `Report`/`Registry` with source precedence (integration > custom > native > manifest > heuristic) and TTL expiry, and `parse_report()` validation (stable `ReportError` codes; resume argv must start with the agent's bare executable name and is accepted only from `integration:*`). The server owns state: `_check_agents` puts the old heuristic in as a `heuristic:*` report (`lifecycle.heuristic`, approval -> blocked/approval), resolves, and `_publish` broadcasts `agent_state` with `status` (legacy `state` kept) and pushes only on a transition into blocked. `POST /api/agent-reports` identifies the terminal only by `X-Shelldeck-Report-Token` (`report_tokens`, set as `SHELLDECK_AGENT_REPORT_TOKEN` in `_attach` and dropped when the PTY exits). `agent_kind` holds `(agent, generation)`; `/api/agent-wait` pins the generation and wakes on `_state_changed` events, never polls screens. The browser trusts server status only for authoritative sources (`AUTHORITATIVE` in app.js); otherwise its own screen heuristic stays.
- `shelldeck/integrations.py` + `shelldeck/hook.py`: lifecycle integrations. `INSTALLERS`: `JsonHooks` merges into shared JSON configs (claude settings.json, gemini settings.json, cursor hooks.json) and owns only entries whose command matches `-m shelldeck.hook <agent>`; `OwnFile` writes copilot's `hooks/shelldeck.json` and the OpenCode plugin (`OPENCODE_PLUGIN`). Both make a one-time `.shelldeck-backup`, write atomically, and refuse non-JSON configs. `hook.py` is stdlib-only (one interpreter start per event): `EVENTS` maps each agent's hook events to states, it posts with only the report token, always exits 0 and prints `REPLY`. `_guarded` lets `POST /api/agent-reports` through with just `X-Shelldeck-Report-Token` when `_is_local` (never a tunnel). Formats come from the agents' hook docs as used by dotpals; add an agent only after checking its docs. `CodexHooks` also sets `[features] hooks = true` in config.toml (`enable_codex_hooks`, line edit). Qwen/Qoder/Droid/Devin hooks are `SESSION` (session id only; no `state` in the report, so `parse_report` returns no Report). `hook.RESUME` holds the resume argv per agent (from herdr's agent_resume.rs); `agent_state.RESUME_EXE` allows `cursor-agent`/`agy`. Installing refuses when the agent's config folder is missing. Other shapes: `JsonHooks(key=None)` (MastraCode, flat events at the top level), `NamedBlock` (Antigravity, a `shelldeck` key), `KimiToml` (marked `[[hooks]]` block with explicit states: the hook takes `<agent> <state>` like herdr's, `STATES`), `OwnFile` for Grok's hook file and the Kilo plugin (`_opencode_plugin('kilo')`). Without hooks, `agents.native()` (`_codex_native` reads the rollout's newest `CODEX_EVENTS` entry, `_claude_native` reads `sessions/<pid>.json`) feeds `native:<agent>` reports via `agent_state.native_report` (working holds `NATIVE_WORKING_S` past the last event, so a prompt falls back to the screen), and `_save_native` stores the session id/resume argv once per id.
- `shelldeck/integrations.py` + `shelldeck/hook.py`: lifecycle integrations. `INSTALLERS`: `JsonHooks` merges into shared JSON configs (claude settings.json, gemini settings.json, cursor hooks.json) and owns only entries whose command matches `-m shelldeck.hook <agent>`; `OwnFile` writes copilot's `hooks/shelldeck.json` and the OpenCode plugin (`OPENCODE_PLUGIN`). Both make a one-time `.shelldeck-backup`, write atomically, and refuse non-JSON configs. `hook.py` is stdlib-only (one interpreter start per event): `EVENTS` maps each agent's hook events to states, it posts with only the report token, always exits 0 and prints `REPLY`. `_guarded` lets `POST /api/agent-reports` through with just `X-Shelldeck-Report-Token` when `_is_local` (never a tunnel). Formats come from the agents' hook docs as used by dotpals; add an agent only after checking its docs. `CodexHooks` also sets `[features] hooks = true` in config.toml (`enable_codex_hooks`, line edit). Qwen/Qoder/Droid/Devin hooks are `SESSION` (session id only; no `state` in the report, so `parse_report` returns no Report). `hook.RESUME` holds the resume argv per agent (from herdr's agent_resume.rs); `agent_state.RESUME_EXE` allows `cursor-agent`/`agy`. Installing refuses when the agent's config folder is missing. Other shapes: `JsonHooks(key=None)` (MastraCode, flat events at the top level), `NamedBlock` (Antigravity, a `shelldeck` key), `KimiToml` (marked `[[hooks]]` block with explicit states: the hook takes `<agent> <state>` like herdr's, `STATES`), `OwnFile` for Grok's hook file and the Kilo plugin (`_opencode_plugin('kilo')`), `HermesPlugin` (Python plugin + `hermes_enable` line edit of `plugins.enabled`, refusing layouts it doesn't know). Without hooks, `agents.native()` (`_codex_native` reads the rollout's newest `CODEX_EVENTS` entry, `_claude_native` reads `sessions/<pid>.json`) feeds `native:<agent>` reports via `agent_state.native_report` (working holds `NATIVE_WORKING_S` past the last event, so a prompt falls back to the screen), and `_save_native` stores the session id/resume argv once per id.
- `shelldeck/context.py`: persistent agent context in `<config>/context.db` (separate from shelldeck.db; FTS5 `search` table with a LIKE fallback). Projects are keyed by resolved folder (the deepest shelldeck project containing cwd, else the git top level). Everything stored goes through `redact()`; `SENSITIVE_FILE` paths are never referenced. Knowledge is de-duplicated per project by `_norm` and never merged across projects. `check_stale` re-hashes `source_references`. `project_context` returns a `ContextPackage` dict plus budgeted `text`. `project_files` writes STATE/TASK/MEMORY/DECISIONS.md (server runs it on a thread via `_project_later`). Server endpoints are `/api/context*`, wrapped by `_ctx` (sqlite errors -> 503 `context_unavailable`, never a crash). `_handoff_files` appends `context.snapshot`.
- `shelldeck/team.py`: agent teams.
- `tier()`/`pick_model()`: `--model auto|small|medium|large` maps onto the agent's own `models()` by regex (medium = its default).
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ sd ~/code/api # add a folder as a project and open a terminal in it
- **Agents that talk to each other.** From inside a terminal, `sd agents` lists the other agents in the project, `sd peek` reads another terminal's screen and `sd tell` types a message into it, tagged with the sender so it can reply. *Copy team prompt* on the AI agents page gives you text to paste into each agent so it knows how.
- **Sub-agents and hand-offs.** `sd spawn "task" --model small|medium|large` opens a new terminal in the project with a sub-agent (Claude Code, Codex, Devin, Gemini, Qwen or opencode) already working on the task, picking a cheaper or stronger model by how hard the task is (`auto` guesses). It opens next to yours without taking the keyboard. `sd handoff Maya "task"` gives a task to an agent that is already running. The receiver runs `sd done <id> "summary"`, and the sender gets the summary typed in (when an agent runs there) plus a toast and chime. Every hand-off is written to the project's `.shelldeck/handoff.md` (git-ignored) and listed on the AI agents page. Sub-agents can't spawn more agents, and a terminal that closes mid-task marks its hand-off as exited.
- **The parent is the control center.** A sub-agent never alerts you. When one stops on a question or permission prompt, shelldeck types the question into its parent agent's terminal; the parent decides and answers with `sd answer Maya 1` (keys for the menu) or `sd tell`. Only when the parent is a plain shell does the question come to you. Once a sub-agent's work is done, the parent asks you and closes it with `sd close Maya`, or use *Close* on the hand-off toast.
- **One status, owned by the server.** Each agent terminal is `idle`, `working`, `blocked` (with a reason such as approval or question), `done` or `exited`. Every tab and the CLI see the same value, and the AI agents page shows where it came from: an integration report or screen/activity detection. `sd agent status` prints it. `sd agent wait Maya --until idle --timeout 10m` blocks until the agent gets there; it exits 2 on timeout and 3 if the agent exits or a different agent takes the terminal. `sd integration install` adds a lifecycle hook to Claude Code, Codex, Gemini CLI, Cursor and Copilot CLI and a plugin to OpenCode, so they report working, needs-you and done exactly instead of being read off the screen. Kimi Code, MastraCode and Kilo Code report exact state too. Qwen Code, Qoder, Droid, Devin, Grok and Antigravity get a hook that reports just their session id, so they can be resumed. Other hooks in those configs are kept, and `sd integration uninstall` removes only shelldeck's (see [docs/agent-integrations.md](docs/agent-integrations.md)). Other tools can report with `sd agent report` ([docs/agent-automation.md](docs/agent-automation.md)).
- **One status, owned by the server.** Each agent terminal is `idle`, `working`, `blocked` (with a reason such as approval or question), `done` or `exited`. Every tab and the CLI see the same value, and the AI agents page shows where it came from: an integration report or screen/activity detection. `sd agent status` prints it. `sd agent wait Maya --until idle --timeout 10m` blocks until the agent gets there; it exits 2 on timeout and 3 if the agent exits or a different agent takes the terminal. `sd integration install` adds a lifecycle hook to Claude Code, Codex, Gemini CLI, Cursor and Copilot CLI and a plugin to OpenCode, so they report working, needs-you and done exactly instead of being read off the screen. Kimi Code, MastraCode and Kilo Code report exact state too. Qwen Code, Qoder, Droid, Devin, Grok, Antigravity, Letta and Hermes get a hook that reports just their session id, so they can be resumed. Other hooks in those configs are kept, and `sd integration uninstall` removes only shelldeck's (see [docs/agent-integrations.md](docs/agent-integrations.md)). Other tools can report with `sd agent report` ([docs/agent-automation.md](docs/agent-automation.md)).
- **Resume after a restart.** shelldeck remembers each terminal's agent session (from an integration or the agent's own logs: Claude Code, Codex, OpenCode). After a restart, *Resumable sessions* on the AI agents page or `sd agent resume Maya` starts it again in its terminal. The setting *Resume agent sessions after a restart* is `ask` by default; `auto` does it when the terminal opens, but never into an open hand-off, a missing folder or a missing CLI. Only stored argv of plain words is typed, never anything taken from the screen.
- **Context that outlives the agent.** Each project keeps a task, its current state and next action, memory (facts and discoveries), decisions and recent events in a local database (`context.db` next to the shelldeck config). The same context is written as Markdown to `.shelldeck/STATE.md`, `TASK.md`, `MEMORY.md` and `DECISIONS.md`. A new agent runs `sd context` and continues where the last one stopped. `sd recall "auth architecture"` searches knowledge from every project, with its source project and files. Secrets are redacted before anything is stored, `.env`/key files are never referenced, and knowledge whose source files changed is marked stale. Hand-off files include a context snapshot. All of it stays on this machine.
- **Agents know the commands.** On start, shelldeck installs a `shelldeck` skill for every agent CLI on PATH: a skill for Claude Code, Codex and Devin, and a marked block in the global instructions file of Gemini, opencode, Qwen, Amp, Droid, Copilot, Crush, Goose and Kiro. `sd install-skill --remove` takes it out and stops the reinstall; the AI agents page has an *Install skill* button per agent.
Expand Down Expand Up @@ -189,7 +189,7 @@ sd done ID ["SUMMARY"] [--failed] close a hand-off you were given; the sender
sd answer TERMINAL KEY... press keys in another terminal, e.g. answer a sub-agent's prompt: 1, y enter, esc
sd close TERMINAL [--force] close a terminal; from an agent only its own sub-agents (after you agree)
sd handoffs [--all] hand-offs in this project and their status
sd integration list|detect|status|install|uninstall [AGENT] hooks for 15 agents: claude, codex, gemini, cursor, copilot, opencode, kilo, kimi, mastracode, qwen, qodercli, droid, devin, grok, antigravity
sd integration list|detect|status|install|uninstall [AGENT] hooks for 17 agents: claude, codex, gemini, cursor, copilot, opencode, kilo, kimi, mastracode, qwen, qodercli, droid, devin, grok, antigravity, letta, hermes
sd agent status [TERMINAL] [--json] lifecycle state (idle/working/blocked/done/exited) and its source
sd agent wait TERMINAL --until STATE [--timeout 10m] block until an agent reaches a state
sd agent resume [TERMINAL] list stored agent sessions, or start one again (claude --resume, codex resume, opencode --session)
Expand Down
6 changes: 4 additions & 2 deletions docs/agent-integrations.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ approve, deny or block a tool.
| Antigravity CLI | One `shelldeck` block (`PreInvocation`) in `hooks.json`, which is keyed by hook name: session id only | `~/.gemini/config/` (`ANTIGRAVITY_CLI_CONFIG_DIR`) | yes: `agy --conversation <id>` |
| Grok CLI | Its own `hooks/shelldeck.json` (`SessionStart`): session id only | `~/.grok/` (`GROK_HOME`) | yes: `grok --resume <id>` |
| Kilo Code CLI | The OpenCode plugin, pointed at Kilo (`plugin/shelldeck.js`) | `~/.config/kilo/` (`XDG_CONFIG_HOME`) | yes: `kilo --session <id>` |
| Letta Code | `SessionStart` (`quiet`): session id only; the default conversation resumes per agent | `~/.letta/settings.json` | yes: `letta --conversation <id>` or `--conversation default --agent <id>` |
| Hermes Agent | A Python plugin, `plugins/shelldeck-agent-state/`, listed under `plugins.enabled` in `config.yaml`. An inline or unusual YAML layout is refused (add it by hand) | `~/.hermes/` (`HERMES_HOME`; `%LOCALAPPDATA%\hermes` on Windows) | yes: `hermes --resume <id>` |
| OpenCode | A plugin, `plugins/shelldeck.js`, that posts `chat.message`, `tool.execute.before`, `session.*` and `permission.*` | `~/.config/opencode/` (`XDG_CONFIG_HOME`) | yes: `opencode --session <id>` |

**Without installing anything**, shelldeck also reads two agents' own logs (source `native`):
Expand All @@ -38,9 +40,9 @@ approve, deny or block a tool.
A native "working" holds only 15 s past the last log event, so a prompt waiting for approval (the log goes quiet) is
picked up by screen detection again. An integration report outranks native, which outranks the screen.

**Session id only** (Qwen, Qoder, Droid, Devin, Grok, Antigravity): herdr found these agents' hook events unreliable for lifecycle, so their hooks report only the session id, for resume. The state stays with screen detection.
**Session id only** (Qwen, Qoder, Droid, Devin, Grok, Antigravity, Letta, Hermes): herdr found these agents' hook events unreliable for lifecycle, so their hooks report only the session id, for resume. The state stays with screen detection.

Installing needs the agent's config folder (install and run the agent once first). Pi, OMP (TypeScript extensions), Hermes (Python plugin), Letta and the rest keep using screen detection for now (see `sd integration list`).
Installing needs the agent's config folder (install and run the agent once first). Pi and OMP (TypeScript extensions) and the rest keep using screen detection for now (see `sd integration list`).

## Commands

Expand Down
9 changes: 8 additions & 1 deletion docs/task.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@
(own hook file, session) and Antigravity CLI (named block, session). 15 agents
are installable, 9 with exact lifecycle. Pi, OMP and Hermes (TS/Python plugin
APIs) and Letta remain on screen detection.
- **2026-10-04 — Letta and Hermes:** Letta (`SessionStart` session hook,
resume via `--conversation [default --agent]`) and Hermes (Python plugin +
`plugins.enabled` YAML edit that refuses layouts it doesn't know). 17 agents
are installable. The OpenCode plugin was verified end to end inside a real
terminal (permission.asked -> blocked/approval from `integration`). Pi/OMP
remain.
- **2026-10-04 — Docs:** README, CHANGELOG (Unreleased), CLAUDE.md,
`docs/agent-automation.md` and `docs/agent-report.schema.json` describe the
lifecycle, report API, waits and context commands.
Expand Down Expand Up @@ -229,7 +235,8 @@ conversation without affecting unrelated Codex hooks.
- [x] Install/uninstall round-trip tests with unrelated config preserved.
- [ ] Manual check against installed binaries.
- [x] Kimi (TOML hooks), Kilo (plugin), MastraCode, Grok, Antigravity.
- [ ] Pi/OMP (TypeScript extensions), Hermes (Python plugin), Letta.
- [x] Hermes (Python plugin), Letta.
- [ ] Pi/OMP (TypeScript extensions).

**Done when:** OpenCode reports `working`, `blocked`, and `idle` accurately and
can provide a resumable native session reference.
Expand Down
Loading
Loading