* Add Claude Code plugin channel and cargo-ai auto-approve hook
- .claude-plugin/marketplace.json + plugin.json: the repo root doubles as
a Claude Code plugin (skills scan root "./" discovers all 15 top-level
skill dirs with no restructuring; plugin version mirrors the router's,
now linter-enforced).
- hooks/approve-cli.sh: allow-only PreToolUse hook that auto-approves
cargo-ai / npx @cargo-ai/cli calls and read-only pipe helpers after a
quote-aware structural pass. Never auto-approves: login/logout,
workspaceManagement token/report, cdk deploy/destroy, or any
remove/delete/destroy token. Verified with a 49-case harness plus a
live end-to-end test (clean permissions: whoami auto-approved, token
list fell through to prompt).
- README: plugin install path + pick-one-channel note; prerequisites.md
gains a "Permission prompts" section. cargo 1.9.0, plugin 1.9.0.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Pin the CLI version in cargo/cli-version
- New cargo/cli-version (1.0.29): single-line semver pin, the source of
truth for which @cargo-ai/cli these skills were written against. Lives
inside the router skill so it ships with skills add and the ClawHub
bundle; session hooks read it locally with a latest fallback, so the
pin can never block an install.
- Linter asserts the pin exists and is bare semver, and that openclaw
install blocks stay @cargo-ai/cli@latest (bootstrap only; the session
hook converges to the pin).
- Docs: router session job 1 reordered (skills add -> pinned npm
install) with a "why the pin" note; prerequisites.md and README
refresh snippets use the pinned form. cargo 1.10.0, plugin 1.10.0.
The producer side (CLI release pipeline PRs pin bumps here; install.sh
consumes the raw pin URL) lands in getcargohq/cargo separately.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(approve-cli): position-independent gating closes token-shift bypass
Review finding: gated checks only examined the first two non-flag tokens
after the binary/package. Valid invocation prefixes shift the real
subcommand out of those slots - `npx -p @cargo-ai/cli cargo-ai login`
puts a literal cargo-ai before login (confirmed auto-approved), and a
global flag with a value would shift the domain word the same way.
Fix: normalize the cargo segment's token stream once, drop leading
`cargo-ai` binary tokens, and gate position-independently - credential
tokens (login/logout), destructive verbs (remove/delete/destroy), and
gated adjacent pairs (workspaceManagement token/report, cdk
deploy/destroy) anywhere in the segment refuse approval. Accepted cost,
documented: a gated word as a literal inside a quoted argument (SQL
containing "login") now falls through to the prompt - the safe
direction for an allow-only hook.
Harness extended to 62 cases: all -p/token-shift/flag-shift bypass
shapes prompt; safe -p usage still auto-approves.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>