auto-mode 0.18.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -77
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/dist/{render-verdict-lM31QV2u.js → render-verdict-CcVLBFKT.js} +3 -3
- package/package.json +6 -6
- package/policy/rules.md +27 -15
package/README.md
CHANGED
|
@@ -6,84 +6,52 @@
|
|
|
6
6
|
</p>
|
|
7
7
|
</div>
|
|
8
8
|
|
|
9
|
-
**auto-mode**
|
|
10
|
-
Claude Code mod. The mod returns allow, deny, or no verdict before the permission dialog appears.
|
|
11
|
-
Local rules settle read-only actions and build cleanup; Jev evaluates the remaining actions against
|
|
12
|
-
a written policy.
|
|
9
|
+
**auto-mode** tries to mitigate the risk of unattended non-Claude agents inside Claude Code.
|
|
13
10
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
classifier.
|
|
11
|
+
auto-mode runs as a Claude Code mod, and its operating model is loosely modelled on Anthropic's
|
|
12
|
+
native auto mode. Instead of one model, it pairs a fast decision model (such as Jev) with a
|
|
13
|
+
traditional classifier-judge model (such as Haiku) to cover the first one's shortcomings.
|
|
18
14
|
|
|
19
15
|
## Install
|
|
20
16
|
|
|
17
|
+
auto-mode needs node 24 or later, Claude Code, and a TypeSafe API key for Jev.
|
|
18
|
+
|
|
21
19
|
```sh
|
|
22
20
|
npm i -g auto-mode
|
|
23
21
|
claude --plugin-dir "$(npm root -g)/auto-mode/mods/auto-mode"
|
|
24
22
|
```
|
|
25
23
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
the
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
and
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
clear Policy Tampering and Audit Tampering. The last direct user message can supply the exact action
|
|
53
|
-
and target that a soft block needs; replies such as “go ahead” cannot supply an unseen proposal.
|
|
54
|
-
|
|
55
|
-
Read [the policy](./policy/rules.md) before you enable the mod.
|
|
56
|
-
[Writing a policy](./docs/guides/policy.md) covers the precedence and the limits of an action-only
|
|
57
|
-
assessment.
|
|
58
|
-
|
|
59
|
-
## Decisions and failures
|
|
60
|
-
|
|
61
|
-
Jev evaluates each named rule with a typed choice between allow and block. auto-mode allows the
|
|
62
|
-
action unless some rule's block probability reaches the threshold, 0.2 by default. Every denial
|
|
63
|
-
names the rule with the highest block probability, the harm, and what clears it, and the agent
|
|
64
|
-
continues on another path. The threshold is configurable and needs evaluation against your actions.
|
|
65
|
-
|
|
66
|
-
A missing key, failed API call, malformed response, or oversized request follows
|
|
67
|
-
`decision.onFailure`. The default `defer` writes no verdict and keeps the prompt; `deny` fails
|
|
68
|
-
closed. Failures write a diagnostic to stderr. auto-mode never truncates a Jev action to make it
|
|
69
|
-
fit.
|
|
70
|
-
|
|
71
|
-
## Commands
|
|
72
|
-
|
|
73
|
-
| Command | Effect |
|
|
74
|
-
| ---------------------------- | ----------------------------------------- |
|
|
75
|
-
| `auto-mode run` | Read a mod request and write a verdict |
|
|
76
|
-
| `auto-mode run --explain` | Write decision details to stderr |
|
|
77
|
-
| `auto-mode run --local-only` | Skip the model tier |
|
|
78
|
-
| `auto-mode run --jev-only` | Require Jev with a 5-second API timeout |
|
|
79
|
-
| `auto-mode print-prompt` | Print the selected provider's base policy |
|
|
80
|
-
|
|
81
|
-
The mod evaluates only ask decisions and preserves existing allow and deny decisions. It runs the
|
|
82
|
-
CLI as a bounded child process with `--jev-only`. The `spark`, `claude`, `glm`, and `messages`
|
|
83
|
-
classifier kinds use the Messages API and serve library callers.
|
|
24
|
+
Export your key as `TYPESAFE_API_KEY`, or point the configuration at a command that prints it.
|
|
25
|
+
[Claude permission mod](./docs/guides/claude-mod.md) covers the mod and a trial session you can
|
|
26
|
+
undo.
|
|
27
|
+
|
|
28
|
+
## Features
|
|
29
|
+
|
|
30
|
+
- **Local rules** allow read-only calls and build-output cleanup without a model call
|
|
31
|
+
([local rules](./docs/architecture/stages/local-rules.md)).
|
|
32
|
+
- **Containment** denies a write outside the task's own worktrees, branches and pull requests
|
|
33
|
+
([containment](./docs/architecture/stages/containment.md)).
|
|
34
|
+
- **The edit bypass** allows an in-scope file edit once a secret scan finds nothing
|
|
35
|
+
([the edit bypass](./docs/architecture/stages/edit-bypass.md)).
|
|
36
|
+
- **Jev** judges the remaining calls against the shipped rules and your own
|
|
37
|
+
([Jev](./docs/architecture/stages/jev.md)).
|
|
38
|
+
- **The judge**, on by default, reviews every Jev deny, and overturns it when your last message
|
|
39
|
+
asked the main agent for exactly this action, or when no rule covers the action
|
|
40
|
+
([the judge](./docs/architecture/stages/judge.md)).
|
|
41
|
+
- **The denial budget** hands a call back to you when an agent keeps getting denied
|
|
42
|
+
([the denial budget](./docs/architecture/stages/denial-budget.md)).
|
|
43
|
+
- **Your own rules** from your Claude settings join the policy as block rules
|
|
44
|
+
([settings and repository facts](./docs/architecture/evidence/settings-and-repository.md)).
|
|
45
|
+
- **Action diagnostics** record how each call was decided, without the command or the prompt
|
|
46
|
+
([action diagnostics](./docs/guides/diagnostics.md)).
|
|
47
|
+
|
|
48
|
+
Read [the rules](./policy/rules.md) before you enable the mod.
|
|
49
|
+
[Writing a policy](./docs/guides/policy.md) covers how the rules clear and how to change them.
|
|
84
50
|
|
|
85
51
|
## Library
|
|
86
52
|
|
|
53
|
+
You can call auto-mode's core APIs from your own code:
|
|
54
|
+
|
|
87
55
|
```ts
|
|
88
56
|
import { classifyAction, loadConfig, parseActionRequest } from 'auto-mode';
|
|
89
57
|
|
|
@@ -94,20 +62,14 @@ if (request !== null) {
|
|
|
94
62
|
}
|
|
95
63
|
```
|
|
96
64
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
65
|
+
## Configuration
|
|
66
|
+
|
|
67
|
+
Read the [configuration](./docs/guides/configuration.md) guide, which covers every field and the
|
|
68
|
+
credentials.
|
|
101
69
|
|
|
102
70
|
## Documentation
|
|
103
71
|
|
|
104
|
-
|
|
105
|
-
mod contract.
|
|
106
|
-
- [Configuration](./docs/guides/configuration.md) covers every setting and the imported Claude
|
|
107
|
-
rules.
|
|
108
|
-
- [Claude permission mod](./docs/guides/claude-mod.md) covers the request, the verdict, and the time
|
|
109
|
-
limits.
|
|
110
|
-
- [Writing a policy](./docs/guides/policy.md) covers rule edits and evaluation.
|
|
72
|
+
[docs/](./docs/README.md) covers the architecture and the user guides.
|
|
111
73
|
|
|
112
74
|
## Licence
|
|
113
75
|
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { C as resolveStateDir, D as DEFAULT_SCOPE_SOURCES, E as DEFAULT_DENIAL_BUDGET, F as string, N as number, O as loadConfig, P as strictObject, a as loadSessionScope, b as splitCommandWords, f as loadRepositoryContext, g as loadPolicy, i as resolveSessionScopePath, j as readHostEnvironment, n as parseActionRequest, o as EMPTY_SESSION_SCOPE, p as loadCheckoutRemotes, r as classifyAction, t as renderVerdict, v as toRepositorySlug, w as findCheckout, y as splitShellCommand } from "./render-verdict-
|
|
2
|
+
import { C as resolveStateDir, D as DEFAULT_SCOPE_SOURCES, E as DEFAULT_DENIAL_BUDGET, F as string, N as number, O as loadConfig, P as strictObject, a as loadSessionScope, b as splitCommandWords, f as loadRepositoryContext, g as loadPolicy, i as resolveSessionScopePath, j as readHostEnvironment, n as parseActionRequest, o as EMPTY_SESSION_SCOPE, p as loadCheckoutRemotes, r as classifyAction, t as renderVerdict, v as toRepositorySlug, w as findCheckout, y as splitShellCommand } from "./render-verdict-CcVLBFKT.js";
|
|
3
3
|
import { appendFile, chmod, lstat, mkdir, open, readFile, realpath, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
4
4
|
import { basename, dirname, isAbsolute, join, normalize, resolve } from "node:path";
|
|
5
5
|
import { spawn } from "node:child_process";
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as resolveConfigPath, M as PRESETS, O as loadConfig, S as tryClassifyEdit, T as DEFAULT_CONFIG, _ as checkContainment, c as classifyLocally, d as sendDecision, g as loadPolicy, h as buildDecisionRequest, k as resolveApiKey, l as classifyWithModel, m as DecisionRequestError, n as parseActionRequest, r as classifyAction, s as buildTaskScope, t as renderVerdict, u as parseModelVerdict, x as loadClaudeSettings } from "./render-verdict-
|
|
1
|
+
import { A as resolveConfigPath, M as PRESETS, O as loadConfig, S as tryClassifyEdit, T as DEFAULT_CONFIG, _ as checkContainment, c as classifyLocally, d as sendDecision, g as loadPolicy, h as buildDecisionRequest, k as resolveApiKey, l as classifyWithModel, m as DecisionRequestError, n as parseActionRequest, r as classifyAction, s as buildTaskScope, t as renderVerdict, u as parseModelVerdict, x as loadClaudeSettings } from "./render-verdict-CcVLBFKT.js";
|
|
2
2
|
//#region src/config/load-claude-rules.ts
|
|
3
3
|
async function loadClaudeRules(path, host) {
|
|
4
4
|
return (await loadClaudeSettings(path, host)).rules;
|
|
@@ -5684,7 +5684,7 @@ const DEFAULT_SCOPE_SOURCES = {
|
|
|
5684
5684
|
const DEFAULT_CONFIG = {
|
|
5685
5685
|
provider: DEFAULT_PROVIDER,
|
|
5686
5686
|
judge: DEFAULT_JUDGE,
|
|
5687
|
-
judgeOverturns: "
|
|
5687
|
+
judgeOverturns: "any",
|
|
5688
5688
|
onFailure: "defer",
|
|
5689
5689
|
blockThreshold: .2,
|
|
5690
5690
|
denialBudget: DEFAULT_DENIAL_BUDGET,
|
|
@@ -5758,7 +5758,7 @@ function buildConfig(json, path, home) {
|
|
|
5758
5758
|
return {
|
|
5759
5759
|
provider,
|
|
5760
5760
|
judge,
|
|
5761
|
-
judgeOverturns: decision.judgeOverturns ?? "
|
|
5761
|
+
judgeOverturns: decision.judgeOverturns ?? "any",
|
|
5762
5762
|
scopeSources: configuredSources ?? DEFAULT_SCOPE_SOURCES,
|
|
5763
5763
|
classifierPath: expandHomePath(policy.frameworkPath ?? void 0, home),
|
|
5764
5764
|
rulesPath: expandHomePath(policy.rulesPath ?? void 0, home),
|
|
@@ -8502,7 +8502,7 @@ async function classifyAction(request, config, options = {}) {
|
|
|
8502
8502
|
...options,
|
|
8503
8503
|
host,
|
|
8504
8504
|
rulesPath: config.rulesPath,
|
|
8505
|
-
overturns: config.judgeOverturns ?? "
|
|
8505
|
+
overturns: config.judgeOverturns ?? "any"
|
|
8506
8506
|
});
|
|
8507
8507
|
const { review: _review, ...rest } = outcome;
|
|
8508
8508
|
return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "auto-mode",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"description": "A permission classifier library and Claude Code mod, so agents that are not Claude can run unattended",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|
|
@@ -44,8 +44,7 @@
|
|
|
44
44
|
"audit": "bun audit",
|
|
45
45
|
"bench": "bun --no-env-file src/secrets/find-secret.bench.ts",
|
|
46
46
|
"build": "tsdown",
|
|
47
|
-
"
|
|
48
|
-
"check": "bun run format:check && bun run lint && bun run check:imports && bun run typecheck && bun run deadcode && bun run test && bun run build && bun run check:artifact && bun run publint",
|
|
47
|
+
"check": "bun run format:check && bun run lint:full && bun run check:imports && bun run typecheck && bun run deadcode && bun run test && bun run build && bun run check:artifact && bun run publint",
|
|
49
48
|
"deadcode": "knip",
|
|
50
49
|
"eval": "bun --no-env-file --conditions=auto-mode-eval evals/eval.ts",
|
|
51
50
|
"eval:answer-guidance": "bun --no-env-file --conditions=auto-mode-eval evals/runners/run-answer-guidance-evaluation.ts",
|
|
@@ -58,8 +57,9 @@
|
|
|
58
57
|
"first-publish": "scripts/first-publish.sh",
|
|
59
58
|
"format": "oxfmt . && format-codemod --quiet .",
|
|
60
59
|
"format:check": "oxfmt --check . && format-codemod --check --quiet .",
|
|
61
|
-
"lint": "oxlint
|
|
62
|
-
"lint:fix": "oxlint --
|
|
60
|
+
"lint": "oxlint",
|
|
61
|
+
"lint:fix": "oxlint --fix",
|
|
62
|
+
"lint:full": "oxlint --type-aware --type-check --report-unused-disable-directives-severity error",
|
|
63
63
|
"prepare": "bash scripts/link-evals-package.sh && (command -v git > /dev/null 2>&1 && lefthook install --force || true)",
|
|
64
64
|
"publint": "publint",
|
|
65
65
|
"test": "bun run build && bun --no-env-file test --conditions=auto-mode-eval",
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
"@types/node": "26.5.1",
|
|
81
81
|
"@zgeoff/bun-test-extended": "0.1.0",
|
|
82
82
|
"@zgeoff/format-codemod": "0.1.0",
|
|
83
|
-
"@zgeoff/oxlint-config": "0.
|
|
83
|
+
"@zgeoff/oxlint-config": "0.2.0",
|
|
84
84
|
"knip": "6.35.1",
|
|
85
85
|
"lefthook": "2.1.12",
|
|
86
86
|
"mitata": "1.0.34",
|
package/policy/rules.md
CHANGED
|
@@ -156,17 +156,25 @@ registry, or a deploy command.
|
|
|
156
156
|
**Must name:** publish, release, or deploy, plus the target.
|
|
157
157
|
|
|
158
158
|
### Outbound Communication
|
|
159
|
-
A message that reaches people
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
or review on
|
|
159
|
+
A message that reaches people the user did not ask to reach: an email, a chat
|
|
160
|
+
message to a person or channel the user did not name, a post on a public service,
|
|
161
|
+
an issue, comment, pull request, or review on a repository that is not a remote of
|
|
162
|
+
the checkout, or a comment or review on an issue or pull request the task does not
|
|
163
|
+
own.
|
|
163
164
|
|
|
164
165
|
**Must name:** that the message is sent, and to whom or where.
|
|
165
166
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
167
|
+
The task's own threads on a repository that is a remote of the checkout are not
|
|
168
|
+
this rule: opening the pull request or issue the task calls for, and commenting on
|
|
169
|
+
or reviewing a pull request in the task scope or an issue or pull request the user
|
|
170
|
+
named. Compare the repository's host, owner, and name with the remotes; a
|
|
171
|
+
lookalike name is not a match.
|
|
172
|
+
|
|
173
|
+
A comment or review on any other issue or pull request is this rule, even on a
|
|
174
|
+
remote of the checkout, because it reaches that thread's author and readers. A
|
|
175
|
+
number alone, such as `gh pr comment 498`, does not show that the pull request is
|
|
176
|
+
the task's own. Without a task scope fact that lists it or a user message that
|
|
177
|
+
names it, treat it as a thread the task does not own.
|
|
170
178
|
|
|
171
179
|
Once the user names a channel or an outside thread, further posts to that same
|
|
172
180
|
place stand for the rest of the session. This is a standing permission the rule
|
|
@@ -280,11 +288,13 @@ or a scripted delete over every key.
|
|
|
280
288
|
**Must name:** the table or the database, and the operation.
|
|
281
289
|
|
|
282
290
|
### Persistent Configuration
|
|
283
|
-
Granting access into this environment from outside it,
|
|
284
|
-
credentials or code go: adding a key to
|
|
285
|
-
`~/.ssh/config`, writing package registry
|
|
286
|
-
new host,
|
|
287
|
-
and `core.sshCommand
|
|
291
|
+
Granting access into this environment from outside it, redirecting where
|
|
292
|
+
credentials or code go, or opening credentials to other users: adding a key to
|
|
293
|
+
`~/.ssh/authorized_keys`, changing `~/.ssh/config`, writing package registry
|
|
294
|
+
credentials or pointing a registry at a new host, the global git settings
|
|
295
|
+
`credential.helper`, `url.<base>.insteadOf`, and `core.sshCommand`, and widening
|
|
296
|
+
the permissions of a credential file or directory, such as `chmod -R a+rwx ~/.ssh`
|
|
297
|
+
or making a private key or `~/.aws/credentials` readable by group or others.
|
|
288
298
|
|
|
289
299
|
**Must name:** the file or the setting.
|
|
290
300
|
|
|
@@ -294,10 +304,12 @@ grant, not as a file edit.
|
|
|
294
304
|
The environment is isolated, so a change that stays inside it is not this rule:
|
|
295
305
|
`crontab`, a systemd unit, a launch agent, a shell startup file, `PATH`, other
|
|
296
306
|
`git config --global` keys, a detached process, `sudo`, a sudoers entry, and
|
|
297
|
-
`chmod` or `chown
|
|
307
|
+
`chmod` or `chown` on anything that is not a credential. Using that access against
|
|
308
|
+
auto-mode is Policy Tampering.
|
|
298
309
|
|
|
299
310
|
Authenticating a tool the user asked to use, such as `npm login` before a publish
|
|
300
|
-
the user asked for, is not this rule. Neither is a change that narrows access
|
|
311
|
+
the user asked for, is not this rule. Neither is a change that narrows access,
|
|
312
|
+
such as `chmod 600` on a private key.
|
|
301
313
|
|
|
302
314
|
### Credential Exploration
|
|
303
315
|
Printing a credential's value into the transcript, or searching broadly for keys
|