opencode-skill-audit 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +93 -39
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://github.com/DepickereSven/skill-audit/actions/workflows/ci.yml)
|
|
4
4
|
[](LICENSE)
|
|
5
|
+
[](https://www.npmjs.com/package/opencode-skill-audit)
|
|
6
|
+
[](#claude-code)
|
|
7
|
+
[](#codex)
|
|
8
|
+
[](#opencode)
|
|
5
9
|
|
|
6
10
|
Deterministic audit trail for [Claude Code](https://code.claude.com),
|
|
7
11
|
[Codex](https://developers.openai.com/codex/) and [opencode](https://opencode.ai) sessions: which
|
|
@@ -29,7 +33,7 @@ with no command to run.
|
|
|
29
33
|
You ask an agent to follow a skill. Did it? Reading the transcript to find out is slow, and asking
|
|
30
34
|
another model to judge costs tokens and is itself non-deterministic.
|
|
31
35
|
|
|
32
|
-
LLMs are not deterministic
|
|
36
|
+
LLMs are not deterministic. Hook events are. This plugin logs the facts exposed by each host's
|
|
33
37
|
documented hook API:
|
|
34
38
|
|
|
35
39
|
- **No LLM judging, no tokens.** Everything except the two in-session slash/skill commands runs
|
|
@@ -43,6 +47,7 @@ documented hook API:
|
|
|
43
47
|
|
|
44
48
|
## Contents
|
|
45
49
|
|
|
50
|
+
- [Why](#why)
|
|
46
51
|
- [How it works](#how-it-works)
|
|
47
52
|
- [Install](#install)
|
|
48
53
|
- [Verify the install](#verify-the-install)
|
|
@@ -60,8 +65,9 @@ documented hook API:
|
|
|
60
65
|
`PostToolUse` hooks capture skill-tool calls and file edits. On Codex, a `UserPromptSubmit` hook
|
|
61
66
|
also captures explicit `$skill-name` references, and `apply_patch` payloads are expanded into one
|
|
62
67
|
file event per path. On opencode a plugin does the same job through the `tool.execute.after` hook.
|
|
63
|
-
Events are appended as NDJSON to `~/.claude/skill-audit/<session_id>.ndjson
|
|
64
|
-
|
|
68
|
+
Events are appended as NDJSON to `~/.claude/skill-audit/<session_id>.ndjson`. All three hosts
|
|
69
|
+
write to that one directory on purpose, so any viewer can read any host's session. Override the
|
|
70
|
+
location with `SKILL_AUDIT_DIR`.
|
|
65
71
|
|
|
66
72
|
```text
|
|
67
73
|
Claude Code / Codex ──hooks───▶ logger.sh ──┐
|
|
@@ -111,12 +117,14 @@ Invoke the bundled Codex skill with `$skill-audit`.
|
|
|
111
117
|
opencode plugin opencode-skill-audit --global
|
|
112
118
|
```
|
|
113
119
|
|
|
114
|
-
|
|
115
|
-
`skill
|
|
116
|
-
current session's timeline live.
|
|
120
|
+
The plugin is published on npm as
|
|
121
|
+
[`opencode-skill-audit`](https://www.npmjs.com/package/opencode-skill-audit).
|
|
117
122
|
|
|
123
|
+
Restart opencode so the plugin loads. It registers two things: a server hook that logs
|
|
124
|
+
`skill`, `edit`, `write`, `multiedit`, `apply_patch` and `patch` tool calls, and a sidebar section
|
|
125
|
+
that renders the current session's timeline live.
|
|
118
126
|
|
|
119
|
-

|
|
120
128
|
|
|
121
129
|
Click the header to collapse the section, or a skill row to fold its files away.
|
|
122
130
|
|
|
@@ -146,7 +154,7 @@ ln -sf ~/.codex/plugins/cache/*/skill-audit/*/scripts/skill-audit ~/.local/bin/s
|
|
|
146
154
|
|
|
147
155
|
You can also clone this repository and link `scripts/skill-audit` directly.
|
|
148
156
|
|
|
149
|
-
`~/.local/bin` is not on every system's `PATH`. Check with `command -v skill-audit
|
|
157
|
+
`~/.local/bin` is not on every system's `PATH`. Check with `command -v skill-audit`. If it prints
|
|
150
158
|
nothing, add the directory in your shell profile:
|
|
151
159
|
|
|
152
160
|
```bash
|
|
@@ -182,7 +190,8 @@ installing.
|
|
|
182
190
|
- Claude Code: `/skill-audit`
|
|
183
191
|
- Codex: `$skill-audit`
|
|
184
192
|
- opencode: watch the sidebar section appear
|
|
185
|
-
2. Check that a log exists and is growing
|
|
193
|
+
2. Check that a log exists and is growing. Look in `~/.claude/skill-audit`, or in the directory
|
|
194
|
+
you set as `SKILL_AUDIT_DIR`:
|
|
186
195
|
|
|
187
196
|
```bash
|
|
188
197
|
ls -la ~/.claude/skill-audit/
|
|
@@ -195,7 +204,7 @@ installing.
|
|
|
195
204
|
skill-audit status # counts + recent timeline for the newest session
|
|
196
205
|
```
|
|
197
206
|
|
|
198
|
-
If `list` prints `no session logs in ...`, nothing was written
|
|
207
|
+
If `list` prints `no session logs in ...`, nothing was written. Go to
|
|
199
208
|
[Troubleshooting](#troubleshooting).
|
|
200
209
|
|
|
201
210
|
## Usage
|
|
@@ -204,16 +213,16 @@ If `list` prints `no session logs in ...`, nothing was written — go to
|
|
|
204
213
|
|----------------------------|------------------------------------------------------------------|-----------:|
|
|
205
214
|
| `skill-audit status [sid]` | Compact counts and recent timeline | 0 |
|
|
206
215
|
| `skill-audit report [sid]` | Full timeline | 0 |
|
|
207
|
-
| `skill-audit watch [sid]` | Live view, refreshed every two seconds
|
|
216
|
+
| `skill-audit watch [sid]` | Live view, refreshed every two seconds. `q` quits | 0 |
|
|
208
217
|
| `skill-audit list` | Recent sessions | 0 |
|
|
209
218
|
| `skill-audit --help` | Usage summary | 0 |
|
|
210
|
-
| `! skill-audit status` | Run inside a Claude Code session
|
|
211
|
-
| opencode sidebar | Live timeline beside the conversation
|
|
219
|
+
| `! skill-audit status` | Run inside a Claude Code session. Queues while the model is busy | 0 |
|
|
220
|
+
| opencode sidebar | Live timeline beside the conversation. No command to run | 0 |
|
|
212
221
|
| `/skill-audit` | Show the report inside Claude Code | Model turn |
|
|
213
222
|
| `$skill-audit` | Show the report inside Codex | Model turn |
|
|
214
223
|
|
|
215
224
|
`status`, `report` and `watch` all take an optional session ID. Without one they use the most
|
|
216
|
-
recently modified log, which is the wrong session if you run several at once
|
|
225
|
+
recently modified log, which is the wrong session if you run several at once. Get the ID from
|
|
217
226
|
`skill-audit list` and pass it explicitly.
|
|
218
227
|
|
|
219
228
|
The `⚠ edits outside skill context` counter is the compliance red flag: files changed while no
|
|
@@ -231,13 +240,13 @@ One NDJSON file per session, one event per line, appended in chronological order
|
|
|
231
240
|
| Field | On | Meaning |
|
|
232
241
|
|-----------|---------|-------------------------------------------------------------------------------|
|
|
233
242
|
| `ts` | both | UTC timestamp, `YYYY-MM-DDThh:mm:ssZ` |
|
|
234
|
-
| `kind` | both | `skill` or `file
|
|
243
|
+
| `kind` | both | `skill` or `file`, the only two event kinds |
|
|
235
244
|
| `cwd` | both | Session working directory as reported by the host |
|
|
236
245
|
| `name` | `skill` | Skill identifier, e.g. `superpowers:test-driven-development` |
|
|
237
|
-
| `args` | `skill` | Arguments passed to the skill tool
|
|
246
|
+
| `args` | `skill` | Arguments passed to the skill tool, empty string when there were none |
|
|
238
247
|
| `source` | `skill` | `tool` for an observed skill tool call, `prompt` for a Codex `$skill-name` |
|
|
239
|
-
| `turn_id` | `skill` | Codex turn identifier
|
|
240
|
-
| `tool` | `file` | Tool that made the edit: `Edit`, `Write`, `
|
|
248
|
+
| `turn_id` | `skill` | Codex turn identifier, present only when the host supplies one |
|
|
249
|
+
| `tool` | `file` | Tool that made the edit: `Edit`, `Write`, `MultiEdit`, `apply_patch`, etc. |
|
|
241
250
|
| `path` | `file` | Absolute path of the changed file (relative paths are resolved against `cwd`) |
|
|
242
251
|
|
|
243
252
|
Within a Codex turn, a repeated `(turn_id, name)` skill pair is written once, so a skill named
|
|
@@ -257,7 +266,7 @@ find ~/.claude/skill-audit -name '*.ndjson' -mtime +30 -delete
|
|
|
257
266
|
session keeps running without them.
|
|
258
267
|
- Confirm the plugin is installed: `claude plugin list`, `codex plugin list`, or check the
|
|
259
268
|
`plugin` array in `~/.config/opencode/opencode.json`.
|
|
260
|
-
- On Codex, hooks only run after you review and trust them
|
|
269
|
+
- On Codex, hooks only run after you review and trust them, so accept the prompt.
|
|
261
270
|
- Is `jq` installed? `logger.sh` exits silently without it, by design: the hook must never block a
|
|
262
271
|
session. Check with `command -v jq`.
|
|
263
272
|
|
|
@@ -269,13 +278,13 @@ recently modified log, which is the wrong one when sessions run in parallel. Run
|
|
|
269
278
|
and pass the ID: `skill-audit report <sid>`.
|
|
270
279
|
|
|
271
280
|
**The CLI finds nothing but the logs exist.** Writer and viewer disagree about the directory. If
|
|
272
|
-
you set `SKILL_AUDIT_DIR` for the host, export it for your shell too
|
|
281
|
+
you set `SKILL_AUDIT_DIR` for the host, export it for your shell too. Otherwise the CLI looks in
|
|
273
282
|
`~/.claude/skill-audit`.
|
|
274
283
|
|
|
275
|
-
**`skill-audit: command not found`.** The symlink is missing or its directory is not on `PATH
|
|
276
|
-
|
|
284
|
+
**`skill-audit: command not found`.** The symlink is missing or its directory is not on `PATH`.
|
|
285
|
+
See [CLI on your PATH](#cli-on-your-path-recommended).
|
|
277
286
|
|
|
278
|
-
**A skill ran but is missing from the timeline.** Expected in some cases
|
|
287
|
+
**A skill ran but is missing from the timeline.** Expected in some cases. See
|
|
279
288
|
[Honest limitations](#honest-limitations).
|
|
280
289
|
|
|
281
290
|
## Honest limitations
|
|
@@ -283,19 +292,19 @@ see [CLI on your PATH](#cli-on-your-path-recommended).
|
|
|
283
292
|
- **Invocation is not compliance.** The log proves that a skill was explicitly selected or exposed
|
|
284
293
|
as a tool event, not that the result followed every instruction.
|
|
285
294
|
- **Codex automatic skill loading is not a hook event today.** Explicit `$skill-name` references
|
|
286
|
-
are captured
|
|
295
|
+
are captured. Skills that Codex chooses automatically are not. No transcript parsing is used to
|
|
287
296
|
fill that gap.
|
|
288
297
|
- **Prompt-sourced entries are syntax-level evidence.** Codex supplies plain prompt text to the
|
|
289
298
|
hook, so a lower-case dollar-prefixed token can be logged even if it does not resolve to an
|
|
290
299
|
installed skill. The NDJSON `source: "prompt"` field distinguishes these entries.
|
|
291
|
-
- **Only observable file tools are captured.** Claude `Edit`/`Write`/`NotebookEdit`,
|
|
292
|
-
`apply_patch`, and opencode `edit`/`write`/`apply_patch` edits are
|
|
293
|
-
indirectly by shell commands are not visible as separate file events.
|
|
300
|
+
- **Only observable file tools are captured.** Claude `Edit`/`Write`/`MultiEdit`/`NotebookEdit`,
|
|
301
|
+
Codex `apply_patch`, and opencode `edit`/`write`/`multiedit`/`apply_patch`/`patch` edits are
|
|
302
|
+
logged. Files created indirectly by shell commands are not visible as separate file events.
|
|
294
303
|
- **opencode agents and subagents are not logged.** They have no equivalent on the other two
|
|
295
304
|
hosts, so logging them would add an event kind only one host can emit. The audit keeps one data
|
|
296
305
|
model across all three.
|
|
297
306
|
- **Session-start injected skills** are context, not skill tool calls, and do not appear.
|
|
298
|
-
- **Concurrent sessions:** the newest-log default can pick the wrong session
|
|
307
|
+
- **Concurrent sessions:** the newest-log default can pick the wrong session. Pass the session ID
|
|
299
308
|
explicitly after using `skill-audit list`.
|
|
300
309
|
|
|
301
310
|
## Uninstall
|
|
@@ -312,7 +321,7 @@ Codex:
|
|
|
312
321
|
codex plugin remove skill-audit@depickeresven-skill-audit
|
|
313
322
|
```
|
|
314
323
|
|
|
315
|
-
opencode has no removal subcommand
|
|
324
|
+
opencode has no removal subcommand. Delete the `"opencode-skill-audit"` entry from the `plugin`
|
|
316
325
|
array in `~/.config/opencode/opencode.json` (or the project-local `opencode.json`), and remove the
|
|
317
326
|
skill symlink if you made one:
|
|
318
327
|
|
|
@@ -327,17 +336,23 @@ rm -f ~/.local/bin/skill-audit
|
|
|
327
336
|
rm -rf ~/.claude/skill-audit
|
|
328
337
|
```
|
|
329
338
|
|
|
330
|
-
## Requirements
|
|
331
|
-
|
|
332
|
-
- macOS or Linux
|
|
333
|
-
- `bash` and `jq` for the CLI viewer and the Claude Code / Codex hooks
|
|
334
|
-
- opencode `>= 1.14` for the plugin and its sidebar
|
|
335
|
-
|
|
336
339
|
## Development
|
|
337
340
|
|
|
338
341
|
The hooks and the CLI viewer are plain bash (`scripts/`) with no build step. The opencode plugin
|
|
339
342
|
and sidebar are TypeScript (`src/`) built with [Bun](https://bun.sh).
|
|
340
343
|
|
|
344
|
+
| Path | What |
|
|
345
|
+
|-------------------|----------------------------------------------------------------------------|
|
|
346
|
+
| `scripts/` | `logger.sh` hook target, the `skill-audit` CLI, `sync-versions.mjs` |
|
|
347
|
+
| `src/` | opencode plugin (`index.ts`), sidebar (`tui.ts`), shared log and view code |
|
|
348
|
+
| `test/` | Bun tests, fixtures, and `test/format-contract.sh` |
|
|
349
|
+
| `.claude-plugin/` | Claude Code plugin manifest and marketplace entry |
|
|
350
|
+
| `.codex-plugin/` | Codex plugin manifest |
|
|
351
|
+
| `.agents/` | Codex marketplace manifest |
|
|
352
|
+
| `skills/` | The `skill-audit` skill used by Codex and opencode |
|
|
353
|
+
| `commands/` | The `/skill-audit` slash command for Claude Code |
|
|
354
|
+
| `.opencode/` | Local opencode workspace for testing the plugin during development |
|
|
355
|
+
|
|
341
356
|
```bash
|
|
342
357
|
bun install
|
|
343
358
|
bun run check # format:check + lint + typecheck (src and test) + tests
|
|
@@ -355,12 +370,51 @@ bun run build # dist/index.js (plugin) and dist/tui.js (sidebar)
|
|
|
355
370
|
| `bun run sync:versions` | Rewrite the plugin manifests from `package.json` |
|
|
356
371
|
|
|
357
372
|
Tests live in `test/`. `test/format-contract.sh` pins the rendered CLI output against fixtures, so
|
|
358
|
-
a change to the timeline format has to be updated there deliberately
|
|
373
|
+
a change to the timeline format has to be updated there deliberately. That output is the contract
|
|
359
374
|
the sidebar and any third-party viewer rely on.
|
|
360
375
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
376
|
+
### Releasing
|
|
377
|
+
|
|
378
|
+
Two workflows, chained.
|
|
379
|
+
|
|
380
|
+
`.github/workflows/ci.yml` runs four jobs: it checks that both plugin manifests carry the same
|
|
381
|
+
version as `package.json`, runs `bun run check` on Bun 1.2.0 and on the latest Bun, builds the
|
|
382
|
+
bundles, and packs the npm tarball to confirm it ships every entry point `package.json` exports.
|
|
383
|
+
It runs on pull requests and on pushes to `main`, not on every branch, so a pull request is never
|
|
384
|
+
tested twice.
|
|
385
|
+
|
|
386
|
+
`.github/workflows/publish.yml` starts only when a CI run on `main` finishes successfully. It
|
|
387
|
+
checks out that exact commit and asks npm whether the version in `package.json` already exists:
|
|
388
|
+
|
|
389
|
+
- **Already on npm.** Nothing is released. This is what an ordinary push to `main` does.
|
|
390
|
+
- **Not on npm.** It publishes with provenance over OIDC, tags the commit, and opens a GitHub
|
|
391
|
+
release with notes generated from the merged commits.
|
|
392
|
+
|
|
393
|
+
So a version bump landing on `main` *is* the release, and it can only happen after CI has gone
|
|
394
|
+
green on that commit.
|
|
395
|
+
|
|
396
|
+
To cut one:
|
|
397
|
+
|
|
398
|
+
```bash
|
|
399
|
+
npm version patch --no-git-tag-version # or minor / major
|
|
400
|
+
git commit -am "chore: release $(node -p 'require("./package.json").version')"
|
|
401
|
+
git push
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
`--no-git-tag-version` matters. The workflow creates the `v<version>` tag itself, and it aborts
|
|
405
|
+
the release if that tag already exists while npm has never seen the version. The bump still runs
|
|
406
|
+
`scripts/sync-versions.mjs` and stages `.claude-plugin/plugin.json` and `.codex-plugin/plugin.json`
|
|
407
|
+
alongside it, keeping both manifests on the same version as `package.json`, which CI fails the
|
|
408
|
+
build over if they ever drift.
|
|
409
|
+
|
|
410
|
+
Use the publish workflow's manual trigger (`workflow_dispatch`) with *dry run* enabled to rehearse
|
|
411
|
+
a publication without releasing anything.
|
|
412
|
+
|
|
413
|
+
## Requirements
|
|
414
|
+
|
|
415
|
+
- macOS or Linux
|
|
416
|
+
- `bash` and `jq` for the CLI viewer and the Claude Code / Codex hooks
|
|
417
|
+
- opencode `>= 1.14` for the plugin and its sidebar
|
|
364
418
|
|
|
365
419
|
## License
|
|
366
420
|
|