Repository navigation
shim v1.0.1
shim-cli 1.0.1
VS Code is a supported client, through the plugin. The same release fixes a
worse problem it uncovered: a Claude Code install has been running inside VS
Code all along, and its prompt block was being ignored there.
Upgrading is uv tool upgrade shim, or /plugin update shim-cli@shim-cli in
Claude Code. There is nothing to migrate.
If you use VS Code
Point VS Code at the plugin folder:
"chat.pluginLocations": { "/path/to/shim-cli/plugins/shim-cli": true }There is no shim install vscode; the plugin is the whole route. What you get,
measured against VS Code 1.137.0 with Copilot Chat 0.65.0 rather than read out
of its documentation:
| Moment | What shim does |
|---|---|
| Your prompt | Reports the finding. Under enforce, the prompt is stopped before it is sent, and VS Code shows the reason. |
| Before a tool runs | Reports. Under enforce, the call is denied and never runs. |
| After a tool has run | Reports only. |
Nothing is masked in VS Code, and after a tool nothing is blocked either.
Both were measured. A hook answering decision: "block" on a terminal result
was followed by the model quoting the secret out of that result, and
continue: false at the same event did not stop the turn: by then the model
has been handed the output. Where Claude Code silently replaces a value with
<SECRET_1>, VS Code tells you and leaves it.
One consequence worth knowing: VS Code sends a read_file result to hooks as
an empty tool_response, so shim cannot see what a file read returned. A file
read is covered by its path before the read. A terminal result does arrive in
full and is inspected.
Because a refusal is the only enforcement available, tool events report by
default there. Ask for the refusal when you want it:
[mode]
outbound = "enforce"If you use Claude Code, read this even if you never open VS Code
VS Code loads hooks from ~/.claude/settings.json by default. So shim install claude has been registering shim in two clients at once, and in VS Code it
spoke Claude's protocol: the prompt block, decision: "block", is a field VS
Code ignores. Anyone running user-prompt = "enforce" who used VS Code had
prompts sent that shim reported as blocked.
1.0.1 tells the two apart by what each always sends — every Claude Code event
carries permission_mode and never timestamp, and every VS Code event is the
reverse — and answers each in its own protocol. A VS Code prompt is now stopped
with continue: false, which VS Code obeys. Nothing changes for Claude Code
itself.
The environment cannot be used for this and is not: the VS Code capture carried
CLAUDE_CODE_* variables, because the editor inherited them from the terminal
that started it.
Also in this release
- The shared event pipeline carries what each client grants at each event —
rewrite,refuseorreport-only— and caps the action at it. A mask
becomes a refusal where only refusal exists, and a refusal becomes a report
where the model already holds the data. The session summary follows: it says
found, notblocked, when nothing was withheld. - A hook asked for a client this build does not know now inspects nothing and
says so on stderr, instead of answering with another client's refusal. An
older package meeting a newer plugin used to block every VS Code prompt with
a message naming Codex. - The plugin carries an Agent Plugins v1 manifest,
plugins/shim-cli/plugin.json,
alongside the Claude and Codex ones. Its hooks live in
com.github.copilot/hooks/hooks.json, which GitHub Copilot CLI and the
Copilot app read as well; there the command stands down, becauseshim install copilotis their route and inspecting a prompt twice helps nobody.