@vibest/cli 0.0.1-beta.12 → 0.0.1-beta.14

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.
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "vibest",
3
- "description": "VIBEST for Claude Code: turn-end reports and the tool guard for VIBEST sessions, and the coordinator inbox that delivers VIBEST messages as prompts, with /vibest-reattach",
3
+ "description": "VIBEST for Claude Code: turn-end reports, prompt reports and the tool guard for VIBEST sessions, and the coordinator inbox that delivers VIBEST messages as prompts, all over HTTP to vibestd",
4
4
  "author": {
5
- "name": "iamdin"
5
+ "name": "vibest-dev"
6
6
  },
7
- "repository": "https://github.com/iamdin/orchestrate-my-agent-cli",
7
+ "repository": "https://github.com/vibest-dev/vibest",
8
8
  "license": "MIT",
9
- "version": "0.0.1-beta.12"
9
+ "version": "0.0.1-beta.14"
10
10
  }
@@ -1,13 +1,31 @@
1
1
  # @vibest/claude: the vibest Claude Code plugin
2
2
 
3
- One ordinary Claude Code plugin with two parts:
4
-
5
- - **Native classic listeners** for every VIBEST session, workers and the coordinator: `classic.Stop` and
6
- `classic.StopFailure` report the turn end (a worker's result, or the coordinator's Claude session) by running
7
- `vibest integration stop --harness claude`, and `classic.PreToolUse` runs `vibest integration guard --harness claude`. These are native event names, not
8
- command-hook registrations.
9
- - **The inbox module**, for a Claude **coordinator** only: it delivers VIBEST inbox claims into the coordinator as prompts,
10
- through the native hooks API.
3
+ One ordinary Claude Code plugin, one hooks module. Every call to vibest is an HTTP request from `$.http.fetch` to
4
+ vibestd's unix socket `<VIBEST_HOME>/vibest-http.sock`; the plugin runs no `vibest` process.
5
+
6
+ - `turn.complete` posts each main-loop turn end to `/hooks/claude/turn-end` with its `reason`, the answer and the
7
+ current Claude session id. vibest maps the reason: `answer` is the result as it is; `aborted` is an interrupted
8
+ (failed) result when the person pressed Esc, and nothing when `vibest interrupt` (or remove, archive) stopped the
9
+ turn; `refusal` and `error` are failed results. A subagent's loop (`agentId` set) reports nothing. For the
10
+ coordinator vibestd records only the conversation id.
11
+ - `prompt.submit` posts a worker's prompt with its `origin.kind` to `/hooks/claude/prompt`; vibest keeps only what
12
+ the person submitted (`composer`, or `bridge` for Remote Control).
13
+ - `tool.call` posts each tool call, a subagent's included, to `/hooks/claude/guard` and returns `{ deny }` when vibest
14
+ refuses it. It tries for 2 s, then again after 100, 300 and 900 ms; when nothing answers, the call is refused.
15
+ - The **coordinator inbox**: from `session.start`, a coordinator polls `/inbox/poll` every second. A batch comes as
16
+ one short line (`<Type> Agent "<title>" completed (<id>) · +N more`) and its full text. The line is submitted with
17
+ `$.prompt.submit` from the AbovePrompt `ui.render` hook, one batch per draw, and this module's own `prompt.submit`
18
+ hook attaches the full text as context. An accepted submit is acked by row id (`/inbox/ack`) on the next tick; a
19
+ `drop` puts the batch back at the front of the queue.
20
+
21
+ Reports (turn end, prompt) retry in the background after 1, 2, 4, 8, 15 and 30 s while vibestd does not take them.
22
+
23
+ Every request carries the session headers from `@vibest/protocol` `sessionHeaders`: protocol, `VIBEST_SESSION_ID`,
24
+ `VIBEST_PROJECT_ID`, the current Claude session id, `VIBEST_AGENT`, `VIBEST_HARNESS`, the cwd, `VIBEST_RUNTIME` and the
25
+ plugin version. Paths carry no version; the only one is `PROTOCOL` in the `vibest-protocol` header. vibestd refuses a
26
+ request with an unknown session (404), a missing or wrong project id (403) or another protocol (409). A 409 body holds
27
+ vibestd's protocol and version, a message and the command to run (`action`); the plugin puts them on the status line
28
+ until a request goes through again, and the guard still refuses each tool call, giving them as the reason.
11
29
 
12
30
  It ships inside `@vibest/cli` and is loaded only into the Claude sessions vibest starts (see Use).
13
31
 
@@ -23,9 +41,8 @@ The plugin directory holds exactly:
23
41
 
24
42
  - `.claude-plugin/plugin.json`, generated: `src/manifest.json` with `version` set from this `package.json`.
25
43
  - `hooks/hooks.json`: `"modules": ["./register.mjs"]` only. No command-hook map and no shell wrapper.
26
- - `hooks/register.mjs`, generated: a single ES module with no imports. It bundles `src/plugin.ts` together with the
27
- client (`src/inbox-client.ts`) and the adapters (`src/inbox-adapter.ts`) it uses. The native `classic.*` listeners are
28
- in that module. Prebuilt JS is a delivery choice; Claude Code can also load TypeScript hooks modules.
44
+ - `hooks/register.mjs`, generated: a single ES module with no imports. It bundles `src/plugin.ts` with the header
45
+ helper it imports from `@vibest/protocol`; the build inlines the package version as `VIBEST_PLUGIN_VERSION`. Prebuilt JS is a delivery choice; Claude Code can also load TypeScript hooks modules.
29
46
  - `README.md` and `LICENSE`.
30
47
 
31
48
  The generated files are ignored by Git. `test/distribution.test.ts` packs this package and checks the extracted files.
@@ -33,109 +50,23 @@ The generated files are ignored by Git. `test/distribution.test.ts` packs this p
33
50
  ## Use
34
51
 
35
52
  Nothing to install. vibest starts each Claude session (and a Claude coordinator) with
36
- `claude --plugin-dir <@vibest/cli>/harnesses/claude`, which loads the plugin for that session only, beside the plugins
37
- the user installed. vibest writes nothing into `~/.claude`. Plain `claude` sessions never load it.
38
-
39
- **The `vibest` it calls is the one on PATH.** The module calls the bare `vibest`: `vibest inbox …` for the inbox, and
40
- `vibest integration stop --harness claude` / `vibest integration guard --harness claude` for the native listeners. There
41
- is no shell and no `VIBEST_COMMAND` override.
42
-
43
- **Mods are not sandboxed.** The inbox module is a mod, code that Claude Code runs in its own process with your permissions.
44
- Its own `$.fs` and `$.process` calls do not go through Claude's tool permission rules or `PreToolUse` hooks, and a
45
- process it starts runs outside the Bash sandbox. What it intends to do is narrow: run the fixed bare argv `vibest inbox attach|pull|ack|release …`,
46
- `vibest integration stop --harness claude` and `vibest integration guard --harness claude`, read the claim file `vibest inbox pull` names, and submit that text
47
- as a prompt. The
48
- module registers no `tool.call` interception, no `tool.check` approval, and changes no permission or policy setting.
49
- `classic.PreToolUse` is a native listener in this module. It is not the settings.json command hook.
50
-
51
- **Where it acts.** The plugin loads only into the Claude sessions vibest starts. The native listeners are always registered there.
52
- `classic.PreToolUse` calls vibest only when `VIBEST_AGENT` is set; `classic.Stop` and `classic.StopFailure` call vibest only
53
- when `VIBEST_AGENT` and `VIBEST_SESSION_ID` are both set. Elsewhere they return `next` and do not call vibest. The inbox
54
- module acts only in a process whose environment marks it as an VIBEST coordinator. That environment is what `vibest`
55
- sets up:
56
-
57
- - `VIBEST_AGENT=coordinator` and `VIBEST_SESSION_ID`;
58
- - `HERDR_PANE_ID` and `HERDR_SOCKET_PATH`;
59
- - the reported Claude session that the daemon fences on.
60
-
61
- The module always registers `session.start`, `session.end`, `command.run`, and the three `classic.*` listeners. In any other
62
- process (a worker, or a plain `claude`) they activate no receiver: the module registers no `/vibest-reattach` command,
63
- starts no timer and never calls `vibest inbox`. Setting the VIBEST
64
- variables by hand is not a substitute, because it does not create the coordinator's daemon-side identity.
65
-
66
- **Loading gate.** Claude Code statically analyzes a hooks module before loading it. Claude Code 2.1.316 loaded this
67
- revision in `claude -p` (E2E I4): `classic.PreToolUse` refused a herdr call and `classic.Stop` wrote the result. The inbox
68
- module has not been exercised in a live coordinator.
69
-
70
- - `register` stays a top-level `function` declaration. Each hook passes `$` only to the top-level `nativeHost`.
71
- - The distribution test checks that `register` is declared and exported, that `hooks.json` has no command hooks, that no
72
- shell wrapper is shipped, and that the official-type source still bundles to import-free JS.
73
-
74
- ## Prerequisites (not checked, not forced)
75
-
76
- - **Hooks modules enabled.** Claude Code must load hooks modules for non-builtin plugins. In 2.1.309 that depends on the
77
- rollout flag `tengu_plugin_hooks_modules` and on accepted workspace trust (interactive sessions). The plugin does not
78
- read or change either, and does not fake readiness when they are off. A module that does not load cannot receive
79
- messages. A bridge attachment made earlier can still leave paste delivery suppressed, because VIBEST keeps the bridge
80
- marker across receiver loss and restarts; disabling the plugin, or a module that fails to load, does not restore
81
- paste delivery automatically.
82
- - **`vibest` on PATH with the `inbox` command.** Calls are the bare argv `vibest inbox attach|pull|ack|release …`, run
83
- through `$.process.run` with the host's PATH and environment, with no shell. An `vibest` without `inbox` makes attach fail
84
- with an exit code, and the status line says so.
85
- - **This Claude session reported to VIBEST.** VIBEST learns the coordinator's Claude session from the `Stop` /
86
- `StopFailure` hook when a turn ends; there is no SessionStart report. Until then attach answers `not-reported`, and
87
- the module keeps polling with ordinary attach (see Behavior). Before the first turn ends nothing is delivered.
88
-
89
- ## Behavior
90
-
91
- **At startup** (the first `session.start`):
92
-
93
- - Registers `/vibest-reattach` as `immediate`, so it also runs mid-turn, and one poll every 2 s.
94
- - Polls never overlap, and each `vibest` call has a 15 s timeout.
95
- - The first poll runs `vibest inbox attach <session id>`, without replace.
96
- - If attach answers `not-reported` (exit 0, that error alone, no generation), nothing was attached: the status line says
97
- it is waiting, and the next poll runs the same ordinary attach again. It never adds `--replace`.
98
- - Any other refusal stops polling, and the status line says what to do:
99
- - `stale-receiver`: another receiver is attached;
100
- - a nonzero exit: `vibest` failed or has no `inbox` command;
101
- - no reply, or a reply that cannot be read or contradicts itself.
102
- - Once attached, the existing bridge marker suppresses Herdr paste delivery; the Claude adapter's `inbox` is `bridge`, so without one rows are pasted.
103
-
104
- **Each poll:**
105
-
106
- - Reads `$.session.id()` and pulls a claim.
107
- - Reads the claim body with `$.fs.read`, never from stdout, and submits it with `$.prompt.submit`.
108
- - Then settles the claim:
109
-
110
- | Submit result | Settlement |
111
- |---|---|
112
- | Accepted or queued | `ack`. This means delivery was accepted, not that an VIBEST task finished. |
113
- | Definite `drop` | `release --retry` |
114
- | Ambiguous (the submit threw) | `release` |
115
-
116
- - A lost settlement retries the same settlement and never submits again.
117
-
118
- **When the session ends** (`session.end`: `/clear`, resume, exit):
119
-
120
- - Polling stops, and the status line asks for `/vibest-reattach`.
121
- - The end is permanent for this receiver. Ordinary polling never undoes it. A session id read that was in flight when the
122
- session ended is discarded. Only a confirmed `/vibest-reattach` starts delivery again.
123
- - Callbacks still in flight from the ended session cannot settle, and cannot submit anything new.
124
-
125
- **`/vibest-reattach`:**
126
-
127
- - Runs `vibest inbox attach <current session id> --replace`. One reattach runs at a time. A `not-reported` answer here is
128
- a refusal like any other: the inbox is unchanged.
129
- - **A generation is confirmed:** it is used only if no `session.end` happened while the command waited. Polling then
130
- continues under it, even if a step of the old generation is still waiting.
131
- - **Old callbacks:** they cannot settle, pull or submit under the new generation. But a prompt the old generation had
132
- already handed to `$.prompt.submit` may still land once.
133
- - **Refusal printed by the server:** the inbox is unchanged.
134
- - **No usable answer** (timeout, nonzero exit, unparsable output): the replace may have committed and retired this
135
- receiver. It is reported as unknown and never replayed automatically. Run `/vibest-reattach` again.
136
-
137
- **Not done:** a shared store, takeover after a reload, detach, leases, or recovery after a pane move. A reloaded module
138
- is a new receiver: it gets `stale-receiver` until `/vibest-reattach`.
53
+ `claude --plugin-dir <@vibest/cli>/harnesses/claude`, which loads the plugin for that session only. vibest writes
54
+ nothing into `~/.claude`. Plain `claude` sessions never load it, and in a Claude process without `VIBEST_AGENT` and
55
+ `VIBEST_SESSION_ID` every listener returns `next` and sends nothing.
56
+
57
+ **Mods are not sandboxed.** The module is code that Claude Code runs in its own process with your permissions. What it
58
+ does is narrow: POST to the fixed vibestd socket and submit the inbox line as a prompt. Its `tool.call` listener only
59
+ refuses; it registers no `tool.check` approval and changes no permission or policy setting. A module that does not
60
+ load guards nothing: with no `--settings`, the guard rules hold only while this module runs.
61
+
62
+ **`/clear`.** Claude Code 2.1.316 changes `$.session.id()` on `/clear`, fires `session.end` for the old id and no new
63
+ `session.start`; the poll timer keeps running. The plugin therefore has no `session.end` handler and sends the
64
+ current id on every request, and vibestd records the new id on the next request.
65
+
66
+ **Loading gate.** Claude Code statically analyzes a hooks module before loading it: `register` stays a top-level
67
+ `function` declaration and each hook passes `$` only to the top-level `nativeHost`. Hooks modules must be enabled for
68
+ non-builtin plugins (in 2.1.309 the rollout flag `tengu_plugin_hooks_modules` and accepted workspace trust); the plugin
69
+ does not read or change either. The AbovePrompt drain needs an interactive UI: under `claude -p` nothing is delivered.
139
70
 
140
71
  ## API source
141
72
 
@@ -149,9 +80,9 @@ The pin is anthropics/claude-code `2eff7a8d21c80be48904f62ebdea36d945d7b504`, `m
149
80
  under Anthropic's commercial terms. This repository does not assert permission to redistribute it, and a missing or
150
81
  unverified cache fails typecheck instead of skipping the plugin project. The cache was not produced by running Claude or `/plugin-types`.
151
82
 
152
- The listeners are `classic.Stop`, `classic.StopFailure`, `classic.PreToolUse`, `session.start`, `session.end` and
153
- `command.run`. Native calls stay in `register` or the top-level `nativeHost`: `$.process.run`, `$.session.cwd`,
154
- `$.session.id`, `$.env.get`, `$.fs.read`, `$.prompt.submit`, `$.command.register`, `$.clock.every`, `$.ui.status`.
83
+ The listeners are `session.start`, `ui.render` (AbovePrompt), `turn.complete`, `prompt.submit` and `tool.call`. Native
84
+ calls stay in `register` or the top-level `nativeHost`: `$.http.fetch`, `$.session.cwd`, `$.session.id`, `$.env.get`,
85
+ `$.prompt.submit`, `$.clock.every`, `$.clock.after`, `$.ui.invalidate`, `$.ui.status`.
155
86
 
156
87
  Hooks modules are early access and may change between releases. `claude plugin validate` and `claude plugin test` have
157
88
  not been run on this revision. The E2E check I4 loads it with `--plugin-dir` into a real Claude: the guard refuses and the
@@ -1,6 +1,4 @@
1
1
  {
2
2
  "description": "VIBEST: turn-end reports and the tool guard for VIBEST sessions; the coordinator inbox module",
3
- "modules": [
4
- "./register.mjs"
5
- ]
3
+ "modules": ["./register.mjs"]
6
4
  }