Document the new tools, plugins, skills, MCP panel, and item repair
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
co-authored by
Sisyphus
parent
2dc7b91c29
commit
397c4355f3
+37
-5
@@ -19,7 +19,7 @@ the agent can read. That is a sandbox problem, not a loader problem — see
|
||||
## Enabling
|
||||
|
||||
```json
|
||||
{ "plugins": ["guard", "time"] }
|
||||
{ "plugins": ["guard", "secrets", "protect", "time"] }
|
||||
```
|
||||
|
||||
That is also the default when the field is absent, and it lists **builtin** plugins only.
|
||||
@@ -95,6 +95,34 @@ a `write_file` overwriting something important is an approval question, not a gu
|
||||
The guard is the last line before a command runs; `ctrl-c` is the one after. A pattern the guard
|
||||
does not know about is still interruptible by hand — see [tools](tools.md#bash).
|
||||
|
||||
### `protect` (default on)
|
||||
|
||||
Refuses writes to files whose contents belong to a tool rather than to anyone editing them by
|
||||
hand. This is a different failure from a secret: the repository looks fine and behaves wrongly,
|
||||
and the breakage surfaces somewhere else entirely.
|
||||
|
||||
| Refused | Why |
|
||||
|---|---|
|
||||
| `.git/**` | git's own object store |
|
||||
| `bun.lock`, `package-lock.json`, `pnpm-lock.yaml`, `yarn.lock`, `Cargo.lock`, `go.sum`, `poetry.lock`, `uv.lock`, `composer.lock`, `Gemfile.lock` | the package manager owns it |
|
||||
| `node_modules/**` | an installed dependency |
|
||||
| `vendor/**`, `target/debug/**`, `target/release/**` | vendored or build directory |
|
||||
| `dist/**`, `build/**`, `out/**`, `.next/**`, `.nuxt/**`, `.svelte-kit/**`, `coverage/**` | generated output |
|
||||
| `.venv/**`, `.tox/**`, `.mypy_cache/**`, `.ruff_cache/**`, `.turbo/**` | tool caches |
|
||||
|
||||
```
|
||||
refusing to write bun.lock (a lockfile the package manager owns). Regenerate it with the
|
||||
tool that owns it rather than editing it.
|
||||
```
|
||||
|
||||
The message says what to do instead, which matters: a model told only "no" writes the same
|
||||
content somewhere else. A lockfile is regenerated by `bun install`; build output is regenerated
|
||||
by the build.
|
||||
|
||||
Both separators match, so `node_modules\react\index.js` is refused on Windows too. Lookalike
|
||||
names are not: `src/gitignore-parser.ts`, `docs/dist-layout.md`, and `distributed/queue.ts` all
|
||||
write normally.
|
||||
|
||||
### `time` (default on)
|
||||
|
||||
Adds `current_time`, returning ISO 8601 plus the local string. Auto-approved; it reads
|
||||
@@ -106,7 +134,7 @@ Writes `\u0007` to stderr when a turn ends. Off by default — a bell after ever
|
||||
intrusive, but it is genuinely useful when a turn takes minutes.
|
||||
|
||||
```json
|
||||
{ "plugins": ["guard", "time", "bell"] }
|
||||
{ "plugins": ["guard", "secrets", "protect", "time", "bell"] }
|
||||
```
|
||||
|
||||
## Writing one
|
||||
@@ -125,7 +153,8 @@ export const noSecretsPlugin: Plugin = {
|
||||
'The no-secrets plugin refuses writes to .env and credential files. Ask the user to ' +
|
||||
'add secrets themselves rather than working around it.',
|
||||
beforeToolCall: ({ toolName, input }) => {
|
||||
if (!['write_file', 'edit_file', 'multi_edit', 'apply_patch'].includes(toolName)) return undefined;
|
||||
const WRITE_TOOLS = ['write_file', 'edit_file', 'multi_edit', 'apply_patch', 'move_file', 'delete_file'];
|
||||
if (!WRITE_TOOLS.includes(toolName)) return undefined;
|
||||
const path = String((input as { path?: unknown } | null)?.path ?? '');
|
||||
if (/(^|\/)\.env|credentials|\.pem$/.test(path)) {
|
||||
return `refusing to write ${path}; add secrets yourself`;
|
||||
@@ -137,8 +166,11 @@ export const noSecretsPlugin: Plugin = {
|
||||
|
||||
Then add it to `BUILTIN_PLUGINS` and, if it should be on by default, `DEFAULT_ENABLED`.
|
||||
|
||||
Note the four tool names. Every write tool has to be listed, and `multi_edit` is easy to miss
|
||||
— a guard that only checks `write_file` and `edit_file` is bypassed by a batch edit.
|
||||
Note the six tool names. Every write tool has to be listed, and `multi_edit`, `apply_patch`,
|
||||
and `move_file` are all easy to miss — a guard that only checks `write_file` and `edit_file` is
|
||||
bypassed by a batch edit, a patch, or a rename. `apply_patch` and `move_file` also carry their
|
||||
paths somewhere other than `path`, so a guard reading only that field sees nothing to check.
|
||||
The builtins share one `writtenPaths` helper for exactly that reason.
|
||||
|
||||
Write the `appendix` whenever the plugin can block something. Without it the model hits a
|
||||
refusal it was never told about and tries to route around it.
|
||||
|
||||
Reference in New Issue
Block a user