Skip to content

Commit 8428e89

Browse files
docs(claude-code): lead with why, add quickstart and drift-to-approve loop
Rewrite the plugin README so a Claude Code user gets the importance in the first screen: the composition (skills, permissions, MCP, instruction layer) is what decides what the agent can do, and it drifts silently. Adds a concrete threat list, a ~60s quickstart with the real first-session baseline message, and the everyday warning -> /manifest verify -> /manifest approve loop with real engine output. Keeps the honest "known limits" section. Polishes both command docs to match and to reflect verify's fresh re-snapshot. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 78297e7 commit 8428e89

3 files changed

Lines changed: 186 additions & 77 deletions

File tree

claude-code/README.md

Lines changed: 145 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,182 @@
11
# AgenTrust for Claude Code
22

3-
Agent-integrity for the coding agent you already use. This plugin captures, every
4-
session:
3+
**Know your coding agent hasn't changed behind your back.**
54

6-
- an **Agent Manifest** — what your Claude agent *is*: skills, tools, MCP servers,
7-
model, permission policy, and instruction layer, each fingerprinted and signed
8-
([agent-manifest](https://github.com/agentrust-io/agent-manifest)).
9-
- a **TRACE Trust Record** — what your agent *did* this run, signed and
10-
conformance-checkable ([trace](https://github.com/agentrust-io/trace-spec)).
5+
Claude Code is not just a model. It is a model plus everything you have wired
6+
around it: skills in `~/.claude/skills`, an allow/deny permission policy, MCP
7+
servers, your `CLAUDE.md` and memory, and the tools it can call. That whole
8+
composition decides what your agent can do to your machine and your code. Any of
9+
it can change without you noticing.
1110

12-
and answers the one question that matters on a developer box:
11+
This plugin answers one question at the start of every session:
1312

14-
> **Is the agent I'm running the one I approved nothing added, nothing subtracted?**
13+
> **Is the agent I'm running the one I approved: nothing added, nothing subtracted?**
1514
16-
A rogue skill dropped into `~/.claude/skills`, a widened permission, an edited
17-
`CLAUDE.md`, or an unexpected MCP server all change a fingerprint, and the next
18-
SessionStart tells you.
15+
## Why this matters
1916

20-
## What it does
17+
You approved a setup you trust. Then, quietly, things drift:
2118

22-
| Surface | What runs | Needs crypto packages? |
23-
|---|---|---|
24-
| **SessionStart hook** | snapshot the agent from disk, diff against your approved baseline, warn in-session on drift | No (stdlib only) |
25-
| `/manifest verify` | full diff including the live tool/MCP roster the agent reports | No |
26-
| `/manifest approve` | make the current composition the approved baseline | No (add `--sign` for records) |
27-
| `/trace` | build + sign the Agent Manifest and TRACE record, explain them in plain English | Yes |
19+
- A skill you installed ships an update that now runs `curl` to an address you
20+
never saw.
21+
- A dependency's postinstall drops a `SKILL.md` into `~/.claude/skills`.
22+
- A permission gets widened from `Bash(git:*)` to `Bash(*)` during some debugging
23+
session and never gets narrowed back.
24+
- An MCP server you added for one task is still connected weeks later.
25+
- Your `CLAUDE.md` picks up an instruction you didn't write.
2826

29-
The hook is deliberately dependency-free so it never blocks session start. Signing
30-
runs only when you ask for records.
27+
None of these announce themselves. Each one changes what your agent will do on
28+
your next run. This plugin fingerprints the whole composition, stores an approved
29+
baseline, and tells you at session start the moment any of it moves. It is the
30+
difference between "I think my agent is what I set up" and "I can prove it, and
31+
I'd know within one session if it wasn't."
3132

32-
## Install
33+
## Quickstart (about 60 seconds)
3334

3435
```bash
35-
# 1. plugin (hooks + commands)
36+
# 1. add the marketplace and install the plugin (hooks + commands)
3637
/plugin marketplace add agentrust-io/integrations
3738
/plugin install agentrust-claude-code
39+
```
40+
41+
That's the whole install for drift detection. The SessionStart hook is
42+
dependency-free (Python standard library only), so it never blocks a session.
43+
44+
On your **first** session after install, it records your baseline and tells you:
45+
46+
```
47+
AgenTrust: baseline established for this Claude agent (7 skills, 2 MCP on disk).
48+
Future sessions are checked against it. Run /manifest approve to re-baseline.
49+
```
50+
51+
The baseline lives at `~/.claude/agentrust/baseline.json`. From then on, every
52+
session is checked against it.
53+
54+
Signed records (`/trace` and `/manifest approve --sign`) are the only feature
55+
that needs crypto packages. Install them when you want them:
3856

39-
# 2. only for signed records (/trace, /manifest approve --sign)
57+
```bash
4058
pip install -r claude-code/requirements.txt
4159
```
4260

43-
First SessionStart establishes your baseline at `~/.claude/agentrust/baseline.json`.
44-
Every later session is checked against it. Run `/manifest approve` whenever you
45-
intentionally change your setup.
61+
## The everyday loop
62+
63+
You mostly do nothing. You install it, and it stays quiet until something
64+
changes. When it does, one line shows up at session start:
65+
66+
```
67+
AgenTrust WARNING: 1 change(s) to your agent since baseline: added skill
68+
pypi-helper. Run /manifest verify for detail, or /manifest approve to accept.
69+
```
70+
71+
Two responses, both one command:
4672

47-
## What it captures (and what it does not)
73+
**If the change is a surprise**, look at it. `/manifest verify` re-reads your
74+
setup right now and lays out exactly what moved:
4875

49-
Captured, by fingerprint — never raw content, never secrets:
76+
```
77+
NOTHING ADDED, NOTHING SUBTRACTED? (vs approved baseline)
78+
--------------------------------------------------------------
79+
~ CHANGED permissions: policy_bundle
80+
+ ADDED skill: exfil
81+
>> 2 change(s) since baseline. Review above.
82+
```
5083

51-
- **skills** — each `~/.claude/skills/*/SKILL.md`
52-
- **permissions**`~/.claude/settings.json` (the allow/deny policy)
53-
- **instruction layer** — your `CLAUDE.md` / memory tree
54-
- **tools + MCP servers** — the roster the agent reports at report time
55-
- **model** — provider, id, version
84+
Now you decide with the facts in front of you: remove the rogue skill, narrow the
85+
permission, or accept it.
5686

57-
It never reads `~/.claude/.credentials.json`, and records skill / tool / MCP
58-
**names** only, never tokens or environment values.
87+
**If you made the change on purpose** (installed a skill you wanted, added an MCP
88+
server for real work), tell the plugin this is the new normal:
5989

60-
## Known gaps (read before relying on it)
90+
```
91+
/manifest approve
92+
```
6193

62-
- **Software-only, Level 0.** A normal dev box has no TEE, so the TRACE record is
63-
software-only integrity, not hardware-rooted attestation. Labelled as such.
64-
- **Instruction layer is a proxy.** The `system_prompt` fingerprint covers your
65-
`CLAUDE.md` and memory, not Claude Code's internal system prompt, which is not
66-
on disk.
67-
- **`policy_language` mismatch.** agent-manifest's `policy_language` enum
68-
(`cedar`/`rego`/`yaml-agt`/`composite`) has no value for host-native agent
69-
permission systems like Claude Code's `settings.json`. Modelled as `composite`;
70-
a spec value for host-native permissions is proposed upstream.
71-
- **Hook visibility.** A shell hook cannot enumerate the live tool roster, so the
72-
SessionStart check compares skills, permissions, and the instruction layer.
73-
The full tool/MCP diff runs in `/manifest verify`, where the agent supplies the
74-
live roster.
94+
That promotes your current setup to the approved baseline. The warnings stop
95+
until something moves again.
96+
97+
## Commands
98+
99+
| Command | What it does | Needs crypto packages? |
100+
|---|---|---|
101+
| SessionStart hook | Snapshot the agent from disk, diff against your approved baseline, warn in-session on drift | No |
102+
| `/manifest verify` | Re-snapshot now and show the full diff, including the live tool and MCP roster the agent reports this session | No |
103+
| `/manifest approve` | Make the current composition the approved baseline | No (add `--sign` for records) |
104+
| `/manifest show` | Show the current composition without touching the baseline | No |
105+
| `/trace` | Build and sign the Agent Manifest and TRACE record for this session, explained in plain English | Yes |
106+
107+
`/manifest verify` always re-reads your setup fresh, so it catches drift that
108+
happens partway through a session, not just at startup.
109+
110+
## What it captures, and what it does not
111+
112+
It records **fingerprints, never raw content, never secrets:**
113+
114+
- **skills**: each `~/.claude/skills/*/SKILL.md`
115+
- **permissions**: `~/.claude/settings.json` (the allow/deny policy)
116+
- **instruction layer**: your `CLAUDE.md` and memory tree
117+
- **tools and MCP servers**: the roster the agent reports, by name only
118+
- **model**: provider, id, version
119+
120+
It never reads `~/.claude/.credentials.json`. It records skill, tool, and MCP
121+
**names** only, never tokens, never environment values, never file contents.
122+
A changed fingerprint tells you *that* something changed and *which category*,
123+
which is what you need to go look.
124+
125+
## Signed records: Agent Manifest and TRACE
126+
127+
When you run `/trace` (or `/manifest approve --sign`), the plugin writes two
128+
signed JSON records:
129+
130+
- an **Agent Manifest**: what your agent *is*, the full composition above, each
131+
part fingerprinted and Ed25519-signed
132+
([agent-manifest](https://github.com/agentrust-io/agent-manifest)).
133+
- a **TRACE Trust Record**: what your agent *did* this run, signed and checkable
134+
against the public conformance suite
135+
([trace-spec](https://github.com/agentrust-io/trace-spec)).
136+
137+
These are shareable proof a third party can verify without trusting your machine.
138+
Confirm a record with:
139+
140+
```bash
141+
trace-tests verify --record trace.json --level 0
142+
# or, if the console script is not on PATH:
143+
python -m trace_tests.cli verify --record trace.json --level 0
144+
```
145+
146+
## Known limits (read before relying on it)
147+
148+
This plugin is honest about what it is. On a normal developer machine:
149+
150+
- **Software-only, Level 0.** A dev box has no hardware TEE, so the TRACE record
151+
is software integrity, not silicon-rooted attestation. It is labelled Level 0,
152+
never presented as hardware-attested.
153+
- **The instruction layer is a proxy.** The `system_prompt` fingerprint covers
154+
your `CLAUDE.md` and memory tree, not Claude Code's internal system prompt,
155+
which is not on disk.
156+
- **`policy_language` is modelled as `composite`.** The agent-manifest
157+
`policy_language` enum (`cedar` / `rego` / `yaml-agt` / `composite`) has no
158+
value for host-native permission systems like Claude Code's `settings.json`.
159+
A spec value for host-native permissions is proposed upstream.
160+
- **The hook sees disk, commands see the session.** A shell hook cannot enumerate
161+
the live tool roster, so the SessionStart check compares skills, permissions,
162+
and the instruction layer. The full tool and MCP diff runs in `/manifest
163+
verify`, where the agent supplies the live roster.
75164

76165
## Layout
77166

78167
```
79168
claude-code/
80169
.claude-plugin/plugin.json plugin manifest
81170
hooks/hooks.json SessionStart -> engine/capture.py hook
82-
commands/manifest.md /manifest capture | verify | approve
171+
commands/manifest.md /manifest verify | approve | show
83172
commands/trace.md /trace report
84173
engine/capture.py capture engine (stdlib hook + signing report)
85174
tests/test_capture.py stdlib-only tests
86175
integration.yaml agentrust-io integration manifest
87176
requirements.txt crypto deps for signing only
88177
```
178+
179+
## License
180+
181+
Apache-2.0. Part of the [agentrust-io](https://github.com/agentrust-io)
182+
open agent-governance toolchain.

claude-code/commands/manifest.md

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
---
2-
description: Capture, verify, or approve the integrity baseline of your Claude Code agent
2+
description: Check, approve, or show the integrity baseline of your Claude Code agent
33
argument-hint: "[verify | approve | show]"
44
---
55

6-
You are running the AgenTrust agent-integrity command. The engine is at
7-
`${CLAUDE_PLUGIN_ROOT}/engine/capture.py`. It captures the agent's composition
8-
(skills, tools, MCP servers, model, permissions, instruction layer) and diffs it
9-
against the user's approved baseline at `~/.claude/agentrust/baseline.json`.
6+
You are running the AgenTrust agent-integrity command. It answers one question
7+
for the user: is the agent they are running the one they approved, with nothing
8+
added and nothing subtracted since their baseline?
9+
10+
The engine is at `${CLAUDE_PLUGIN_ROOT}/engine/capture.py`. It captures the
11+
agent's composition (skills, tools, MCP servers, model, permissions, instruction
12+
layer) and diffs it against the approved baseline at
13+
`~/.claude/agentrust/baseline.json`.
1014

1115
The shell hook cannot see the live tool roster, so YOU enrich it. Before running,
12-
write the current session's real facts to a temp `live.json`:
16+
write the current session's real facts to a temp `live.json`. Use real values you
17+
actually observe this session, never invented ones:
1318

1419
```json
1520
{
@@ -24,13 +29,20 @@ write the current session's real facts to a temp `live.json`:
2429
Then dispatch on `$ARGUMENTS`:
2530

2631
- `verify` (default): run
27-
`python "${CLAUDE_PLUGIN_ROOT}/engine/capture.py" verify --live-context live.json`
28-
and show the "nothing added, nothing subtracted" result. Explain any change in
29-
plain language and ask whether to approve it.
30-
- `approve`: run `... approve --live-context live.json --sign --out .` to make the
31-
current composition the new approved baseline and write signed records.
32-
- `show`: run `... snapshot --live-context live.json` to display the current
33-
composition without touching the baseline.
32+
`python "${CLAUDE_PLUGIN_ROOT}/engine/capture.py" verify --live-context live.json`.
33+
Verify always re-reads the setup fresh and merges your `live.json`, so it
34+
reflects the agent's state right now, including drift introduced partway
35+
through this session. Show the result and explain any change in plain language,
36+
then ask whether to approve it.
37+
- `approve`: run
38+
`python "${CLAUDE_PLUGIN_ROOT}/engine/capture.py" approve --live-context live.json --sign --out .`
39+
to make the current composition the new approved baseline and write signed
40+
records. Use this when the user confirms the changes are intentional.
41+
- `show`: run
42+
`python "${CLAUDE_PLUGIN_ROOT}/engine/capture.py" snapshot --live-context live.json`
43+
to display the current composition without touching the baseline.
3444

35-
Report the result in plain English. Never claim hardware attestation: on a normal
36-
dev box this is software-only (Level 0) integrity, not silicon-rooted proof.
45+
Report the result in plain English. Name the categories that changed (a skill, a
46+
permission, an MCP server, the instruction layer) and what the user should do
47+
about each. Never claim hardware attestation: on a normal dev box this is
48+
software-only (Level 0) integrity, not silicon-rooted proof.

claude-code/commands/trace.md

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,25 @@ session and explain it in plain English. Engine:
99

1010
Steps:
1111

12-
1. Ensure the packages are installed (once):
13-
`pip install agent-manifest agentrust-trace "agentrust-trace-tests>=0.2"`.
14-
2. Write this session's real facts to `live.json` (do NOT invent values):
15-
`model_id`, `model_provider`, `model_version`, `builtin_tools` (your actual
16-
built-in tools), `mcp_servers` (the MCP servers actually connected now).
12+
1. Ensure the signing packages are installed (once). Prefer the pinned set:
13+
`pip install -r "${CLAUDE_PLUGIN_ROOT}/requirements.txt"`.
14+
2. Write this session's real facts to `live.json`. Use values you actually
15+
observe, never invented ones: `model_id`, `model_provider`, `model_version`,
16+
`builtin_tools` (your actual built-in tools), `mcp_servers` (the MCP servers
17+
actually connected now).
1718
3. Run
1819
`python "${CLAUDE_PLUGIN_ROOT}/engine/capture.py" report --live-context live.json --out .`
1920
4. Optionally confirm the TRACE record passes the suite:
2021
`trace-tests verify --record trace.json --level 0` (or
21-
`python -m trace_tests.cli verify ...` if the script is not on PATH).
22+
`python -m trace_tests.cli verify --record trace.json --level 0` if the
23+
console script is not on PATH).
2224

2325
Then explain the report the user actually cares about:
24-
- what the agent IS (skills, tools, MCP, model, permissions), each fingerprinted,
25-
- what it DID this run (TRACE record, software-only / Level 0 on a dev box),
26+
27+
- what the agent IS: skills, tools, MCP, model, permissions, each fingerprinted.
28+
- what it DID this run: the TRACE record, software-only and Level 0 on a dev box.
2629
- whether anything changed since their approved baseline.
2730

28-
Be honest about scope: no TEE on a normal laptop means Level 0, not hardware
29-
attestation. The "instruction layer" fingerprint covers CLAUDE.md and memory,
30-
not Claude Code's internal system prompt (which is not on disk).
31+
Be honest about scope. No TEE on a normal laptop means Level 0, not hardware
32+
attestation. The instruction-layer fingerprint covers `CLAUDE.md` and memory, not
33+
Claude Code's internal system prompt, which is not on disk.

0 commit comments

Comments
 (0)