Skip to content

plugin: add the cost-policy skill, two commands, and a Stop hook - #7

Draft
aadereiko wants to merge 2 commits into
mainfrom
sasha/plugin-cost-policy-layer
Draft

plugin: add the cost-policy skill, two commands, and a Stop hook#7
aadereiko wants to merge 2 commits into
mainfrom
sasha/plugin-cost-policy-layer

Conversation

@aadereiko

@aadereiko aadereiko commented Sep 3, 2026

Copy link
Copy Markdown

Every cipx session opens by telling the developer their Claude Code "has been optimized" and pointing them at a command. On its own that sentence is unverifiable, and until now the command it points at did not exist in the plugin. This PR ships the layer that makes the claim checkable.

What this adds

skills/cost-policy/SKILL.md — which MCP servers the org's cost policy denies for this user, how to turn one off or back on for themselves, and how to read the outcome off opik-cipx mcp's exit code (0 changed, 3 locked by an admin, 5 ambiguous, 9 backend refused, …) so a refusal is never handed back as "done". Claude pulls it in on its own, which is the whole point: Claude Code removes a denied MCP server silently — it vanishes from /mcp and claude mcp list with no warning — so this skill is usually how a user finds out what happened.

commands/cost-intelligence.md (/opik-cipx:cost-intelligence [thing]) — the receipt. What cipx changed on this machine, what org policy blocks, what this session cost, what the last 30 days cost and where the tokens went, which cost policies are in effect and who set each one, and for anything a policy turned off, the one route that turns it back on. Given an argument it answers about that one MCP server / skill / tool / settings key and nothing else. The instructions are mostly guardrails against the model retelling the report: paste the measured output, never compute a figure, never conflate the three different kinds of dollar the spend section prints (real money, at list shadow price, cash marginal), and never fill in in-plan or n/a with $0.00.

commands/mcp-policy.md (/opik-cipx:mcp-policy) — the policy table on its own, shown every time it is asked for.

hooks/hooks.json — a Stop entry, wired exactly like the existing SessionStart and UserPromptSubmit ones:

"Stop": [{"hooks": [{"type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/scripts/opik-cipx-hook-launcher stop"}]}]

The launcher is untouched — hook forward-compat is a hard rule. It ignores the event argument it is passed and always runs opik-cipx sync, which is idempotent, so this is a no-op on the current 0.0.61 binary: one extra sync at the end of a turn, the same operation UserPromptSubmit already performs at the start of one. It is here so a later binary can render its turn-end notice without needing another plugin release. Per the hooks docs a Stop hook that exits 0 with no stdout does not block or alter anything, and the launcher exits 0 even when it finds no binary.

plugins/opik-cipx/hooks.json (the Codex variant) is deliberately not changed.

⚠️ Merge only after the next cipx release

This is release-gated, which is why it is a draft. All three markdown files call opik-cipx as a bare command, and on the currently released plugin that does not work:

  • The plugin's bin/ holds only per-platform directories (bin/opik-cipx-darwin-arm64/, …), so nothing on PATH answers to opik-cipx — bare calls reach the user as exit 127 / command not found.
  • Even resolved, the 0.0.61 binary has no mcp, statusline or cost-intelligence subcommand — unknown command.

The release that follows comet-ml/cost-intelligence-proxy-internal#123 fixes both: it adds those subcommands, and its "Stage binaries into public repo bin/" step writes a bin/opik-cipx dispatcher that execs the right per-platform build. Claude Code puts an installed plugin's bin/ on the Bash tool's PATH, so that dispatcher is what makes the bare command real.

The files are copied verbatim from the PoC branch on purpose. Rewriting them here to use absolute paths would fork the two copies and hide the dependency instead of stating it; the correct fix is to merge this after the release, not to edit around it.

Validated

  • claude plugin validate . (CLI 2.1.259) — passes; the single warning (marketplace has no description) is pre-existing on main and unrelated.
  • claude plugin validate ./commands and ./skills, both plain and --strict — pass. Worth noting: --strict fails on unrecognized frontmatter fields, and it accepts argument-hint and allowed-tools, which the public docs page does not currently list.
  • claude plugin validate .claude-plugin/plugin.json — passes.
  • YAML frontmatter of both command files and the skill parses under yaml.safe_load; keys are description / argument-hint / allowed-tools and name / description / allowed-tools respectively.
  • hooks/hooks.json parses as JSON with all three events present in the right case (SessionStart, UserPromptSubmit, Stop).
  • scripts/opik-cipx-hook-launcher stop run with nothing reachable on PATH: prints its install hint and exits 0, confirming the extra event argument is harmless under set -u.
  • All three copied files are byte-identical to the PoC source (verified with diff -q).
  • skills/opik-cipx/SKILL.md, scripts/, and plugins/ are untouched.

🤖 Generated with Claude Code

Update 2026-09-03 — naming

The skill ships as cost-intelligence-policy and the MCP command as /cost-intelligence-mcp, matching the PoC branch; /cost-intelligence is unchanged. A skill named cost-intelligence would have collided with the command in Claude Code's shared command/skill namespace. Files remain byte-identical to the PoC's.

aadereiko and others added 2 commits September 3, 2026 11:12
Ships the plain-language layer that turns the session intro's "your Claude
Code has been optimized" into something a developer can check for themselves.

- skills/cost-policy/SKILL.md — which MCP servers org policy denies for this
  user, how to turn one off or back on for themselves, and how to read the
  outcome off `opik-cipx mcp`'s exit code so a refusal is never reported back
  as a success. Claude pulls it in on its own, which is the point: Claude Code
  drops a denied server silently, so the skill is usually how a user finds out
  what happened.
- commands/cost-intelligence.md — the receipt. What cipx changed on this
  machine, what is blocked, what this session and the last 30 days cost and
  where the tokens went, which cost policies are in effect and who set each
  one, and for anything a policy turned off, the one route that turns it back
  on. Takes an optional MCP server / skill / tool / settings key to answer
  about just that one thing.
- commands/mcp-policy.md — the MCP policy table on its own.
- hooks/hooks.json — a Stop entry wired exactly like SessionStart and
  UserPromptSubmit. The launcher ignores the event argument and always runs
  `opik-cipx sync`, which is idempotent, so this is a no-op on the current
  0.0.61 binary; it is here so a later binary can render its turn-end notice
  without another plugin release.

The three markdown files are copied verbatim from the PoC branch and call
`opik-cipx` as a bare command on PATH. That only resolves once the release
following comet-ml/cost-intelligence-proxy-internal#123 lands the
`bin/opik-cipx` dispatcher, so this must not merge before that release.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…intelligence-mcp

Matches the PoC branch: the skill that explains policy and drives `opik-cipx mcp`
is `cost-intelligence-policy`, the MCP slash command is `/cost-intelligence-mcp`,
and the report command keeps `/cost-intelligence`. Files are byte-identical to
the PoC's; the report command's stale "adds nothing to PATH" passage now
reflects the bin/opik-cipx dispatcher the release adds.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant