@bondsmith/bondsmithd 0.1.14 → 0.1.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +43 -15
- package/dist/index.js +557 -243
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -82,20 +82,20 @@ that pane belongs to:
|
|
|
82
82
|
tmux set-option -t "$TMUX_PANE" -q @bondsmith-agent-state "waiting:$(date +%s)"
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
-
The value is `<state>:<epoch seconds>`, where state is `working`, `waiting` (needs the user) or `done
|
|
85
|
+
The value is `<state>:<epoch seconds>`, where state is `working`, `waiting` (needs the user) or `done` (finished a turn, shown until the user attaches, types or resizes after it).
|
|
86
86
|
The daemon reads it on its 5-second tick and shows it on the session. Anything else is ignored, as is
|
|
87
87
|
a report dated in the future. A `waiting` or `done` report is dropped once the pane writes output more
|
|
88
88
|
than 2 seconds after it, since that means the agent moved on. A `working` report is dropped once the
|
|
89
89
|
pane has been silent for 2 minutes, since an interrupted or crashed agent never reports again.
|
|
90
90
|
|
|
91
91
|
Claude Code sessions that Bondsmith starts as plain `claude` report this on their own (see the end of the
|
|
92
|
-
plan section below): `working` when a prompt is sent, `waiting` when it asks for permission
|
|
93
|
-
|
|
92
|
+
plan section below): `working` when a prompt is sent, `waiting` when it asks for permission or fails with
|
|
93
|
+
an API error, `done` when it finishes a turn. Nothing needs installing for those.
|
|
94
94
|
|
|
95
95
|
For an agent the daemon does not set up (a wrapper, `npx claude`, another agent), note that every session
|
|
96
96
|
Bondsmith starts has `BONDSMITH_SESSION` set to its id, so a hook installed once for all your projects can
|
|
97
97
|
stay silent everywhere else. This entry in `~/.claude/settings.json` reports a Claude Code session as
|
|
98
|
-
waiting the moment it asks for permission
|
|
98
|
+
waiting the moment it asks for permission, and as done when it finishes a turn:
|
|
99
99
|
|
|
100
100
|
```json
|
|
101
101
|
{
|
|
@@ -116,7 +116,7 @@ waiting the moment it asks for permission or finishes a turn:
|
|
|
116
116
|
"hooks": [
|
|
117
117
|
{
|
|
118
118
|
"type": "command",
|
|
119
|
-
"command": "[ -n \"$BONDSMITH_SESSION\" ] && tmux set-option -t \"$TMUX_PANE\" -q @bondsmith-agent-state \"
|
|
119
|
+
"command": "[ -n \"$BONDSMITH_SESSION\" ] && tmux set-option -t \"$TMUX_PANE\" -q @bondsmith-agent-state \"done:$(date +%s)\"; exit 0"
|
|
120
120
|
}
|
|
121
121
|
]
|
|
122
122
|
}
|
|
@@ -127,7 +127,7 @@ waiting the moment it asks for permission or finishes a turn:
|
|
|
127
127
|
|
|
128
128
|
This is optional, and nothing edits your settings for you. The command does nothing outside a Bondsmith
|
|
129
129
|
session, and sessions started before the daemon set the variable are skipped by it. It reports only
|
|
130
|
-
`waiting`. A `working` report is dropped after the pane has been silent for 2 minutes, so one that an
|
|
130
|
+
`waiting` and `done`. A `working` report is dropped after the pane has been silent for 2 minutes, so one that an
|
|
131
131
|
interrupted Claude Code never clears (it does not run `Stop` then, and has no hook for Escape) expires on
|
|
132
132
|
its own.
|
|
133
133
|
|
|
@@ -143,24 +143,25 @@ A hook can store the plan outside the repository instead, in `~/.bondsmith/plans
|
|
|
143
143
|
option, so a plan written there is never left over from an earlier session.
|
|
144
144
|
|
|
145
145
|
For Claude Code the daemon sets this up itself. When a session's command is `claude` (that word alone, not
|
|
146
|
-
behind `npx
|
|
146
|
+
behind `npx` or a wrapper; `VAR=value` words before it are fine), the daemon starts it as
|
|
147
147
|
`claude --settings ~/.bondsmith/hooks/claude-settings.json …`. That file adds hooks to the ones you
|
|
148
|
-
already have:
|
|
149
|
-
|
|
148
|
+
already have: one stores the plan as above as soon as plan mode proposes it, before you approve it;
|
|
149
|
+
another logs the agent's task calls (`TaskCreate`, `TaskUpdate`, `TodoWrite`) to `~/.bondsmith/plans/<session id>.tasks.jsonl`,
|
|
150
|
+
which the daemon replays into the session's task list (shown under the plan in the browser); and four
|
|
151
|
+
report the agent state (`working` on a prompt; `waiting` on a permission request, the end of a turn, or a turn that fails with
|
|
150
152
|
an API error). Nothing in `~/.claude` changes, the session still shows the command you typed, and the hooks
|
|
151
153
|
do nothing outside a Bondsmith session. Claude Code's `/hooks` menu does not list hooks passed with
|
|
152
154
|
`--settings`, though they run.
|
|
153
155
|
|
|
154
|
-
A fifth hook
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
the hook, so it does too. The prompt is stored as typed, so a secret in a prompt is in the headline.
|
|
156
|
+
A fifth hook watches Bash calls for `gh pr create`. When one succeeds and prints a pull request URL, the URL is
|
|
157
|
+
appended to the tmux option `@bondsmith-prs` (space separated, each once, the newest 20 kept), and the daemon
|
|
158
|
+
reports it on the session as `pullRequestUrls`. It matches `gh pr create` only as a command of its own, so
|
|
159
|
+
`echo "gh pr create"` or `gh pr view` record nothing, and a failed command never reaches it.
|
|
159
160
|
|
|
160
161
|
The daemon leaves the command alone if it already has `--settings`, if the installed `claude` does not list
|
|
161
162
|
`--settings` in `claude --help` (asked once per daemon run; if `claude` cannot be run at all, that is logged
|
|
162
163
|
and asked again after a minute), or if `BONDSMITH_AGENT_HOOKS` is set to `off`, `0`, `false` or `no` where
|
|
163
|
-
the daemon starts. Each hook has a timeout (5 seconds for a state report
|
|
164
|
+
the daemon starts. Each hook has a timeout (5 seconds for a state report, 10 for the plan and the task list), so a stuck command
|
|
164
165
|
cannot hold up the agent. Plans are written to `~/.bondsmith/plans` readable only by you, and a symlink in
|
|
165
166
|
the way is replaced, not followed. A plan the agent changes later without going back through plan mode is
|
|
166
167
|
not seen; the hook's plan keeps winning over the folder's file until the next approval.
|
|
@@ -204,6 +205,33 @@ tmux only flags a bell when no client is attached to the session or the bell is
|
|
|
204
205
|
the one the attached client has open. A session whose terminal is open in a browser tab, even a hidden
|
|
205
206
|
one, counts as being looked at, so a bell in it is not flagged; use the hook report for that case.
|
|
206
207
|
|
|
208
|
+
## Adding an agent
|
|
209
|
+
|
|
210
|
+
The daemon splits what is the same for every agent from what is one agent's own.
|
|
211
|
+
|
|
212
|
+
| Part | Where | Agent-specific? |
|
|
213
|
+
| ----------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | ----------------- |
|
|
214
|
+
| What an agent reports: state, plan, task list, pull requests (the channels below) | `src/sessions/agent-reports/` | No |
|
|
215
|
+
| Turning reports into what the UI shows (`readSessionReport`: the plan and the task list for `getPlan`; attention state) | `agent-reports/`, `tmux/agent-state.ts` | No |
|
|
216
|
+
| Recognising an agent's command and launching it so it reports | `src/sessions/agents/<agent>/` | Yes |
|
|
217
|
+
| The list of agents | `AGENT_IDS` in `@bondsmith/local-agent-protocol`; `agents/registry.ts` | Add one line each |
|
|
218
|
+
|
|
219
|
+
An agent reports through these channels, and the daemon reads them without caring who wrote them:
|
|
220
|
+
|
|
221
|
+
| Report | Channel |
|
|
222
|
+
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
223
|
+
| State | tmux option `@bondsmith-agent-state` = `<working\|waiting\|done>:<epoch seconds>` on the session's pane; or ring the bell; or nothing (a pane gone quiet counts as waiting) |
|
|
224
|
+
| Plan | `~/.bondsmith/plans/<session id>.md`, or `.bondsmith/plan.md` in the session's folder, or tmux option `@bondsmith-plan` |
|
|
225
|
+
| Task list | `~/.bondsmith/plans/<session id>.tasks.jsonl`: one JSON `TaskEvent` per line, appended (`add`, `update`, `remove`, `replace`; see `agent-reports/task-list.ts`) |
|
|
226
|
+
| Pull requests | tmux option `@bondsmith-prs`, space-separated URLs |
|
|
227
|
+
|
|
228
|
+
To add an agent: add its id to `AGENT_IDS`, which makes `registry.ts` refuse to compile until it has an adapter. A new
|
|
229
|
+
`AgentAdapter` needs `matches(command)` and `prepareCommand(command)`. With nothing to set up use `plainAdapter(id)`,
|
|
230
|
+
as Codex and opencode do today (they report through the bell and the quiet-pane check). With hooks, put the agent's
|
|
231
|
+
settings and payload mapping in `agents/<agent>/` and build its hook commands from the helpers in
|
|
232
|
+
`agent-reports/hook-commands.ts` and `agent-reports/hook-scripts.ts`; the agent's file only says where in its
|
|
233
|
+
payload the plan, the task event and the shell command are. `agents/claude/` is the worked example.
|
|
234
|
+
|
|
207
235
|
## Production connectivity (current status)
|
|
208
236
|
|
|
209
237
|
`bondsmithd` connects outbound to the Bondsmith relay by default (`BONDSMITH_RELAY_ENABLED=true`,
|