@datagusto/cli 0.0.0-stage → 0.2.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.
- package/LICENSE +21 -0
- package/README.md +186 -2
- package/bin/run.js +5 -0
- package/dist/adapters/claude-code.d.ts +48 -0
- package/dist/adapters/claude-code.js +526 -0
- package/dist/adapters/claude-code.js.map +1 -0
- package/dist/adapters/claude-settings.d.ts +29 -0
- package/dist/adapters/claude-settings.js +115 -0
- package/dist/adapters/claude-settings.js.map +1 -0
- package/dist/adapters/index.d.ts +10 -0
- package/dist/adapters/index.js +37 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/kiro-agent.d.ts +29 -0
- package/dist/adapters/kiro-agent.js +124 -0
- package/dist/adapters/kiro-agent.js.map +1 -0
- package/dist/adapters/kiro.d.ts +24 -0
- package/dist/adapters/kiro.js +752 -0
- package/dist/adapters/kiro.js.map +1 -0
- package/dist/adapters/types.d.ts +81 -0
- package/dist/adapters/types.js +14 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/api/client.d.ts +36 -0
- package/dist/api/client.js +85 -0
- package/dist/api/client.js.map +1 -0
- package/dist/api/errors.d.ts +4 -0
- package/dist/api/errors.js +25 -0
- package/dist/api/errors.js.map +1 -0
- package/dist/commands/remove.d.ts +13 -0
- package/dist/commands/remove.js +59 -0
- package/dist/commands/remove.js.map +1 -0
- package/dist/commands/setup.d.ts +16 -0
- package/dist/commands/setup.js +114 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/status.d.ts +7 -0
- package/dist/commands/status.js +53 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/display.d.ts +2 -0
- package/dist/display.js +12 -0
- package/dist/display.js.map +1 -0
- package/dist/fs/atomic.d.ts +23 -0
- package/dist/fs/atomic.js +65 -0
- package/dist/fs/atomic.js.map +1 -0
- package/dist/key-input.d.ts +24 -0
- package/dist/key-input.js +96 -0
- package/dist/key-input.js.map +1 -0
- package/dist/platform.d.ts +24 -0
- package/dist/platform.js +61 -0
- package/dist/platform.js.map +1 -0
- package/dist/state/installs.d.ts +24 -0
- package/dist/state/installs.js +110 -0
- package/dist/state/installs.js.map +1 -0
- package/dist/vendor.d.ts +16 -0
- package/dist/vendor.js +60 -0
- package/dist/vendor.js.map +1 -0
- package/package.json +57 -4
- package/vendor/claude_code/.claude-plugin/plugin.json +55 -0
- package/vendor/claude_code/README.md +267 -0
- package/vendor/claude_code/dist/api-client.js +82 -0
- package/vendor/claude_code/dist/builtin-tools.generated.js +33 -0
- package/vendor/claude_code/dist/extractors.js +201 -0
- package/vendor/claude_code/dist/index.js +695 -0
- package/vendor/claude_code/dist/monitoring.js +66 -0
- package/vendor/claude_code/dist/state.js +71 -0
- package/vendor/claude_code/dist/types.js +5 -0
- package/vendor/claude_code/hooks/hooks.json +25 -0
- package/vendor/claude_code/package.json +26 -0
- package/vendor/kiro/.kiro/agents/kiro_default.json +20 -0
- package/vendor/kiro/.kiro/hooks/datagusto-post-tool-use.json +10 -0
- package/vendor/kiro/.kiro/hooks/datagusto-pre-tool-use.json +10 -0
- package/vendor/kiro/.kiro/hooks/datagusto-session-start.json +10 -0
- package/vendor/kiro/.kiro/hooks/datagusto-stop.json +10 -0
- package/vendor/kiro/.kiro/hooks/datagusto-user-prompt-submit.json +10 -0
- package/vendor/kiro/dist/api-client.js +82 -0
- package/vendor/kiro/dist/builtin-tools.generated.js +87 -0
- package/vendor/kiro/dist/engine.js +65 -0
- package/vendor/kiro/dist/extractors.js +201 -0
- package/vendor/kiro/dist/index.js +735 -0
- package/vendor/kiro/dist/monitoring.js +66 -0
- package/vendor/kiro/dist/state.js +71 -0
- package/vendor/kiro/dist/types.js +5 -0
- package/vendor/kiro/package.json +25 -0
- package/vendor/manifest.json +42 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 datagusto
|
|
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.
|
package/README.md
CHANGED
|
@@ -1,3 +1,187 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @datagusto/cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The `dg` command (also installed as `datagusto`) connects a coding agent to Datagusto with one command. See [ADR-0003](../ADR-0003-agent-setup-cli.md) for the design.
|
|
4
|
+
|
|
5
|
+
> **Status: Phase 2.** `claude-code` and `kiro` work end to end (Kiro on the Kiro CLI; the Kiro IDE is not verified). `codex` is accepted by the argument parser but reports "not supported yet".
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
dg setup <claude-code|kiro|codex> [--server-url <url>] [--workspace <dir>]
|
|
9
|
+
dg status
|
|
10
|
+
dg remove <claude-code|kiro|codex> [--workspace <dir>]
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Connect Claude Code
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
npm install -g @datagusto/cli
|
|
17
|
+
dg setup claude-code --server-url https://datagusto.your-company.example # prompts for the key (hidden)
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
`--server-url` is the address of your company's Datagusto server. There is no shared Datagusto server and so no default: the first setup needs the flag. A re-run without it keeps the URL that is already installed.
|
|
21
|
+
|
|
22
|
+
`dg setup claude-code`:
|
|
23
|
+
|
|
24
|
+
1. checks that Claude Code is installed (`claude` on `PATH`, or a `~/.claude` folder)
|
|
25
|
+
2. reads the agent API key (see below) and checks it with `GET /api/v1/public/safety/whoami`. A bad key or URL stops here and nothing is written
|
|
26
|
+
3. copies the bundled plugin to `~/.datagusto/claude-code/` and writes `claude-code.json` (server URL + key, mode `0600`) inside it
|
|
27
|
+
4. adds the plugin's hooks to `~/.claude/settings.json`, pointing at that folder. Nothing else in the file is changed
|
|
28
|
+
5. records the install in `~/.datagusto/installs.json` (paths and agent id, never the key)
|
|
29
|
+
|
|
30
|
+
Running it again is safe. It replaces the plugin files with the bundled version and updates the key and URL, keeping any other options you added to `claude-code.json` (such as `"verbose": true`).
|
|
31
|
+
|
|
32
|
+
New Claude Code sessions run the hooks automatically. Sessions that are already open usually pick up the `settings.json` change on their own; restart them to be sure.
|
|
33
|
+
|
|
34
|
+
`dg status` checks every install: Claude Code version, plugin files against the hashes recorded at install time, the hooks in `settings.json`, config file permissions, and a live whoami call with the stored key. It exits `1` if any check fails.
|
|
35
|
+
|
|
36
|
+
`dg remove claude-code` takes dg's entries out of `settings.json`, deletes the plugin folder and drops the ledger entry. It works offline. The key keeps working until you revoke it in the dashboard, and `dg remove` says so.
|
|
37
|
+
|
|
38
|
+
### How the plugin is wired in, and why
|
|
39
|
+
|
|
40
|
+
| Option | Loads every session | Works on every Claude Code version | Used |
|
|
41
|
+
|---|---|---|---|
|
|
42
|
+
| Hook entries merged into `~/.claude/settings.json` | Yes | Yes (any version with hooks) | **Yes** |
|
|
43
|
+
| `~/.claude/skills/<dir>/` with `.claude-plugin/plugin.json` | Yes | No: 2.1.157 or later only | No |
|
|
44
|
+
| `claude --plugin-dir` / `CLAUDE_CODE_PLUGIN_DIRS` | No: one session, or needs a shell-profile edit | Yes | No (still fine for plugin development) |
|
|
45
|
+
| Marketplace + `/plugin install` | Yes | Yes | No: marketplaces are out of scope (ADR-0003) |
|
|
46
|
+
|
|
47
|
+
One method for every version keeps setup, status and remove simple. The skills folder was tried first and dropped: it only works on newer Claude Code, so it needed `settings.json` as a second method anyway, plus logic to switch between them. It is also a confusing home for something that isn't a skill.
|
|
48
|
+
|
|
49
|
+
The hook commands are the ones in the plugin's `hooks/hooks.json`, with `${CLAUDE_PLUGIN_ROOT}` replaced by the absolute folder: `node "/Users/you/.datagusto/claude-code/dist/index.js"`. The plugin's `loadConfig()` reads `claude-code.json` from its own folder, so the plugin runtime needed no change. The folder lives outside `~/.claude` so that no Claude Code version also loads it as a plugin, which would run every hook twice.
|
|
50
|
+
|
|
51
|
+
Confirmed on Claude Code 2.1.202 in a throwaway HOME: a session started there made the plugin's session-start and prompt calls to the server.
|
|
52
|
+
|
|
53
|
+
How dg treats `settings.json` (ADR-0003 TR-5: only add or remove our own entries):
|
|
54
|
+
|
|
55
|
+
- **Only known events are written.** Before 2.1.122, one bad hooks entry could invalidate the whole settings file, so each event is written only if the installed version has it: `PreToolUse`/`PostToolUse` 1.0.38, `UserPromptSubmit` 1.0.54, `SessionStart` 1.0.62, `SessionEnd` 1.0.85, `PermissionRequest` 2.0.45, `PostToolUseFailure` 2.1.119 (its first changelog mention). Setup refuses Claude Code older than 1.0.62. If `claude --version` can't be run, setup assumes a current version and writes all seven.
|
|
56
|
+
- **A file that isn't valid JSON is never rewritten.** Setup stops and asks the user to fix it.
|
|
57
|
+
- **Only dg's entries change.** Entries are recognised by their command pointing into `~/.datagusto/claude-code/`. The user's other hooks and settings are written back as read, though the file is re-indented with 2 spaces.
|
|
58
|
+
- **Symlinks survive.** A symlinked `settings.json` (dotfile managers) is written through to its target, and the file keeps its mode.
|
|
59
|
+
- **Upgrades are picked up on a re-run.** After a Claude Code upgrade, `dg status` says which newer events are missing, and `dg setup claude-code` adds them.
|
|
60
|
+
|
|
61
|
+
Things to know:
|
|
62
|
+
|
|
63
|
+
- Loading the plugin with `--plugin-dir` as well (plugin development) runs every hook twice. Run `dg remove claude-code` first.
|
|
64
|
+
- `.datagusto-install.json` inside the folder marks it as dg's. `dg setup` refuses to overwrite a `~/.datagusto/claude-code` folder without it, and `dg remove` won't delete one.
|
|
65
|
+
- An earlier build of dg installed to `~/.claude/skills/datagusto-safety/`. Setup removes that copy if it carries dg's marker, and keeps its options.
|
|
66
|
+
- If setup created `~/.claude/settings.json`, `dg remove` leaves it behind as `{}`.
|
|
67
|
+
- The version floors come from Claude Code's `CHANGELOG.md`. Versions older than 2.1.202 are tested with a fake `claude --version`, not a real old install.
|
|
68
|
+
|
|
69
|
+
## Connect Kiro
|
|
70
|
+
|
|
71
|
+
Kiro hooks are per workspace, so the plugin is installed into one workspace at a time. `--workspace` defaults to the current directory.
|
|
72
|
+
|
|
73
|
+
```sh
|
|
74
|
+
cd ~/code/my-repo
|
|
75
|
+
dg setup kiro --server-url https://datagusto.your-company.example # prompts for the key (hidden)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
`dg setup kiro`:
|
|
79
|
+
|
|
80
|
+
1. checks that the workspace is a folder and that the Kiro CLI is installed (`kiro-cli` on `PATH`). If it isn't, setup stops and prints the install command (`curl -fsSL https://cli.kiro.dev/install | bash`, `brew install --cask kiro-cli` on macOS, or the Windows installer from kiro.dev). The Kiro IDE on its own is not enough
|
|
81
|
+
2. stops, before asking for the key, if the workspace already has a file at one of the paths below that dg didn't put there (most often the project's own `dist/index.js`)
|
|
82
|
+
3. reads the agent API key (see below) and checks it with whoami, exactly as for Claude Code. `--server-url` is the same flag
|
|
83
|
+
4. copies the bundled plugin to `<workspace>/dist/`, writes `<workspace>/kiro.json` (server URL + key, mode `0600`), and copies the five hook files to `<workspace>/.kiro/hooks/datagusto-*.json`
|
|
84
|
+
5. writes `<workspace>/.kiro/agents/kiro_default.json`, a default agent carrying the same five hooks, or merges those hooks into the file if the workspace already has one
|
|
85
|
+
6. records the install in `~/.datagusto/installs.json`, one entry per workspace
|
|
86
|
+
|
|
87
|
+
Then start `kiro-cli` in that folder. Running setup again is safe: it replaces the plugin and hook files with the bundled version and updates the key and URL, keeping any other options in `kiro.json`.
|
|
88
|
+
|
|
89
|
+
Kiro CLI 2.x has engines that read hooks from different places, which is why there are two sets. `kiro-cli --v3` reads the standalone files in `.kiro/hooks/`. The default engine (plain `kiro-cli`, or `--v2`) ignores those and runs the `hooks` in the config of the agent a session uses; a workspace agent named `kiro_default` takes the built-in default agent's place, so its hooks run in a plain session. `--v3` does not run the hooks in that file, so the two sets never fire together. A third engine, V1, runs when the Kiro setting `chat.agentEngine` is `v1` or, per `kiro-cli chat --help`, with `--agent-engine v1` (the flag was not tried); it honours neither set, so dg does not cover it.
|
|
90
|
+
|
|
91
|
+
`dg status` lists every workspace separately and checks the plugin files and hook files against the hashes recorded at install time, that the default agent still runs the plugin on all five events, `kiro.json`'s permissions and whether git ignores it, and a live whoami call. It fails when it knows a plain `kiro-cli` session goes unchecked, which includes Kiro's `chat.agentEngine` setting being `v1`, and warns when that depends on an agent dg doesn't manage: Kiro's `chat.defaultAgent` setting pointing plain sessions at another agent, on either engine. It only reads Kiro's settings, and it cannot see a `--agent-engine v1` flag passed on the command line. `dg remove kiro [--workspace <dir>]` deletes the files dg installed and the folders it created, if they're empty. Other workspaces stay connected.
|
|
92
|
+
|
|
93
|
+
Things to know:
|
|
94
|
+
|
|
95
|
+
- **Kiro CLI only.** The hooks are verified on `kiro-cli` 2.27, on the default engine and `--v3`: they run and they block. The two engines send different tool names and inputs, and the plugin registers the tool catalog of the engine a session runs, so a guardrail written for one engine's names does not match the other (see the [plugin README](../kiro/README.md#tool-catalog)). The Kiro IDE reads the same hook files, but whether it runs them the same way is unconfirmed. Setup and `dg status` both say so.
|
|
96
|
+
- **On the default engine, only the default agent is covered.** Hooks there belong to an agent, so a session started with `--agent <name>`, or switched with `/agent`, runs none of ours. Setup and `dg status` both say so.
|
|
97
|
+
- **The default agent can be the user's.** If `.kiro/agents/kiro_default.json` already exists, dg adds one entry per event to its `hooks` and changes nothing else, the way it treats Claude Code's `settings.json`. Its entries are recognized by their command, `node dist/index.js`. A file that isn't valid JSON is never rewritten: setup stops. `dg remove` deletes the file only if dg created it and it hasn't changed since; otherwise it takes its own entries out and keeps the rest. The agent dg creates has all tools, `includeMcpJson`, and the built-in agent's resources, but no `prompt`.
|
|
98
|
+
- **The layout is the plugin's own.** Its hook files run `node dist/index.js` relative to the workspace, and it reads `kiro.json` from the folder above `dist/`, so the hook files are installed unchanged. That is why a workspace that builds to `dist/index.js` can't be set up.
|
|
99
|
+
- **`kiro.json` holds the API key.** Keep it out of git. dg doesn't edit `.gitignore`; `dg status` warns if git isn't ignoring the file.
|
|
100
|
+
- **Ownership is per file.** `.kiro/.datagusto-install.json` lists each installed file with its hash. `dg remove` deletes only files that still match, so if the project's build has since written its own `dist/index.js`, that file is left and reported. Your own hooks in `.kiro/hooks/` and other files in `dist/` are never touched.
|
|
101
|
+
- The plugin's `package.json` is installed as `dist/package.json`, so node loads the plugin as ESM even in a CommonJS project.
|
|
102
|
+
- A build step that empties `dist/` deletes the plugin. Kiro treats a hook that can't start as a warning and lets the tool call through, so check `dg status` after changing the build; it fails when plugin files are missing.
|
|
103
|
+
|
|
104
|
+
## The API key is never a flag
|
|
105
|
+
|
|
106
|
+
A flag value ends up in shell history and in `ps` output, so `dg` reads the key from one of these sources, in this order:
|
|
107
|
+
|
|
108
|
+
1. the `DATAGUSTO_API_KEY` environment variable
|
|
109
|
+
2. stdin, when it is piped: `pbpaste | dg setup claude-code`
|
|
110
|
+
3. a hidden prompt, when stdin is a terminal
|
|
111
|
+
|
|
112
|
+
`--api-key` is rejected. The "Connect your agent" page in the platform has to show one of the forms above.
|
|
113
|
+
|
|
114
|
+
## Bundled plugins
|
|
115
|
+
|
|
116
|
+
`npm run vendor` (`scripts/vendor-plugins.mjs`) does a clean build of `../claude_code` and copies its runtime files into `vendor/claude_code/`: `dist/*.js`, `.claude-plugin/`, `hooks/`, `package.json` (needed for `"type": "module"`) and `README.md`. It does the same for `../kiro` into `vendor/kiro/`: `dist/*.js`, `.kiro/hooks/` and `package.json`. Then `scripts/write-vendor-manifest.mjs` records a sha256 for every file in `vendor/manifest.json`.
|
|
117
|
+
|
|
118
|
+
Setup refuses to install if the bundled files don't match the manifest, and `dg status` compares the installed files against the hashes copied into the install's marker. `vendor/` is git-ignored. `npm test` and `prepublishOnly` regenerate it, so the npm package always ships a fresh build.
|
|
119
|
+
|
|
120
|
+
## Layout
|
|
121
|
+
|
|
122
|
+
| Path | What it does |
|
|
123
|
+
|---|---|
|
|
124
|
+
| `src/commands/` | One file per command (oclif) |
|
|
125
|
+
| `src/adapters/claude-code.ts` | Claude Code adapter: detect, plan, apply, clear, doctor |
|
|
126
|
+
| `src/adapters/claude-settings.ts` | Reads and edits the `hooks` in `~/.claude/settings.json` without touching anything else |
|
|
127
|
+
| `src/adapters/kiro.ts` | Kiro adapter: the same five steps, per workspace |
|
|
128
|
+
| `src/adapters/kiro-agent.ts` | Reads and edits the hooks in a Kiro agent config without touching the rest of it |
|
|
129
|
+
| `src/adapters/index.ts` | Adapter registry and the default adapter context |
|
|
130
|
+
| `src/adapters/types.ts` | Per-agent contract: `detect`, `plan`, `apply`, `clear`, `doctor` |
|
|
131
|
+
| `src/api/client.ts` | Bearer agent-key client, `GET /api/v1/public/safety/whoami` |
|
|
132
|
+
| `src/api/errors.ts` | Failed API calls → one plain-English sentence with the next step |
|
|
133
|
+
| `src/key-input.ts` | Key from env / stdin / hidden prompt, plus a format check |
|
|
134
|
+
| `src/state/installs.ts` | `~/.datagusto/installs.json` ledger: paths and agent id only, dir `0700`, file `0600` |
|
|
135
|
+
| `src/fs/atomic.ts` | Crash-safe writes: temp file → chmod → rename |
|
|
136
|
+
| `src/vendor.ts` | Reads `vendor/manifest.json` and checks file hashes |
|
|
137
|
+
| `scripts/` | `vendor-plugins.mjs` and `write-vendor-manifest.mjs`, plus `dev-whoami-stub.mjs` (dev only, not in the npm package) |
|
|
138
|
+
|
|
139
|
+
`DATAGUSTO_HOME` overrides `~/.datagusto`. It's used by the tests and is handy when trying things locally.
|
|
140
|
+
|
|
141
|
+
## Development
|
|
142
|
+
|
|
143
|
+
```sh
|
|
144
|
+
npm install
|
|
145
|
+
npm test # vendors ../claude_code and ../kiro, builds, then runs node --test tests/
|
|
146
|
+
./bin/run.js --help
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Needs Node 22 or later, on macOS, Linux or Windows. GitHub Actions runs the tests on all three (`.github/workflows/cli-test.yml`). The tests use a throwaway `HOME` and a local stand-in for the Datagusto API, so they never touch your real `~/.claude`. The Kiro tests use a throwaway workspace as well.
|
|
150
|
+
|
|
151
|
+
To try it by hand without touching your real home:
|
|
152
|
+
|
|
153
|
+
```sh
|
|
154
|
+
T=$(mktemp -d) && mkdir $T/.claude
|
|
155
|
+
DATAGUSTO_API_KEY=agt_live_… HOME=$T ./bin/run.js setup claude-code --server-url http://localhost:8000
|
|
156
|
+
HOME=$T ./bin/run.js status # should show ✔ Hooks: 7 events in ~/.claude/settings.json
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
To try Kiro by hand with no Datagusto server to point at, `scripts/dev-whoami-stub.mjs` answers whoami for any `agt_…` key. It answers every other path with `200 {}`, so it is only good for setup, status and remove:
|
|
160
|
+
|
|
161
|
+
```sh
|
|
162
|
+
node scripts/dev-whoami-stub.mjs 8787 # terminal 1; Ctrl-C to stop
|
|
163
|
+
|
|
164
|
+
T=$(mktemp -d) && mkdir -p $T/home $T/ws # terminal 2: throwaway HOME and workspace
|
|
165
|
+
export DATAGUSTO_API_KEY=agt_live_anything
|
|
166
|
+
HOME=$T/home ./bin/run.js setup kiro --workspace $T/ws --server-url http://127.0.0.1:8787
|
|
167
|
+
find $T/ws -type f # dist/, kiro.json, .kiro/hooks/datagusto-*.json, .kiro/agents/kiro_default.json
|
|
168
|
+
HOME=$T/home ./bin/run.js status # ✔ Plugin files, ✔ Hooks (--v3), ✔ Hooks (default engine), agent "stub-agent"
|
|
169
|
+
HOME=$T/home ./bin/run.js remove kiro --workspace $T/ws
|
|
170
|
+
find $T/ws # only the empty folder is left
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Live check (manual, before release)
|
|
174
|
+
|
|
175
|
+
Datagusto runs no shared staging server, so this needs a Datagusto server you run yourself (one that has the whoami endpoint) and an agent key from its dashboard.
|
|
176
|
+
|
|
177
|
+
1. `dg setup claude-code --server-url <your server>` with that agent key. `dg status` shows the agent name.
|
|
178
|
+
2. Start `claude` in a scratch project and ask it to run `ls`. The call shows up in the dashboard's guardrail logs for that agent.
|
|
179
|
+
3. With a guardrail that blocks a tool, the tool call is denied in Claude Code.
|
|
180
|
+
4. Change `serverUrl` in `~/.datagusto/claude-code/claude-code.json` to an unreachable address. Tool calls are denied (fail-closed).
|
|
181
|
+
5. `dg remove claude-code`, then check that `~/.claude/settings.json` has no Datagusto hooks left, and revoke the key.
|
|
182
|
+
|
|
183
|
+
## Decisions
|
|
184
|
+
|
|
185
|
+
- **oclif, not Commander.js.** The plan allowed falling back to Commander if oclif's scaffolding slowed down day 1. It didn't: `@oclif/core` v5 needs one `bin/run.js` and an `oclif` block in `package.json`, and it gives us generated help, arg validation and the `datagusto` alias for free.
|
|
186
|
+
- **Hooks in `settings.json`, not a skills-folder plugin.** See [How the plugin is wired in](#how-the-plugin-is-wired-in-and-why). One method works on every Claude Code version; the cost is editing a file the user owns, which dg limits to its own entries.
|
|
187
|
+
- **Replace the whole folder on re-run.** The new folder is built in a staging directory next to the target and renamed into place. The old one is restored if the rename fails, so the plugin files never mix two versions.
|
package/bin/run.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type ApiResult, type WhoamiResponse } from "../api/client.js";
|
|
2
|
+
import { type Platform } from "../platform.js";
|
|
3
|
+
import type { InstallRecord } from "../state/installs.js";
|
|
4
|
+
import { type HooksConfig } from "./claude-settings.js";
|
|
5
|
+
import { type AdapterContext, type AgentAdapter, type ClearResult, type DetectResult, type DoctorReport, type InstallPlan, type PluginConnection } from "./types.js";
|
|
6
|
+
/** Oldest Claude Code dg will set up: has SessionStart + UserPromptSubmit. */
|
|
7
|
+
export declare const MIN_HOOKS_VERSION = "1.0.62";
|
|
8
|
+
/**
|
|
9
|
+
* First Claude Code release with each hook event, from its CHANGELOG.md.
|
|
10
|
+
* PostToolUseFailure's first changelog mention is 2.1.119, so that is used as
|
|
11
|
+
* a safe lower bound. Events not listed are never written to settings.json.
|
|
12
|
+
*/
|
|
13
|
+
export declare const HOOK_EVENT_SINCE: Record<string, string>;
|
|
14
|
+
export interface ClaudeCodeAdapterDeps {
|
|
15
|
+
whoami?: (serverUrl: string, apiKey: string) => Promise<ApiResult<WhoamiResponse>>;
|
|
16
|
+
/** `claude --version` output, or undefined if it can't be run. */
|
|
17
|
+
claudeVersion?: (env: NodeJS.ProcessEnv) => Promise<string | undefined>;
|
|
18
|
+
}
|
|
19
|
+
export declare class ClaudeCodeAdapter implements AgentAdapter {
|
|
20
|
+
readonly name: "claude-code";
|
|
21
|
+
readonly displayName = "Claude Code";
|
|
22
|
+
private readonly whoami;
|
|
23
|
+
private readonly claudeVersion;
|
|
24
|
+
constructor(deps?: ClaudeCodeAdapterDeps);
|
|
25
|
+
pluginDir(ctx: AdapterContext): string;
|
|
26
|
+
installedServerUrl(ctx: AdapterContext): Promise<string | undefined>;
|
|
27
|
+
/** ~/.claude/skills/datagusto-safety, removed on setup if dg created it. */
|
|
28
|
+
legacySkillsDir(ctx: AdapterContext): string;
|
|
29
|
+
settingsPath(ctx: AdapterContext): string;
|
|
30
|
+
detect(ctx: AdapterContext): Promise<DetectResult>;
|
|
31
|
+
plan(ctx: AdapterContext, _conn: PluginConnection): Promise<InstallPlan>;
|
|
32
|
+
apply(ctx: AdapterContext, _plan: InstallPlan, conn: PluginConnection): Promise<InstallRecord>;
|
|
33
|
+
clear(ctx: AdapterContext, record: InstallRecord): Promise<ClearResult>;
|
|
34
|
+
doctor(ctx: AdapterContext, record: InstallRecord): Promise<DoctorReport>;
|
|
35
|
+
/** Parsed `claude --version` (undefined if it can't be run); throws if too old. */
|
|
36
|
+
private supportedVersion;
|
|
37
|
+
/** Drop hooks pointing into `dirs` from settings.json; true if any went. */
|
|
38
|
+
private removeSettingsHooks;
|
|
39
|
+
private checkClaudeVersion;
|
|
40
|
+
private checkSettingsHooks;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* The plugin's hooks.json rewritten for settings.json: ${CLAUDE_PLUGIN_ROOT}
|
|
44
|
+
* becomes the absolute plugin folder (only plugins get that variable), and
|
|
45
|
+
* events `version` doesn't know are left out.
|
|
46
|
+
*/
|
|
47
|
+
export declare function settingsHooks(pluginHooks: HooksConfig, pluginDir: string, version: string | undefined, platform?: Platform): HooksConfig;
|
|
48
|
+
export declare function compareVersions(a: string, b: string): number;
|