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
docs(readme): refresh screenshots, one actions menu per agent row
  • Loading branch information
claude committed Oct 4, 2026
commit fdc479fe82844296247e1654800414430d09c89b
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ in split or free-floating panes that survive restarts, with your AI coding agent

[Install](#install) · [Features](#features) · [CLI](#cli) · [Remote access](#remote-access) · [Security](#security) · [Contributing](https://github.com/codejunction/shelldeck/blob/main/CONTRIBUTING.md)

<img src="https://raw.githubusercontent.com/codejunction/shelldeck/main/docs/assets/screenshot.png" alt="shelldeck with four named terminals: a git log, Claude Code with its model and context use, Codex with a detected port, and a Claude Code sub-agent reporting its finished hand-off" width="100%">
<img src="https://raw.githubusercontent.com/codejunction/shelldeck/main/docs/assets/screenshot.png" alt="shelldeck with four named terminals across projects: a git log, Claude Code waiting on you, Codex running a smart recall, and agent status per terminal" width="100%">

</div>

Expand Down Expand Up @@ -101,13 +101,15 @@ sd ~/code/api # add a folder as a project and open a terminal in it
- **What needs you, first.** Each project in the sidebar shows its most urgent agent state as text: *needs you*, then *working*, then *done*. The AI agents page sorts agents the same way, shows how long each has been in its state, and *Open next* jumps to the next agent waiting on you, in any project. A finished agent stays *done* until you open its terminal.
- **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.
- **What happened, recorded for free.** Each agent's commands (with success or failure), test runs and edited files come in through its integration hooks, and your own shell commands through shell integration. They become the project's recent events and its *Tests* and *Last error* lines. Each agent run ends with `.shelldeck/sessions/<id>.md`: agent, times, files changed, commands, tests, errors, git. No model is involved and no tokens are spent. Command output, file contents and `.env`-style files are never recorded, and secrets are redacted.
- **Facts come from the agents.** No model runs inside shelldeck: agents record what they learn with `sd remember`, `sd decide` and `sd task update`. *Extract facts* on the AI agents page (or `sd agent extract Maya`) asks an agent to do it now, in one short turn. It never runs on its own, so it costs tokens only when you ask.
- **Facts come from the agents.** No model runs inside shelldeck: agents record what they learn with `sd remember`, `sd decide` and `sd task update`. *Extract facts* in an agent's *Actions* menu on the AI agents page (or `sd agent extract Maya`) asks an agent to do it now, in one short turn. It never runs on its own, so it costs tokens only when you ask.
- **Smart search without embeddings.** `sd recall auth --smart` (or *smart* on the Context page, or the *Smart search* setting) asks an installed agent's smallest model for related keywords (authentication, oauth, jwt, session...) and searches with those too. It uses the agent's own non-interactive mode: `claude -p --model haiku`, `codex exec`, `gemini -p -m flash-lite` or `devin -p`. Only the query is sent, never your stored memory, and answers are cached, so each new query costs a few tokens once. If no agent is available, search uses keywords only.
- **Context page.** The sidebar's *Context* view reads like a status page: *Working on* (task, next step, tests passing or failing, last error, git; *Edit* when you need it), *Facts* ("may be out of date" when a source file changed; check or remove them on hover), *Decisions*, and *Recent activity* in plain words. The search box can widen a search with an installed agent and a model you choose (its cheapest by default).
- **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.

<img src="https://raw.githubusercontent.com/codejunction/shelldeck/main/docs/assets/agents.png" alt="AI agents page: four named agents with their tool, model and project, two finished hand-offs with their results, and the available agent CLIs" width="100%">
<img src="https://raw.githubusercontent.com/codejunction/shelldeck/main/docs/assets/agents.png" alt="AI agents page: who needs you with Open next, each agent's live status and source, the hook integrations, and the available agent CLIs" width="100%">

<img src="https://raw.githubusercontent.com/codejunction/shelldeck/main/docs/assets/context.png" alt="Context page: what the project is working on, its facts, decisions and recent agent activity" width="100%">

<table>
<tr>
Expand Down
2 changes: 1 addition & 1 deletion docs/agent-integrations.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ three, the flags come from their docs as used by dotpals and herdr.

## Native slash commands

`sd agent cmd TERMINAL ACTION [ARG]` (and the *Command…* menu on the AI agents page) types the agent's own command:
`sd agent cmd TERMINAL ACTION [ARG]` (and the *Actions* menu on the AI agents page) types the agent's own command:

| Action | Claude Code | Codex | Gemini CLI | Devin CLI |
| --- | --- | --- | --- | --- |
Expand Down
Binary file modified docs/assets/agents.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/context.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/git-graph.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/task-manager.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions docs/task.md
Original file line number Diff line number Diff line change
Expand Up @@ -639,3 +639,7 @@ exist. Do not make an integration authoritative before its lifecycle events are
covered by tests. The attention UI can be prototyped earlier, but its final
behavior must use server-owned semantic status. Knowledge system depends on
context store and database schema.

## README screenshots refreshed
- [x] New screenshot.png, agents.png, context.png, task-manager.png, git-graph.png from a seeded demo (four projects, hook-driven states).
- [x] AI agents page: Extract facts, Message and the native commands merged into one *Actions* menu per row (the old buttons overflowed the table).
83 changes: 29 additions & 54 deletions shelldeck/static/agents.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,74 +179,49 @@ const COMMANDS = {}; // agent -> its native commands (/api/agent-commands)
/** The agent's own slash commands, by shelldeck action name (compact -> /compress in Gemini). */
function commandMenu(r) {
const cmds = (COMMANDS[r.agent] || []).filter((c) => !c.takes_arg);
if (!cmds.length) return "";
const opts = cmds.map((c) => `<option value="${c.action}">${esc(c.action)} (${esc(c.command)})${c.verified ? "" : " ?"}</option>`).join("");
return `<button class="btn sm" data-extract="${r.session_id}" title="Ask it to save what it learned to project memory (one short prompt)">Extract facts</button>
<button class="btn sm" data-message="${r.session_id}" title="Send a prompt (refused while it waits on a question)">Message</button>
<select class="sm" data-agent-cmd="${r.session_id}" aria-label="Run a ${esc(r.label)} command"><option value="">Command…</option>${opts}</select>`;
const opts = cmds.map((c) => `<option value="cmd:${c.action}">${esc(c.action)} (${esc(c.command)})</option>`).join("");
return `<select class="sm ag-actions" data-agent-cmd="${r.session_id}" aria-label="Actions for ${esc(r.nick || r.label)}">
<option value="">Actions…</option>
<option value="extract">Extract facts</option>
<option value="message">Message…</option>
${opts ? `<optgroup label="${esc(r.label)} commands">${opts}</optgroup>` : ""}</select>`;
}

const BUSY = { agent_blocked: "It is waiting on a question: answer that first.", agent_working: "It is busy: try when it finishes (or use sd agent cmd --force)." };

function busyToast(err, title) {
const code = Object.keys(BUSY).find((k) => String(err?.message || err).includes(k));
if (code) toast({ title, body: BUSY[code], kind: "warn" });
else toastError(err);
}

/** The row's Actions menu: extract facts, message, or one of the agent's own slash commands. */
async function onCommand(e, el) {
const sel = e.target.closest("[data-agent-cmd]");
if (!sel || !sel.value) return;
const command = sel.value;
const sid = sel.dataset.agentCmd;
const choice = sel.value;
sel.value = "";
try {
const r = await api(`/api/sessions/${sel.dataset.agentCmd}/agent-command`, { method: "POST", body: { command } });
if (choice === "extract") {
await api(`/api/sessions/${sid}/extract`, { method: "POST" });
return toast({ title: "Asked it to save its facts", body: "They appear on the Context page." });
}
if (choice === "message") {
const text = await promptDialog("Message the agent", "", { label: "Prompt", ok: "Send" });
if (!text?.trim()) return;
await api("/api/agent-prompt", { method: "POST", body: { session_id: sid, text } });
return toast({ title: "Sent" });
}
const r = await api(`/api/sessions/${sid}/agent-command`, { method: "POST", body: { command: choice.slice(4) } });
toast({ title: `Sent ${r.typed}`, body: `to ${r.agent}` });
} catch (err) {
const why = { agent_blocked: "It is waiting on a question: answer that first.", agent_working: "It is busy: wait until it finishes (or use sd agent cmd --force)." };
const code = Object.keys(why).find((k) => String(err?.message || err).includes(k));
if (code) toast({ title: "Command not sent", body: why[code], kind: "warn" });
else toastError(err);
busyToast(err, "Not sent");
}
}

async function onClick(e, el) {
if (e.target.closest("select")) return; // the command menu, not "open terminal"
const ex = e.target.closest("[data-extract]")?.dataset.extract;
if (ex) {
try {
await api(`/api/sessions/${ex}/extract`, { method: "POST" });
toast({ title: "Asked it to save its facts", body: "They appear on the Context page." });
} catch (err) {
const busy = ["agent_blocked", "agent_working"].find((k) => String(err?.message || err).includes(k));
if (busy) toast({ title: "Not sent", body: busy === "agent_blocked" ? "It is waiting on a question: answer that first." : "It is busy: try when it finishes.", kind: "warn" });
else toastError(err);
}
return;
}
const msgTo = e.target.closest("[data-message]")?.dataset.message;
if (msgTo) {
const text = await promptDialog("Message the agent", "", { label: "Prompt", ok: "Send" });
if (!text?.trim()) return;
try {
await api("/api/agent-prompt", { method: "POST", body: { session_id: msgTo, text } });
toast({ title: "Sent" });
} catch (err) {
if (String(err?.message || err).includes("agent_blocked")) toast({ title: "Not sent", body: "It is waiting on a question: answer that first.", kind: "warn" });
else toastError(err);
}
return;
}
const sid = e.target.closest("tr[data-sid]")?.dataset.sid;
if (sid) return showSession(sid);
if (e.target.closest("[data-copy-prompt]")) {
await navigator.clipboard.writeText(TEAM_PROMPT).catch(() => {});
return toast({ title: "Team prompt copied", body: "Paste it into each agent." });
}
const skill = e.target.closest("[data-skill]")?.dataset.skill;
if (skill) {
try {
const { results } = await api("/api/skills", { method: "POST", body: { agents: [skill] } });
toast({ title: "Skill installed", body: results.map((r) => r.path).join("\n") });
return renderAgents(el);
} catch (err) {
return toastError(err);
}
}
const next = e.target.closest("[data-open-next]")?.dataset.openNext;
if (next) return showSession(next);
const again = e.target.closest("[data-resume-agent]")?.dataset.resumeAgent;
if (again) {
try {
Expand Down
2 changes: 2 additions & 0 deletions shelldeck/static/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -3316,3 +3316,5 @@ body.embed .pane {
.cx-empty .cx-add { max-width: 460px; margin: 12px auto 0; }
@media (max-width: 900px) { .cx-grid { grid-template-columns: minmax(0, 1fr); } .cx-search { flex-wrap: wrap; } }
@media (prefers-reduced-motion: reduce) { .cx-actions { transition: none; } }

.ag-actions { width: auto; max-width: 170px; font-size: 12px; }