grok-bot-cli 0.3.0 → 0.4.0

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.
Files changed (38) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/README.md +54 -22
  3. package/dist/.agents/plugins/marketplace.json +1 -0
  4. package/dist/.claude-plugin/marketplace.json +1 -0
  5. package/dist/.claude-plugin/plugin.json +1 -0
  6. package/dist/.codex-plugin/mcp.json +1 -0
  7. package/dist/.codex-plugin/plugin.json +1 -0
  8. package/dist/.cursor-plugin/marketplace.json +1 -0
  9. package/dist/.cursor-plugin/mcp.json +1 -0
  10. package/dist/.cursor-plugin/plugin.json +1 -0
  11. package/dist/.mcp.json +1 -0
  12. package/dist/INSTALL.md +269 -0
  13. package/dist/LICENSE +21 -0
  14. package/dist/README.md +173 -0
  15. package/dist/agent-bundle.compile-evidence.json +1 -0
  16. package/dist/agent-bundle.manifest.json +1 -0
  17. package/dist/agent-bundle.package-compile-evidence.json +1 -0
  18. package/dist/bin/gbot-flight.mjs +29162 -0
  19. package/dist/bin/gbot-install.js +135699 -0
  20. package/dist/bin/gbot.mjs +87242 -0
  21. package/dist/install.mjs +1322 -0
  22. package/dist/mcp/mcp-grok-bot-b8c2461e-flight.mjs +26413 -0
  23. package/dist/mcp/mcp-grok-bot-b8c2461e.mjs +107760 -0
  24. package/dist/mcp.json +1 -0
  25. package/dist/package.json +60 -0
  26. package/dist/plugin.json +1 -0
  27. package/dist/skills/talk-to-grok-bot/SKILL.md +37 -0
  28. package/package.json +30 -10
  29. package/src/app-session.js +0 -249
  30. package/src/cli.js +0 -548
  31. package/src/codex-bridge.js +0 -480
  32. package/src/commands.js +0 -52
  33. package/src/gateway.js +0 -361
  34. package/src/headers.js +0 -53
  35. package/src/history.js +0 -83
  36. package/src/store.js +0 -358
  37. package/src/transcript.js +0 -50
  38. package/src/url-policy.js +0 -161
package/CHANGELOG.md ADDED
@@ -0,0 +1,59 @@
1
+ # grok-bot-cli
2
+
3
+ ## 0.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 1dc6d34: Ship `gbot` as one generated Agent Bundle CLI at the package root and add `gbot-install install|uninstall <cursor|codex|claude>` / `gbot-install doctor` for the bundled `grok-bot` MCP tools and `talk-to-grok-bot` skill; delete the nested `plugin/` project and the hand-written dispatcher. Breaking (pre-1.0): Node.js 22.19.0 or newer is required; options are command-local (`gbot send --history-dir DIR …`, no leading globals); `--json` is reserved anywhere before `--`, so put `--` before flag-like message text; `send` and every `codex` command write one JSON document to stdout with `exitCode` (failures keep `error`, `delivery`, `reason`, `mode` and exit 1), other commands print failures on stderr and exit 1; argument and schema errors exit 2; `--instructions` is gone (use `--description`) and `--notify`/`--hidden` take `on|off` only; `chat` records history rows as `event: "thread"`; the installed bundle is named `gbot` (uninstall an earlier source-built `grok-bot` plugin first). (#50)
8
+
9
+ ### Patch Changes
10
+
11
+ - 4b3cd78: Make `gbot codex` dependable for automation and safe for agent relays: `codex status --json` reports `socketState`, a stable failure `mode` (`socket-absent`, `permission-denied`, `not-a-socket`, `connect-failed`, `handshake-failed`, `bad-response`, `windows-unsupported`), `schema.compatibility` separate from reachability, a bounded `codex --version` probe (`cliVersionProbe`), and `desktopAttached: "unknown"`; `codex list-threads` adds `--cursor`, bounds `--limit` to 1–200, rejects unknown arguments, validates the response shape, and strips terminal controls from every text field in JSON too. `codex send` and `send` accept `--correlation-id`, `--reply-to`, `--hop`, and `--envelope`, return receipts with `messageId` (sent as Codex's `clientUserMessageId`), `correlationId`, `replyTo`, `hop`, and `maxHops`, refuse relays at `GROK_BOT_MAX_HOPS` (default 4) with `reason: "hop-limit"`, honor the operator allowlist `GROK_BOT_CODEX_THREADS`, refuse `active` threads with `reason: "busy"` instead of steering a running turn (or, with `--when-busy queue` and `GROK_BOT_CODEX_EXPERIMENTAL=1`, hand them to Codex's experimental `thread/queue/add` and report `delivery: "queued"`; `codex queue <threadId>` lists that queue), and emit `reason`/`mode` in every `--json` send failure. Fixes #37, #38, #39.
12
+ - bf64783: Add `gbot thread --after ID` for exclusive client-side filtering of the bounded gateway tail, including no-op cursors and explicit gap-reset snapshots.
13
+
14
+ ## 0.3.1
15
+
16
+ ### Patch Changes
17
+
18
+ - HOLD-fix follow-up for the P1 bridge work: gateway reads count true bytes through a streaming reader that cancels on overflow; Codex transport uses an absolute handshake deadline, caps terminated headers and complete frames before decoding, guarantees socket destruction on close, and routes malformed RPC through failure handling; CLI `--json` failures emit structured errors with delivery and IDs; sends stay `unknown` without a confirmed receipt; MCP full reads add aggregate budgets with truncation metadata and a CLI continuation path.
19
+
20
+ ## 0.3.0
21
+
22
+ ### Minor Changes
23
+
24
+ - 82badce: Add `gbot codex status`, `gbot codex list-threads [--limit N]`, and `gbot codex send <threadId> <message...>`: attach to the local Codex app-server daemon socket (`$CODEX_HOME/app-server-control/app-server-control.sock`) with a built-in WebSocket client, list threads, and start a turn with documented JSON-RPC (`thread/resume` + `turn/start`). Reports an absent socket (no daemon or ChatGPT Desktop private mode), unknown threads, threads owned by another client, and refuses server approval requests instead of approving them. Method names are pinned to Codex 0.154.0.
25
+
26
+ ### Patch Changes
27
+
28
+ - 93cb28e: Parse global `gbot` flags only before the command so `gbot codex send` keeps `--json` / `--dir` inside the message; refuse native Windows for `gbot codex` with a clear error; strip terminal controls from thread listings; run unit tests through `scripts/run-unit-tests.mjs` so Windows and Node 18 work without shell globs.
29
+ - ef6ce79: Send the gateway bearer only to `https` hosts on `*.cursor.sh`, `*.cursor.com`, or `*.cursorvm.com`, and the EnsureSandBox / Cursor access token only to `*.cursor.sh` / `*.cursor.com`; refuse cross-origin fetch redirects; redact Authorization (any scheme), Cookie, and named token fields from error output. `GROK_BOT_ALLOW_LOCAL_GATEWAY=1` admits loopback gateways and `GROK_BOT_ALLOW_ANY_GATEWAY=1` disables the host check; both warn once on stderr.
30
+ - d59fa95: Add opt-in local JSONL thread history (`GROK_BOT_HISTORY=on`) with offline `gbot history` search.
31
+ - a7415d7: P1 bridge follow-ups: preserve send receipts with rejected/accepted/unknown delivery states (Codex `CodexSendError` keeps thread/turn IDs, gateway `sendPrompt` returns `delivery` + `messageId` and marks post-write loss unknown); bound the Codex WebSocket transport (idempotent close settling pending requests, socket destroy on every failure, exact handshake validation, fragmentation/UTF-8/opcode handling, header/frame/message/buffer budgets); make `gbot_thread` bounded without losing replies (truncation metadata, `full` bounded full-read in tool and `--full` in CLI, safe string normalization, 1–200 limit consistency, gateway deadline and response-byte cap).
32
+ - 9b034ce: Validate group membership in gateway mode before sending mutations: deduplicate member references, enforce one to six bot members, reject nested groups, and reject bots as group targets.
33
+ - ab70a00: Strip C0/C1 controls (including CR, backspace, and BEL) from `gbot codex list-threads` text output, not only ESC sequences.
34
+ - 93cb28e: Fix `gbot thread` so bot replies (`send-message` entries) show their text instead of empty lines, by sharing transcript parsing with the grok-bot plugin.
35
+ - 3fe1287: Use the signed-in Grok Bot app session on Windows (`%APPDATA%\\Grok Bot`, DPAPI Safe Storage).
36
+
37
+ ## 0.2.3
38
+
39
+ ### Patch Changes
40
+
41
+ - 5519136: Use the signed-in Grok Bot app session on Linux: read `~/.config/Grok Bot/gateway-descriptor.json` (honouring `XDG_CONFIG_HOME`), decrypt Chromium `v11` payloads with the Secret Service password via `secret-tool` and `v10` payloads with the basic-text key, and apply Linux's single PBKDF2 round instead of the macOS 1003.
42
+
43
+ ## 0.2.2
44
+
45
+ ### Patch Changes
46
+
47
+ - ce452cd: Support version 2 Grok Bot gateway descriptors and report unusable app sessions clearly in `gbot doctor`.
48
+
49
+ ## 0.2.1
50
+
51
+ ### Patch Changes
52
+
53
+ - 13f6858: Remove redundant group-member normalization branches.
54
+
55
+ ## 0.2.0
56
+
57
+ ### Minor Changes
58
+
59
+ - 9691ea3: Add complete bot and group profile creation and update fields, including instructions, titles, avatar shape and color, notifications, and sidebar visibility.
package/README.md CHANGED
@@ -14,7 +14,7 @@ Manage [Grok Bot](https://cursor.com/help/grok-bot/plans) agents, groups, and me
14
14
  npm install --global grok-bot-cli
15
15
  ```
16
16
 
17
- Requires Node.js 18+ and the Grok Bot desktop app on macOS, Linux, or Windows. Open Grok Bot and sign in once; `gbot` automatically uses the app's encrypted session and routing credentials. No token copying is required. On Linux the app keeps its session under `~/.config/Grok Bot` (or `$XDG_CONFIG_HOME`); when it is stored in the system keyring, `gbot` reads the key with `secret-tool` (package `libsecret-tools`). On Windows the session lives under `%APPDATA%\\Grok Bot` and decrypts with the app's DPAPI-wrapped Safe Storage key.
17
+ Requires Node.js 22.19.0+ and the Grok Bot desktop app on macOS, Linux, or Windows. Open Grok Bot and sign in once; `gbot` automatically uses the app's encrypted session and routing credentials. No token copying is required. On Linux the app keeps its session under `~/.config/Grok Bot` (or `$XDG_CONFIG_HOME`); when it is stored in the system keyring, `gbot` reads the key with `secret-tool` (package `libsecret-tools`). On Windows the session lives under `%APPDATA%\\Grok Bot` and decrypts with the app's DPAPI-wrapped Safe Storage key.
18
18
 
19
19
  ## Use
20
20
 
@@ -28,14 +28,25 @@ gbot groups update Launch --title "Launch room" --hidden off
28
28
  gbot send Researcher "Summarize the launch status."
29
29
  gbot send Launch "Share your updates."
30
30
  gbot thread Researcher
31
+ gbot thread Researcher --after <last-entry-id> --json
31
32
  gbot groups delete Launch
32
33
  gbot bots delete Researcher
33
34
  gbot bots delete Writer
34
35
  ```
35
36
 
36
- `update` fields: `--name` `--description`/`--instructions` `--title` `--avatar-shape` `--avatar-color` `--notify` `--hidden`. `--description` is the UI Instructions field.
37
+ `update` fields: `--name` `--description` `--title` `--avatar-shape` `--avatar-color` `--notify on|off` `--hidden on|off`. `--description` is the UI Instructions field.
38
+
39
+ `gbot thread --after ID` filters the bounded tail locally and returns entries strictly
40
+ after that opaque entry ID. Its JSON includes `cursor`, `entryCount`, and `gapReset`.
41
+ An unchanged poll has `entryCount: 0`; an unknown or expired ID returns one bounded
42
+ snapshot with `gapReset: true`. The gateway request remains limit-only.
37
43
 
38
44
  Run `gbot --help` for every command.
45
+ Options are command-local (for example, `gbot send --history-dir DIR ...`);
46
+ the former leading-global form is no longer accepted. `--json` prints the
47
+ canonical JSON result; `send` and the `codex` commands also report failures as
48
+ a JSON document on stdout with `exitCode` (see below), every other command
49
+ prints the failure message on stderr and exits 1.
39
50
 
40
51
  ## Gateway URL policy
41
52
 
@@ -62,42 +73,63 @@ gbot codex send <threadId> "Grok here: the build is green, please continue."
62
73
 
63
74
  `send` resumes the thread, starts a turn with your text, prints the turn id, and returns; Codex keeps working after `gbot` disconnects. Every command accepts `--json`.
64
75
 
65
- **Which Codex you reach.** `gbot` connects to `$CODEX_HOME/app-server-control/app-server-control.sock` (default `~/.codex/...`) with a built-in WebSocket client. The daemon must be started by `codex app-server daemon start`. `list-threads` shows the threads recorded under `CODEX_HOME` (CLI, TUI, VS Code); `send` works on any of them that no other client currently holds open. Method and parameter names are pinned to the Codex release recorded in `src/codex-bridge.js` (`codex app-server generate-json-schema`); `status` prints the daemon and CLI versions so a stale daemon is visible, and `codex app-server daemon restart` picks up the installed CLI. Native Windows is not supported yet (AF_UNIX control socket); use WSL, Linux, or macOS.
76
+ **Which Codex you reach.** `gbot` connects to `$CODEX_HOME/app-server-control/app-server-control.sock` (default `~/.codex/...`) with a built-in WebSocket client. The daemon must be started by `codex app-server daemon start`. `list-threads` shows the threads recorded under `CODEX_HOME` (CLI, TUI, VS Code); `send` works on any of them that no other client currently holds open. Method and parameter names are pinned to the Codex release recorded in `src/core/codex-bridge.js` (`codex app-server generate-json-schema`); `status` prints the daemon and CLI versions so a stale daemon is visible, and `codex app-server daemon restart` picks up the installed CLI. Native Windows is not supported yet (AF_UNIX control socket); use WSL, Linux, or macOS.
66
77
 
67
78
  **ChatGPT Desktop limitation.** Desktop runs its own private stdio app-server and does not publish the shared control socket, so external clients cannot reach live Desktop tasks. When the socket is absent, `gbot codex status` exits 1 and says so, naming the upstream issues: [openai/codex#41014](https://github.com/openai/codex/issues/41014) and [openai/codex#41112](https://github.com/openai/codex/issues/41112). `gbot` never reads Desktop's temporary `CODEX_APP_TOOLS_PIPE_PATH` sockets under `/tmp/codex-browser-use/`; that channel is private to Desktop.
68
79
 
69
- **Failure modes.**
80
+ **Status contract (`gbot codex status --json`).** `reachable` is endpoint reachability only. `socketState` is `socket`, `absent`, `permission-denied`, or `not-a-socket`; `mode` is `daemon` for a usable daemon, otherwise the failure: `socket-absent`, `permission-denied` (the file or the connect refused this user), `not-a-socket`, `connect-failed` (socket present, nothing completed the WebSocket upgrade), `handshake-failed` (upgrade or `initialize` failed), `windows-unsupported`, or `bad-response` (reachable, but `initialize` returned something off-schema — `reachable` stays `true`). `schema.compatibility` is `exact` when the daemon reports the pinned version, `unverified` when it differs (methods usually survive upgrades, but the shapes are not re-checked), or `unknown`. `cliVersionProbe` reports whether `codex --version` answered (`ok`, `missing`, `timeout` after 3 s, `error`). Whether ChatGPT Desktop owns a thread is not observable from the socket, so `desktopAttached` is always `"unknown"`. The document is always written to stdout and includes `exitCode`; it is `0` only for a usable daemon.
81
+
82
+ **Thread discovery.** `list-threads --limit N` (1–200) pages with the opaque `--cursor` from the previous `nextCursor`; JSON keeps the cursor verbatim, text output prints a sanitized `more: --cursor …` hint. Text fields are stripped of terminal control sequences in both outputs (single-line fields also lose line breaks; `preview` keeps its newlines; a structured `source` such as `{ "custom": … }` passes through unchanged), `status` is one of `notLoaded | idle | active | systemError | unknown`, and non-numeric `updatedAt` becomes `null`. Unknown arguments are rejected before the socket is touched; a response that does not match the pinned schema (including an entry without a string `id`) fails with `reason: "bad-response"`.
83
+
84
+ **Routes, attribution, and loops.** `gbot codex send` runs on the machine that owns `CODEX_HOME`, as the user who owns the socket, with that user's Codex credentials; the socket path comes only from `CODEX_HOME`, never from the message or an agent-supplied argument. A cloud-hosted Grok Bot cannot reach a desktop socket directly — run `gbot` locally (for example from a Codex skill or an agent on that machine). `GROK_BOT_CODEX_THREADS=id,id` lets the operator pin `send` to approved threads (`reason: "route-not-allowed"` otherwise). Every send gets a delivery envelope: `messageId` (also sent as Codex's native `clientUserMessageId`), `correlationId` (defaults to the message id), optional `replyTo`, and `hop`. A reply passes the original correlation id and `hop` + 1:
85
+
86
+ ```sh
87
+ gbot codex send <threadId> "Grok here: build is green" # receipt: messageId M, correlationId M, hop 0
88
+ gbot codex send --correlation-id M --reply-to M --hop 1 <threadId> "ack" # the answer, one hop later
89
+ ```
90
+
91
+ Sends at `hop >= GROK_BOT_MAX_HOPS` (default 4) are refused with `reason: "hop-limit"` before anything reaches the daemon, so two agents cannot acknowledge each other forever; `gbot` never auto-acknowledges. `--envelope` (implied by any envelope flag) prepends a one-line `[gbot msg=… corr=… reply-to=… hop=… from=user@host]` header so the receiving agent can quote the ids back. That header is caller-authored provenance for the reader, not authentication: the daemon authenticates the local user through the socket, nothing else. Private ChatGPT Desktop pipes and arbitrary ChatGPT chats stay out of scope; only Codex threads on a reachable app-server daemon are routes.
92
+
93
+ **Busy threads.** `send` reads the thread status on resume. Only `idle` and `notLoaded` threads start a turn. An `active` thread (a turn in progress, or waiting on approval / user input) is refused with `reason: "busy"`: in app-server 0.154.0 a `turn/start` on an active thread steers that turn rather than queueing behind it, and `gbot` never steers or interrupts work a human may be doing. Either wait for `list-threads` to show `idle` and resend, or pass `--when-busy queue` to hand the message to the daemon's own queue through Codex's experimental `thread/queue/add` — that needs `GROK_BOT_CODEX_EXPERIMENTAL=1`, returns `delivery: "queued"` with `queuedSubmissionId`, and `gbot codex queue <threadId>` shows what is still waiting. `systemError` threads are refused with `reason: "thread-error"`, statuses this version does not know with `reason: "unknown-status"`. Receipts distinguish `delivery: "accepted"` (turn started; `turnId`, `turnStatus`), `"queued"`, `"rejected"` (nothing was sent; see `reason`), and `"unknown"` (the request left but no acknowledgment came back — look for `messageId` in the thread or queue before resending). The decision record, with the schema evidence and a live probe of the queue API, is in [`docs/codex-busy-threads.md`](docs/codex-busy-threads.md).
70
94
 
71
- - Socket absent: no daemon, or Desktop-private mode. Start the daemon or wait for the upstream fixes.
72
- - Unknown thread: `send` fails with "Unknown Codex thread"; use `list-threads`.
73
- - Thread open elsewhere: a thread with an active writer (VS Code, TUI) fails with "open in another client"; close it there first.
74
- - Approvals: `gbot` never approves commands or file changes on your behalf. If Codex asks while `gbot` is still connected, `send` refuses the request, exits 1, and tells you the turn id. `send` disconnects as soon as the turn starts, so later approval requests stay with the daemon for a Codex client to answer; for unattended sends set `approval_policy = "never"` in the daemon's `config.toml`.
95
+ **Failure modes.** Every `send` and `codex` outcome under `--json` is one document on stdout with `exitCode`; failures include `{ error, delivery, reason, messageId, correlationId, hop, exitCode: 1, … }` and the process exits 1. Framework argument/schema errors remain on stderr and exit 2. `--json` is reserved anywhere before `--`; put `--` before flag-like message text. `reason` values are stable:
96
+
97
+ - `socket-absent` / `permission-denied` / `not-a-socket` / `connect-failed` / `handshake-failed` / `windows-unsupported`: the route is unavailable. Start the daemon, fix the socket, or wait for the upstream Desktop fixes.
98
+ - `unknown-thread`: use `list-threads`.
99
+ - `external-owner`: a thread with an active writer (VS Code, TUI) is open in another client; close it there first.
100
+ - `busy` / `thread-error` / `unknown-status`: see above.
101
+ - `route-not-allowed` / `hop-limit` / `experimental-disabled`: refused by operator policy, the relay bound, or the experimental-API gate.
102
+ - `unsupported`: the daemon does not offer the (experimental) method `--when-busy queue` needs.
103
+ - `approval-refused` (`delivery: "accepted"`): `gbot` never approves commands or file changes on your behalf. If Codex asks while `gbot` is still connected, `send` refuses the request, exits 1, and tells you the turn id. `send` disconnects as soon as the turn starts, so later approval requests stay with the daemon for a Codex client to answer; for unattended sends set `approval_policy = "never"` in the daemon's `config.toml`.
104
+ - `transport` / `bad-response` (`delivery: "unknown"`): the connection dropped or the daemon answered off-schema after the request left.
75
105
 
76
106
  ## Talking to Grok Bot from Codex
77
107
 
78
- `plugin/` is an [Agent Bundle](https://scriptedalchemy.github.io/agent-bundle/) plugin
108
+ The npm package is also an [Agent Bundle](https://scriptedalchemy.github.io/agent-bundle/) plugin
79
109
  that gives Codex, Claude Code, and Cursor two MCP tools on a `grok-bot` server,
80
110
  `gbot_send` and `gbot_thread`, plus a `talk-to-grok-bot` skill that tells the agent
81
111
  when to ping a bot and how to word the message. The tools bundle this repository's
82
112
  gateway client, so the installed plugin does not need `gbot` on `PATH`.
83
113
 
84
- The plugin is not part of the npm package. From a clone of this repository, build
85
- the artifact once, then install it into each host you use:
114
+ Install the bundled host projections from the same npm package:
86
115
 
87
116
  ```sh
88
- git clone https://github.com/ScriptedAlchemy/grok-bot-cli.git
89
- cd grok-bot-cli/plugin
90
- npm install
91
- npm run build
92
- npx agent-bundle install codex --from artifact
93
- npx agent-bundle install claude --from artifact
94
- npx agent-bundle install cursor --from artifact
95
- npx agent-bundle doctor --from artifact
117
+ gbot-install install codex
118
+ gbot-install install claude
119
+ gbot-install install cursor
120
+ gbot-install doctor
96
121
  ```
97
122
 
98
- Add `--replace` to an install command to overwrite an earlier copy. `npm run check`
99
- runs the plugin gates: source validation, build, artifact validation, typecheck, and
100
- the route-unit tests, which drive both tools against a loopback fake gateway.
123
+ Add `--replace` to an install command to overwrite an earlier copy. The bundle is
124
+ registered as `gbot`; if you installed the pre-0.4 `grok-bot` plugin from a source
125
+ checkout, uninstall it first so the two do not both register the `grok-bot` server.
126
+
127
+ `gbot_thread` returns a small receipt by default: deterministic `summary`, opaque
128
+ `cursor`, `entryCount`, and `gapReset`.
129
+ Pass the cursor back as `after` for an exclusive client-side delta. Pass `full:true`
130
+ only when bounded entry bodies are needed in structured content; `Agent.Text` remains
131
+ the short summary. Unknown cursors set `gapReset: true`; repeat that call with
132
+ `full:true` to inspect the bounded reset snapshot.
101
133
 
102
134
  Auth resolves exactly as for `gbot`: `GROK_BOT_GATEWAY_URL` + `GROK_BOT_GATEWAY_TOKEN`,
103
135
  then the Grok Bot app session, then `CURSOR_ACCESS_TOKEN`. The MCP server therefore
@@ -0,0 +1 @@
1
+ {"interface":{"displayName":"gbot"},"name":"gbot-marketplace","plugins":[{"category":"Productivity","name":"gbot","policy":{"authentication":"ON_INSTALL","installation":"AVAILABLE"},"source":{"path":"./","source":"local"}}]}
@@ -0,0 +1 @@
1
+ {"description":"Message Grok Bot bots and groups and read their threads from Codex, Claude Code, and Cursor.","name":"gbot-marketplace","owner":{"name":"gbot"},"plugins":[{"author":{"name":"Zack Jackson","url":"https://github.com/ScriptedAlchemy"},"description":"Message Grok Bot bots and groups and read their threads from Codex, Claude Code, and Cursor.","homepage":"https://github.com/ScriptedAlchemy/grok-bot-cli#readme","keywords":["grok","grok-bot","grokbot","gbot","cursor","ai-agents","automation","terminal","cli","agent-bundle"],"license":"MIT","name":"gbot","repository":"https://github.com/ScriptedAlchemy/grok-bot-cli","source":"./","version":"0.4.0"}]}
@@ -0,0 +1 @@
1
+ {"author":{"name":"gbot"},"description":"Message Grok Bot bots and groups and read their threads from Codex, Claude Code, and Cursor.","name":"gbot","version":"0.4.0"}
@@ -0,0 +1 @@
1
+ {"mcpServers":{"grok-bot":{"args":["./mcp/mcp-grok-bot-b8c2461e.mjs"],"command":"node","cwd":"./","env":{"AGENT_BUNDLE_PLUGIN_ROOT":"./"},"type":"stdio"}}}
@@ -0,0 +1 @@
1
+ {"author":{"name":"Zack Jackson","url":"https://github.com/ScriptedAlchemy"},"description":"Message Grok Bot bots and groups and read their threads from Codex, Claude Code, and Cursor.","homepage":"https://github.com/ScriptedAlchemy/grok-bot-cli#readme","interface":{"capabilities":["mcp","skills"],"category":"Productivity","defaultPrompt":["Help me use gbot."],"developerName":"gbot","displayName":"gbot","longDescription":"Message Grok Bot bots and groups and read their threads from Codex, Claude Code, and Cursor.","shortDescription":"Message Grok Bot bots and groups and read their threads from Codex, Claude Code, and Cursor."},"keywords":["grok","grok-bot","grokbot","gbot","cursor","ai-agents","automation","terminal","cli","agent-bundle"],"license":"MIT","mcpServers":"./.codex-plugin/mcp.json","name":"gbot","repository":"https://github.com/ScriptedAlchemy/grok-bot-cli","skills":"./skills/","version":"0.4.0"}
@@ -0,0 +1 @@
1
+ {"name":"gbot-marketplace","owner":{"name":"gbot"},"plugins":[{"description":"Message Grok Bot bots and groups and read their threads from Codex, Claude Code, and Cursor.","name":"gbot","source":"./"}]}
@@ -0,0 +1 @@
1
+ {"mcpServers":{"grok-bot":{"args":["${CURSOR_PLUGIN_ROOT}/mcp/mcp-grok-bot-b8c2461e.mjs"],"command":"node","env":{"AGENT_BUNDLE_PLUGIN_ROOT":"${CURSOR_PLUGIN_ROOT}"}}}}
@@ -0,0 +1 @@
1
+ {"author":{"name":"Zack Jackson"},"description":"Message Grok Bot bots and groups and read their threads from Codex, Claude Code, and Cursor.","displayName":"gbot","homepage":"https://github.com/ScriptedAlchemy/grok-bot-cli#readme","keywords":["grok","grok-bot","grokbot","gbot","cursor","ai-agents","automation","terminal","cli","agent-bundle"],"license":"MIT","mcpServers":"./.cursor-plugin/mcp.json","name":"gbot","repository":"https://github.com/ScriptedAlchemy/grok-bot-cli","skills":"./skills/","version":"0.4.0"}
package/dist/.mcp.json ADDED
@@ -0,0 +1 @@
1
+ {"mcpServers":{"grok-bot":{"args":["${CLAUDE_PLUGIN_ROOT}/mcp/mcp-grok-bot-b8c2461e.mjs"],"command":"node","env":{"AGENT_BUNDLE_PLUGIN_ROOT":"${CLAUDE_PLUGIN_ROOT}"},"type":"stdio"}}}
@@ -0,0 +1,269 @@
1
+ # Install gbot
2
+
3
+ Message Grok Bot bots and groups and read their threads from Codex, Claude Code, and Cursor.
4
+
5
+ Version: `0.4.0`
6
+
7
+ Run these commands from this bundle directory. The bundle is self-contained: every command below is
8
+ a host command or the bundled installer, and nothing requires the `agent-bundle` CLI. Where that CLI is
9
+ mentioned it is optional and automates the same steps.
10
+
11
+ ## Claude Code
12
+
13
+ Claude Code installs this bundle through its local marketplace contract:
14
+
15
+ ```sh
16
+ claude plugin marketplace add ./
17
+ claude plugin install gbot@gbot-marketplace --scope user
18
+ ```
19
+
20
+ Replace `user` with `project` or `local` when that Claude scope is intended.
21
+
22
+ ### Reinstall after a same-version rebuild
23
+
24
+ `claude plugin update` is version-gated: when the bundle content changed but `version` did not,
25
+ it reports the plugin is already at the latest version and leaves the cached copy stale.
26
+ Uninstall and install again instead (`--keep-data` preserves the plugin's persistent data):
27
+
28
+ ```sh
29
+ claude plugin uninstall gbot@gbot-marketplace --scope user --keep-data
30
+ claude plugin marketplace add ./
31
+ claude plugin install gbot@gbot-marketplace --scope user
32
+ ```
33
+
34
+ With the optional `agent-bundle` CLI, `agent-bundle install claude --from ./` runs this sequence
35
+ automatically when the installed copy has the same version but a different content hash; `--replace`
36
+ (alias `--force`) forces it.
37
+
38
+ ### Uninstall
39
+
40
+ ```sh
41
+ claude plugin uninstall gbot@gbot-marketplace --scope user --keep-data
42
+ ```
43
+
44
+ Match the scope the plugin was installed with (`user`, `project`, or `local`). `--keep-data` keeps durable
45
+ runtime state (Claude orphans the cached copy, `state/` included, for its ~14-day grace period); omit it to
46
+ remove `~/.claude/plugins/data/<id>/` immediately.
47
+
48
+ The marketplace `gbot-marketplace` stays registered. Remove it only when nothing else installs from it:
49
+ `plugin marketplace remove` applies to every scope and every project, and `claude plugin list` shows only
50
+ the current project, so also check `~/.claude/plugins/installed_plugins.json` (under `$CLAUDE_CONFIG_DIR`
51
+ when set), where Claude records every scope of every install. The optional `agent-bundle uninstall claude`
52
+ below performs that inventory before it removes anything.
53
+
54
+ ```sh
55
+ claude plugin marketplace remove gbot-marketplace
56
+ ```
57
+
58
+ With the optional `agent-bundle` CLI, `agent-bundle uninstall claude --from ./ --plan` prints exactly what
59
+ would be removed and `agent-bundle uninstall claude --from ./` reverses the recorded registrations.
60
+ `agent-bundle install claude` records a receipt at `~/.claude/agent-bundle/receipts/gbot.gbot-marketplace.user.json`
61
+ (or under `$CLAUDE_CONFIG_DIR`; `user` is the install scope, pass `--scope project` or `--scope local` to match
62
+ a scoped install), and `uninstall` consumes it, running the two commands above in order and retaining the
63
+ marketplace while any other plugin, scope, or project still installs from it. Durable runtime state
64
+ is kept by default; `--purge-data --confirm-purge` removes `state/` and `~/.claude/plugins/data/<id>/`
65
+ immediately. A missing receipt or a cached copy that no longer matches it is refused unless `--force`; a
66
+ second run is a `not-installed` no-op.
67
+
68
+ ## Codex
69
+
70
+ Codex installs this bundle from its local marketplace snapshot:
71
+
72
+ ```sh
73
+ codex plugin marketplace add ./
74
+ codex plugin add gbot@gbot-marketplace
75
+ ```
76
+
77
+ ### Reinstall after a same-version rebuild
78
+
79
+ `codex plugin add` re-copies the marketplace snapshot but never deletes files a rebuild removed.
80
+ Remove and add again for a clean same-version copy:
81
+
82
+ ```sh
83
+ codex plugin remove gbot@gbot-marketplace
84
+ codex plugin marketplace add ./
85
+ codex plugin add gbot@gbot-marketplace
86
+ ```
87
+
88
+ With the optional `agent-bundle` CLI, `agent-bundle install codex --from ./` runs this sequence
89
+ automatically when the installed copy has the same version but a different content hash; `--replace`
90
+ (alias `--force`) forces it.
91
+
92
+ ### Uninstall
93
+
94
+ ```sh
95
+ codex plugin remove gbot@gbot-marketplace
96
+ ```
97
+
98
+ Codex 0.147.0 deletes the cached plugin tree, `state/` included, on `plugin remove` and has no keep-data
99
+ option.
100
+
101
+ The marketplace `gbot-marketplace` stays registered. Remove it only when nothing else installs from it:
102
+ `codex plugin list` shows every other plugin from it.
103
+
104
+ ```sh
105
+ codex plugin marketplace remove gbot-marketplace
106
+ ```
107
+
108
+ With the optional `agent-bundle` CLI, `agent-bundle uninstall codex --from ./ --plan` prints exactly what
109
+ would be removed and `agent-bundle uninstall codex --from ./` reverses the recorded registrations.
110
+ `agent-bundle install codex` records a receipt at `~/.codex/agent-bundle/receipts/gbot.gbot-marketplace.user.json` (or
111
+ under `$CODEX_HOME`), and `uninstall` consumes it, running the two commands above in order. `--keep-data`
112
+ cannot preserve durable state on Codex; the result says so (`unavailable`). A missing receipt or a cached
113
+ copy that no longer matches it is refused unless `--force`; a second run is a `not-installed` no-op.
114
+
115
+ ## Cursor
116
+
117
+ Cursor has no non-interactive plugin install command. The bundled installer supports two delivery modes.
118
+
119
+ ### Local plugin (default)
120
+
121
+ ```sh
122
+ node ./install.mjs
123
+ ```
124
+
125
+ It safe-copies the bundle to `~/.cursor/plugins/local/gbot`. Restart Cursor or run
126
+ `Developer: Reload Window` after installation. Cursor loads rules, skills, MCP servers, and the
127
+ manifest-declared `hooks/hooks.json` from that directory; plugin hooks run from the plugin root with
128
+ `${CURSOR_PLUGIN_ROOT}` substituted and need no `~/.cursor/hooks.json` entry.
129
+
130
+ ### Reinstall after a same-version rebuild
131
+
132
+ The installer writes an install receipt (`.agent-bundle-install.json`: plugin, version, content hash,
133
+ owned files) beside the plugin manifest. Re-running `node ./install.mjs` on an identical artifact
134
+ is a no-op that says so. When the installed copy has the same version but different content, the
135
+ installer replaces its owned files in place and leaves runtime state (`state/`) untouched:
136
+
137
+ ```sh
138
+ node ./install.mjs # same-version content drift of a receipt-managed copy is replaced
139
+ node ./install.mjs --replace # also replace a different installed version, or adopt a pre-receipt copy
140
+ ```
141
+
142
+ `--force` is an alias for `--replace`. A directory that is not an agent-bundle install of this
143
+ plugin is always refused with an installed-versus-artifact content-hash comparison; remove it
144
+ manually. The optional `agent-bundle` CLI applies the same policy through
145
+ `agent-bundle install cursor --from ./ [--replace]`.
146
+
147
+ ### Uninstall
148
+
149
+ ```sh
150
+ node ./install.mjs --uninstall --plan # print exactly what would be removed
151
+ node ./install.mjs --uninstall # remove the receipt-owned files; keep state/
152
+ node ./install.mjs --uninstall --purge-data --confirm-purge # also remove durable runtime state
153
+ node ./install.mjs --uninstall --mode marketplace # remove a staged marketplace repository
154
+ ```
155
+
156
+ Uninstall removes exactly what the receipt owns: the listed files, the directories the installer
157
+ created (including `~/.cursor/plugins/local` when the installer made it), and nothing else. Durable
158
+ runtime state under `state/` (state kernel, notices journal) — and, for an Agent Plugins pack with a stdio
159
+ server, the `~/.cursor/agent-bundle/plugin-data/<name>` directory the receipt records as `PLUGIN_DATA` — is kept
160
+ unless `--purge-data --confirm-purge` is passed (a kept data directory leaves a remnant receipt behind so a later
161
+ purge still finds it; an empty one is pruned); unowned files are left in place and listed. A supported older
162
+ receipt with no recorded state location retains the current environment's default as unproven; a keep-data run
163
+ cannot turn that observation into later purge authority. A directory without a receipt is refused unless
164
+ `--force` (which removes a pre-receipt legacy copy by its inventory); owned content that no longer matches
165
+ the receipt is refused unless `--force`; a directory that is not this plugin's install is always refused.
166
+ A second run is a `Not installed` no-op. With the optional `agent-bundle` CLI,
167
+ `agent-bundle uninstall cursor --from ./ [--mode marketplace]` applies the same policy, and
168
+ `agent-bundle doctor --from ./` shows the lifecycle stage (placed, registered, enabled, active) with
169
+ unobservable stages typed `unavailable`.
170
+
171
+ ### Marketplace plugin
172
+
173
+ ```sh
174
+ node ./install.mjs --mode marketplace
175
+ ```
176
+
177
+ It stages a committed Git repository at `~/.cursor/agent-bundle/marketplaces/gbot` whose
178
+ `.cursor-plugin/marketplace.json` lists this plugin, then prints the exact Cursor step: Customize -> Plugins ->
179
+ "Add Plugins from Local Repository" -> select that directory -> Install. Cursor then shows the plugin as a
180
+ marketplace install (not "local") and manages it from Customize. `git` must be on PATH. Verify in Cursor:
181
+ Customize -> Plugins lists the plugin, and its files appear under `~/.cursor/plugins/cache`. The optional
182
+ `agent-bundle` CLI performs the same check with `agent-bundle doctor --host cursor`.
183
+
184
+ ## Portable Agent Plugin
185
+
186
+ Portable is a distribution profile, not a host runtime with one universal install location.
187
+ This bundle follows the Agent Plugins open standard (Agent Plugins 1.0.0, https://agent-plugins.org).
188
+ Cursor loads this format natively from `~/.cursor/plugins/local/<name>`; restart Cursor or run
189
+ `Developer: Reload Window` after copying it. The bundled installer provides the Cursor local copy:
190
+
191
+ ```sh
192
+ node ./install.mjs
193
+ ```
194
+
195
+ ### Other recorded clients
196
+
197
+ Each line below is pinned to that client's own documentation on the date shown, and names only the
198
+ paths this build actually wrote. Recognizing a document and running what it configures are separate:
199
+ `mcp` records that the client reads the emitted `mcp.json` as MCP configuration, while `placeholders`
200
+ records that it expands the reserved `${PLUGIN_ROOT}` / `${PLUGIN_DATA}` and provides them to the
201
+ process it spawns. A client can do the first without the second, and then a plugin-relative server
202
+ is configured but not runnable there.
203
+
204
+ - **Antigravity** (docs retrieved 2026-09-06; no product or CLI version is published on any page) loads nothing from this bundle as published. Not loaded: manifest, skills, mcp, placeholders, hooks.
205
+ - **Cascade (Devin Desktop)** (docs.devin.ai/desktop retrieved 2026-09-06; Windsurf renamed to Devin Desktop, Cascade documented as the legacy agent beside the Devin Local agent) loads the components it recognizes without reading the manifest. Reads: `skills`. Install: `cp -R skills/<skill> .agents/skills/<skill>`. Not loaded: manifest, mcp, placeholders, hooks.
206
+ - Partial `skills`: 2026-09-06: the emitted package root is not a Cascade discovery root; each skill directory is copied into .windsurf/skills/, ~/.codeium/windsurf/skills/, or .agents/skills/ before Cascade sees it, and the copy is what loads.
207
+ - **Cline** (@cline/cli 0.0.13 exercised 2026-09-06; docs.cline.bot retrieved 2026-09-06 (@cline/sdk 0.0.82)) loads the components it recognizes without reading the manifest. Reads: `skills`. Install: `cp -R skills/<skill> ~/.cline/skills/<skill>`. Not loaded: manifest, mcp, placeholders, hooks.
208
+ - Partial `skills`: 2026-09-06: the skill tree must be copied into one of Cline's own roots; the emitted package is not a Cline install unit, and no CLI verb in @cline/cli 0.0.13 performs the copy.
209
+ - **CodeWhale** (Hmbown/CodeWhale main 19d34a5fb6c07b34e0b7234beb74a1cf1969efb4, docs retrieved 2026-09-06 (native Agent Plugins v1.0.0 support since v0.9.4)) loads this bundle as one plugin. Reads: `mcp.json`, `plugin.json`, `skills`. Install: `/plugin install ./<plugin directory>`. Not loaded: placeholders, hooks.
210
+ - Partial `mcp`: 2026-09-06: CodeWhale narrows the standard at the plugin boundary. Its env rule — "Local stdio environment entries must use exact ${SOURCE_ENV} references" — rejects an emitted env value that is anything other than one whole variable reference. A remote server emitted into mcp.json is narrower still: the URL must be HTTPS (or explicit loopback HTTP) with no user information, query, or fragment, a literal header is rejected in favor of CodeWhale's own env_headers or bearer_token_env_var keys, redirects must stay on the reviewed origin, and the bundle must declare exactly the normalized endpoint host set in capabilities.network_hosts. That declaration rides in extensions["net.codewhale"], which this projection writes only when the author authors portable.extensions; a remote server emitted without it is a validation error, and "an active bundle must be … free of validation errors", so the whole bundle stays inactive there until the author declares the matching host set.
211
+ - **GitHub Copilot CLI** (@github/copilot 1.0.83, installed and exercised 2026-09-06) loads this bundle as one plugin. Reads: `plugin.json`, `skills`. Install: `copilot plugin install <plugin directory>`. Not loaded: hooks. This build also writes `.mcp.json`, which it uses for mcp instead. A root that also carries `.plugin/plugin.json` uses it for manifest and still reads the rest.
212
+ - **Devin CLI** (Agent Plugins 1.0.0; docs retrieved 2026-09-06, plugins documented as closed beta) loads this bundle as one plugin, but this build also writes `.claude-plugin/plugin.json`, which it reads as the plugin instead.
213
+ - **Gemini CLI** (@google/gemini-cli 0.58.0, installed and exercised 2026-09-06) loads the components it recognizes without reading the manifest. Reads: `skills`. Install: `gemini skills install <plugin directory>/skills/<skill>`. Not loaded: manifest, mcp, placeholders, hooks.
214
+ - **Grok Build** (xai-org/grok-build main 72a61251fcffb464bcc687aeb5a998e5a98ec0c9, docs retrieved 2026-09-06) loads the components it recognizes without reading the manifest. Reads: `skills`. Install from a marketplace (no local-directory install is verified for this artifact): `grok plugin install <marketplace plugin name> --trust`. Not loaded: manifest, mcp, placeholders, hooks.
215
+ - **Hermes Agent** (hermes-agent.nousresearch.com developer guide retrieved 2026-09-06; no version is printed on the page) loads this bundle as one plugin. Reads: `mcp.json`, `plugin.json`, `skills`. Install from a Git repository (no local-directory install is verified for this artifact): `hermes plugins install <owner>/<repository> --no-enable`. Not loaded: hooks.
216
+ - Partial `manifest`: 2026-09-06: the validation rule set is not published: the page never states that the manifest root is treated as closed or what happens to an unknown root key.
217
+ - Partial `placeholders`: 2026-09-06: the expansion sites are unpublished — the page does not say whether ${PLUGIN_ROOT} and ${PLUGIN_DATA} are expanded in args, env values, and cwd as §9.1 requires, only that the variables are provided.
218
+ - **JetBrains Junie** (junie.jetbrains.com/docs retrieved 2026-09-06, agent-skills page dated 01 September 2026; no CLI version is published on the page) loads the components it recognizes without reading the manifest. Reads: `skills`. Register: `junie --skill-location <plugin directory>/skills`. Not loaded: manifest, mcp, placeholders, hooks.
219
+ - Partial `skills`: 2026-09-06: the emitted skills/ root is not a default location, so it loads only once registered with --skill-location or the skill-locations config field, and "if a project-level and a user-level skills have the same name, the user-level skill will be skipped".
220
+ - **Kiro (Powers)** (kiro.dev/docs/powers pages updated September 2, 2026 and August 4, 2026, retrieved 2026-09-06) loads this bundle as one plugin. Reads: `mcp.json`, `plugin.json`, `skills`. Install: `Powers panel -> Add Custom Power -> Import power from a folder -> select <plugin directory> -> Install`. Not loaded: placeholders, hooks.
221
+ - Partial `manifest`: 2026-09-06: Kiro's "Required fields" table additionally requires version, description, author, and keywords, where the canonical schema requires only $schema and name — so a bundle that declares no portable author or keywords metadata does not meet Kiro's tightened manifest, and Kiro publishes no validation-error behavior to say what happens then.
222
+ - Partial `mcp`: 2026-09-06: only stdio is documented for a power's mcp.json; no Kiro page states that a streamable-http server in that file is read, so an emitted remote server is unproven there.
223
+ - **OpenClaw** (Agent Plugins 1.0.0; docs retrieved 2026-09-06) loads this bundle as one plugin, but this build also writes `.claude-plugin/plugin.json`, which it reads as the plugin instead.
224
+ - **OpenCode** (opencode-ai 1.18.29 exercised 2026-09-06; opencode.ai/docs retrieved 2026-09-06) loads the components it recognizes without reading the manifest. Reads: `skills`. Install: `cp -R skills/<skill> .agents/skills/<skill>`. Not loaded: manifest, mcp, placeholders, hooks.
225
+ - Partial `skills`: 2026-09-06: the skill tree must be copied into one of OpenCode's own roots; the emitted package as a whole is not an OpenCode install unit, and skill names must be unique across all roots ("Ensure skill names are unique across all locations").
226
+ - **Pi** (@mariozechner/pi-coding-agent 0.73.1 installed from npm 2026-09-07; packaged docs/skills.md and docs/packages.md read from that release) loads the components it recognizes without reading the manifest. Reads: `skills`. Register: `pi --skill <plugin directory>/skills`. Not loaded: manifest, mcp, placeholders, hooks.
227
+ - Partial `skills`: 2026-09-07: the emitted skills/ root is not one of the scanned default roots, so it loads only when it is named with --skill or added to the `skills` settings array; discovery inside it is recursive once named.
228
+ - **Qoder CLI** (docs retrieved 2026-09-06; no CLI version is published on any page) loads the components it recognizes without reading the manifest. Reads: `skills`. Install: `qoder plugins install <plugin directory> --scope user`. Not loaded: manifest, placeholders, hooks. This build also writes `.mcp.json`, which it uses for mcp instead.
229
+ - **Swival** (docs retrieved 2026-09-06; no product version is published on the documentation pages) loads the components it recognizes without reading the manifest. Reads: `skills`. Register: `swival --skills-dir <plugin directory>/skills "<task>"`. Not loaded: manifest, mcp, placeholders, hooks.
230
+ - Partial `skills`: 2026-09-06: the emitted skills/ root is not a default location, so it loads only once registered with --skills-dir or the swival.toml skills_dir field, and it loses by name to the default roots: "If the same skill name exists in multiple locations, the first one in the precedence order wins", with .swival/skills/ and .agents/skills/ ahead of --skills-dir paths. A registered tree outside the project resolves as external, which Swival adds "as read-only roots".
231
+ - **VS Code (Copilot agent plugins)** (code.visualstudio.com/docs/agent-customization/agent-plugins, page footer 9/2/2026, retrieved 2026-09-06) loads this bundle as one plugin. Reads: `mcp.json`, `plugin.json`, `skills`. Register: `"chat.pluginLocations": { "<plugin directory>": true }`. Not loaded: placeholders, hooks.
232
+ - **Zed Agent** (zed.dev/docs retrieved 2026-09-06; no page publishes a version or last-updated date) loads the components it recognizes without reading the manifest. Reads: `skills`. Install: `cp -R skills/<skill> ~/.agents/skills/<skill>`. Not loaded: manifest, mcp, placeholders, hooks.
233
+ - Partial `skills`: 2026-09-06: only the skill folders load, one copy at a time, and the catalog is capped — "50KB catalog budget… Skills that don't fit are dropped from the catalog with a warning in the UI" — so a large emitted skill set is not guaranteed to be wholly visible.
234
+
235
+ ### Cursor placeholder expansion
236
+
237
+ Cursor 3.18.25 spawns the stdio servers of an Agent Plugins package without expanding
238
+ `${PLUGIN_ROOT}` / `${PLUGIN_DATA}` in `args`, `env` values, or `cwd`, without providing the
239
+ reserved `PLUGIN_ROOT` / `PLUGIN_DATA` variables (spec §9.1), with an omitted `cwd` defaulting to
240
+ the home directory, and with plugin-relative `./` commands resolved against the workspace folder
241
+ (spec §7.2.1). The installer therefore rewrites `mcp.json` in the Cursor copy only: the plugin root
242
+ becomes `~/.cursor/plugins/local/<name>`, the data directory `~/.cursor/agent-bundle/plugin-data/<name>`
243
+ (created by the installer), an omitted `cwd` becomes the plugin root, `./` commands resolve against
244
+ it, and every stdio server gains `PLUGIN_ROOT` / `PLUGIN_DATA` in its environment. The bundle itself
245
+ stays spec-conformant; the pre-expansion document is kept in `.agent-bundle-install.json` (`cursorExpansion`),
246
+ and the optional `agent-bundle doctor --host cursor` verifies the expanded paths (`AB7326`). Nothing is changed for
247
+ other clients; the recorded clients above name which of them expand the placeholders themselves.
248
+
249
+ ### Reinstall after a same-version rebuild
250
+
251
+ The installer records an install receipt (`.agent-bundle-install.json`) and replaces its owned files in
252
+ place when the same version was rebuilt with different content; runtime state (`state/`) is never
253
+ touched. Pass `--replace` (alias `--force`) to replace a different installed version or to adopt a
254
+ copy installed before receipts existed. Foreign directories are refused with a content-hash
255
+ comparison. For a client that manages its own copy, remove and re-add the plugin through that client
256
+ when only content changed at the same version.
257
+
258
+ ### Uninstall
259
+
260
+ ```sh
261
+ node ./install.mjs --uninstall --plan # print exactly what would be removed
262
+ node ./install.mjs --uninstall # remove the receipt-owned files; keep state/
263
+ node ./install.mjs --uninstall --purge-data --confirm-purge # also remove durable runtime state
264
+ ```
265
+
266
+ Uninstall removes exactly what the receipt owns (files, installer-created directories) and keeps
267
+ durable runtime state under `state/` (and the recorded `PLUGIN_DATA` directory of an Agent Plugins pack)
268
+ unless `--purge-data --confirm-purge` is passed. A missing
269
+ receipt or modified owned content is refused unless `--force`; foreign directories are always refused.
package/dist/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ScriptedAlchemy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.