surshar / claude-code
Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.
Built by Anthropic · github.com/anthropics
| @@ -25,7 +25,8 @@ | ||
| 25 | 25 | | event | from the outermost seat | |
| 26 | 26 | | --- | --- | |
| 27 | 27 | | `classic.*` | Continue past the user tier: the organization's settings hooks see the engine's input and their answer stands. | |
| 28 | -| `prompt.section`, `prompt.context`, `prompt.compose`, `skill.prompt`, `attribution.text` | Continue past the user tier: managed CLAUDE.md, rules and policy skills reach the model as written, and the system prompt's list of sections is composed by the organization's tiers and the built-ins alone. A person's plugins keep `prompt.submit` and its additive context. | | |
| 28 | +| `prompt.section`, `prompt.context`, `skill.prompt`, `attribution.text` | Continue past the user tier: managed CLAUDE.md, rules and policy skills reach the model as written. A person's plugins keep `prompt.submit` and its additive context. | | |
| 29 | +| `prompt.compose` | Continue past the user tier: the system prompt's list of sections is what the organization's tiers, the built-ins and the engine's own composition make it. A person's plugin neither drops, reorders nor rewrites a section, nor changes the facts the list is composed from, nor answers a list of its own in its place. The engine raises this event only when some loaded plugin hooks it, so where this plugin is seated every render of the system prompt runs the chain. | | |
| 29 | 30 | | `settings.read` | Continue past the user tier: no user hook rewrites what any caller reads as settings, this plugin's own policy reads included. | |
| 30 | 31 | | `tool.describe`, `command.describe`, `agent.offer`, `agent.spawn` | When the subject's pinned `e.provider.tier` is `prepend` or `append` (a policy-installed plugin, the managed folder, a policy MCP server), continue past the user tier; a subject provided by `user`, `builtin` or `core` passes. | |
| 31 | 32 | | `tool.register` | A caller in `prepend` or `append` continues past the user tier. A `user`-tier caller is refused by name while managed settings hold `allowedMcpServers` (set at all, empty included); otherwise it passes. | |
| @@ -4,8 +4,8 @@ | ||
| 4 | 4 | * The facts of one render of the system prompt, as the engine raises them. |
| 5 | 5 | */ |
| 6 | 6 | export const COMPOSED: PromptComposeInput = { |
| 7 | - model: 'claude-sonnet-5', | |
| 8 | - promptModel: 'claude-sonnet-5', | |
| 7 | + model: 'example-model-1', | |
| 8 | + promptModel: 'example-model-1', | |
| 9 | 9 | surfaces: ['terminal'], |
| 10 | 10 | tools: ['Bash'], |
| 11 | 11 | outputStyle: null, |
| @@ -26,6 +26,7 @@ | ||
| 26 | 26 | export * from './registered-tool-of.js' |
| 27 | 27 | export * from './registering.js' |
| 28 | 28 | export * from './relabeling.js' |
| 29 | +export * from './rewording.js' | |
| 29 | 30 | export * from './server-policy.js' |
| 30 | 31 | export * from './session.js' |
| 31 | 32 | export * from './signing.js' |
| @@ -1,0 +1,23 @@ | ||
| 1 | +import type { Plugin } from 'claude-code/testing' | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * A plugin the person installed that asks for what is beneath it, then | |
| 5 | + * drops the body and rewrites the text of every section it keeps. | |
| 6 | + */ | |
| 7 | +export const rewording: Plugin = { | |
| 8 | + name: 'rewording', | |
| 9 | + register(on) { | |
| 10 | + on('prompt.compose', async ($, e, next) => { | |
| 11 | + const { sections } = await next(e) | |
| 12 | + | |
| 13 | + return { | |
| 14 | + sections: sections | |
| 15 | + .filter(section => section.id !== 'body') | |
| 16 | + .map(section => ({ | |
| 17 | + ...section, | |
| 18 | + text: `${section.text} (reworded)`, | |
| 19 | + })), | |
| 20 | + } | |
| 21 | + }) | |
| 22 | + }, | |
| 23 | +} |
| @@ -159,6 +159,7 @@ | ||
| 159 | 159 | "the system prompt's sections pass over the plugins the person installed", |
| 160 | 160 | { plugins: [Fixtures.emptying, Fixtures.heading] }, |
| 161 | 161 | async ($, on) => { |
| 162 | + on('settings.read', () => ({ value: Fixtures.NO_ALLOWLIST })) | |
| 162 | 163 | on('prompt.compose', () => ({ |
| 163 | 164 | sections: [{ id: 'body', text: 'the body', scope: 'shared' }], |
| 164 | 165 | })) |
| @@ -173,6 +174,24 @@ | ||
| 173 | 174 | ) |
| 174 | 175 | |
| 175 | 176 | test( |
| 177 | + "nor does a person's plugin drop or reword a section it asked for", | |
| 178 | + { plugins: [Fixtures.rewording, Fixtures.heading] }, | |
| 179 | + async ($, on) => { | |
| 180 | + on('settings.read', () => ({ value: Fixtures.NO_ALLOWLIST })) | |
| 181 | + on('prompt.compose', () => ({ | |
| 182 | + sections: [{ id: 'body', text: 'the body', scope: 'shared' }], | |
| 183 | + })) | |
| 184 | + | |
| 185 | + expect(await $.prompt.compose(Fixtures.COMPOSED)).toEqual({ | |
| 186 | + sections: [ | |
| 187 | + { id: 'heading:org', text: 'the org says hi', scope: 'shared' }, | |
| 188 | + { id: 'body', text: 'the body', scope: 'shared' }, | |
| 189 | + ], | |
| 190 | + }) | |
| 191 | + }, | |
| 192 | + ) | |
| 193 | + | |
| 194 | + test( | |
| 176 | 195 | "a user plugin's rewrite of policy is skipped for every other reader", |
| 177 | 196 | { |
| 178 | 197 | plugins: [ |
Large file, diff not shown.