@technomoron/agent-run 0.99.25 → 0.99.26

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/CHANGES CHANGED
@@ -1,6 +1,15 @@
1
1
  CHANGES
2
2
  =======
3
3
 
4
+ Version 0.99.26 (2026-07-31)
5
+ ----------------------------
6
+ * Add `--danger` support for Claude so unattended runs pass
7
+ `--dangerously-skip-permissions`.
8
+ * Remove Claude's generated `.claude/settings.local.json` after guarded runs,
9
+ while preserving project-local settings when `--local` is used.
10
+ * Keep nested command-guard tests independent of an outer agent-run session's
11
+ executable search path.
12
+
4
13
  Version 0.99.25 (2026-07-11)
5
14
  ----------------------------
6
15
  * Add config-root `agent-run.defaults.jsonc` inheritance so project manifests
package/README.md CHANGED
@@ -154,9 +154,8 @@ Codex defaults to `-a on-request -s workspace-write`. `agent-run` sets
154
154
  `CODEX_HOME` under the private agent directory, where Codex discovers the
155
155
  generated `AGENTS.md`, `config.toml`, and skills natively. It starts Codex from
156
156
  that private directory, passes the project root with `-C`, and keeps generated
157
- guard shims on `PATH`. Use `--danger` explicitly for
158
- `-a never -s danger-full-access`; use `--network` to enable network access in
159
- the workspace-write sandbox.
157
+ guard shims on `PATH`. Use `--network` to enable network access in the
158
+ workspace-write sandbox.
160
159
  When `~/.codex/auth.json` exists, profile-specific Codex homes link their
161
160
  `auth.json` to that shared login cache so changing profiles does not require a
162
161
  new ChatGPT login.
@@ -165,7 +164,16 @@ Claude Code currently has no `--cd` equivalent. `agent-run` keeps Claude's
165
164
  process cwd at the project root, appends the generated `CLAUDE.md` with
166
165
  `--append-system-prompt-file`, passes generated settings with `--settings`, and
167
166
  loads generated skills from a local plugin with `--plugin-dir`. It does not
168
- replace the user's normal `CLAUDE_CONFIG_DIR`.
167
+ replace the user's normal `CLAUDE_CONFIG_DIR`. If Claude writes remembered
168
+ permissions to `.claude/settings.local.json`, `agent-run` removes that file
169
+ after the session unless `--local` was used.
170
+
171
+ `--danger` runs either tool unattended, with no approval prompts: Codex with
172
+ `-a never -s danger-full-access`, Claude with `--dangerously-skip-permissions`.
173
+ Only use it when the agent may change or delete anything it can reach. Claude
174
+ refuses `--dangerously-skip-permissions` when it runs as root, so run it as a
175
+ normal user. `--sandboxed` and `--network` stay Codex-only because Claude has no
176
+ matching sandbox.
169
177
 
170
178
  By default, `agent-run codex` and `agent-run claude` fail when local AI files
171
179
  such as `AGENTS.md`, `CLAUDE.md`, `CLAUDE.local.md`, `.mcp.json`, `.agents`,
package/dist/cli.js CHANGED
@@ -130,7 +130,7 @@ function parseRunCommand(command, inputArgs) {
130
130
  local: false,
131
131
  show: false,
132
132
  generate: false,
133
- codexSandboxMode: null,
133
+ sandboxMode: null,
134
134
  codexNetwork: false
135
135
  };
136
136
  const args = [];
@@ -148,12 +148,12 @@ function parseRunCommand(command, inputArgs) {
148
148
  if (applyCommonRunOption(arg, wrapperArgs)) {
149
149
  continue;
150
150
  }
151
- if (applyCodexRunOption(command, arg, wrapperArgs)) {
151
+ if (applySandboxRunOption(command, arg, wrapperArgs)) {
152
152
  continue;
153
153
  }
154
154
  args.push(arg);
155
155
  }
156
- if (wrapperArgs.codexNetwork && wrapperArgs.codexSandboxMode === 'danger') {
156
+ if (wrapperArgs.codexNetwork && wrapperArgs.sandboxMode === 'danger') {
157
157
  (0, utils_1.fail)('--network cannot be combined with agent-run codex --danger');
158
158
  }
159
159
  return { args, command, wrapperArgs };
@@ -173,11 +173,11 @@ function applyCommonRunOption(arg, options) {
173
173
  options[field] = true;
174
174
  return true;
175
175
  }
176
- function applyCodexRunOption(command, arg, options) {
176
+ function applySandboxRunOption(command, arg, options) {
177
177
  if (!['--danger', '--sandboxed', '--network'].includes(arg)) {
178
178
  return false;
179
179
  }
180
- if (command !== 'codex') {
180
+ if (arg !== '--danger' && command !== 'codex') {
181
181
  (0, utils_1.fail)(`${arg} is only supported for agent-run codex`);
182
182
  }
183
183
  if (arg === '--network') {
@@ -185,10 +185,10 @@ function applyCodexRunOption(command, arg, options) {
185
185
  return true;
186
186
  }
187
187
  const mode = arg === '--danger' ? 'danger' : 'sandboxed';
188
- if (options.codexSandboxMode !== null && options.codexSandboxMode !== mode) {
188
+ if (options.sandboxMode !== null && options.sandboxMode !== mode) {
189
189
  (0, utils_1.fail)('cannot combine --danger and --sandboxed');
190
190
  }
191
- options.codexSandboxMode = mode;
191
+ options.sandboxMode = mode;
192
192
  return true;
193
193
  }
194
194
  function parseCheckCommand(inputArgs) {
@@ -319,7 +319,7 @@ function renderHelp(topic) {
319
319
  'Commands:',
320
320
  ' codex [--none] [--create] [--local] [--show] [--generate] [--danger|--sandboxed] [--network] [args...]',
321
321
  ' Run codex with generated private config',
322
- ' claude [--none] [--create] [--local] [--show] [--generate] [args...]',
322
+ ' claude [--none] [--create] [--local] [--show] [--generate] [--danger] [args...]',
323
323
  ' Run claude with generated private config',
324
324
  ' check [--all] [path] Validate generated profile output',
325
325
  ' init [path] Create a sparse profile marker and render output',
@@ -338,9 +338,11 @@ function renderHelp(topic) {
338
338
  ' --local Warn about local AI files instead of failing',
339
339
  ' --show Show read/include and generated files without running the tool',
340
340
  ' --generate Generate files without running the tool',
341
+ ' --danger Run unattended without approval prompts:',
342
+ ' Codex with -a never -s danger-full-access,',
343
+ ' Claude with --dangerously-skip-permissions',
341
344
  '',
342
345
  'Codex wrapper options:',
343
- ' --danger Run Codex with no sandbox: -a never -s danger-full-access',
344
346
  ' --sandboxed Run Codex with workspace-write sandbox (default)',
345
347
  ' --network Enable network for the workspace-write sandbox',
346
348
  ''
package/dist/commands.js CHANGED
@@ -47,7 +47,8 @@ function runTool(parsed) {
47
47
  validateRunModes(parsed, projectRoot);
48
48
  if (wrapperArgs.none || (0, project_1.isIgnoredDir)(projectRoot)) {
49
49
  (0, utils_1.verbose)(`wrapper bypassed for ${command}${wrapperArgs.none ? ' via --none' : ' because project is ignored'}`);
50
- (0, process_1.execTool)((0, process_1.findRealBinary)(command), [...(0, tools_1.getPermissionArgs)(command), ...args]);
50
+ const runtimeArgs = wrapperArgs.sandboxMode === 'danger' ? (0, tools_1.getDangerArgs)(command) : (0, tools_1.getPermissionArgs)(command);
51
+ (0, process_1.execTool)((0, process_1.findRealBinary)(command), [...runtimeArgs, ...args]);
51
52
  return;
52
53
  }
53
54
  const profileResult = (0, project_1.resolveProfileResult)(projectRoot);
package/dist/tools.js CHANGED
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.runCodex = runCodex;
4
4
  exports.runClaude = runClaude;
5
+ exports.getDangerArgs = getDangerArgs;
5
6
  exports.getPermissionArgs = getPermissionArgs;
6
7
  const fs = require("fs");
7
8
  const path = require("path");
@@ -25,15 +26,13 @@ function runCodex(realBinary, permissionArgs, context, args, wrapperArgs) {
25
26
  AGENT_RUN_REAL_PATH: realPath,
26
27
  PATH: `${path.join(liveDir, 'bin')}${path.delimiter}${realPath}`
27
28
  };
28
- const runtimeArgs = wrapperArgs.codexSandboxMode === 'danger'
29
- ? ['-a', 'never', '-s', 'danger-full-access']
30
- : ['-a', 'on-request', '-s', 'workspace-write'];
29
+ const runtimeArgs = wrapperArgs.sandboxMode === 'danger' ? getDangerArgs('codex') : ['-a', 'on-request', '-s', 'workspace-write'];
31
30
  (0, process_1.execCommand)(realBinary, [
32
31
  ...permissionArgs,
33
32
  ...runtimeArgs,
34
33
  '-C',
35
34
  projectRoot,
36
- ...(wrapperArgs.codexSandboxMode !== 'danger' && wrapperArgs.codexNetwork
35
+ ...(wrapperArgs.sandboxMode !== 'danger' && wrapperArgs.codexNetwork
37
36
  ? ['--config', 'sandbox_workspace_write.network_access=true']
38
37
  : []),
39
38
  ...args
@@ -55,8 +54,9 @@ function runClaude(realBinary, permissionArgs, context, args, wrapperArgs) {
55
54
  AGENT_RUN_REAL_PATH: realPath,
56
55
  PATH: `${path.join(liveDir, 'bin')}${path.delimiter}${realPath}`
57
56
  };
57
+ const runtimeArgs = wrapperArgs.sandboxMode === 'danger' ? getDangerArgs('claude') : permissionArgs;
58
58
  (0, process_1.execCommand)(realBinary, [
59
- ...permissionArgs,
59
+ ...runtimeArgs,
60
60
  '--append-system-prompt-file',
61
61
  claudePath,
62
62
  '--settings',
@@ -70,6 +70,9 @@ function postflightProjectCheck(context, allowLocal, code) {
70
70
  if (!context.guardrails.forbidRepoAiFiles) {
71
71
  return code;
72
72
  }
73
+ if (!allowLocal) {
74
+ removeClaudeLocalSettings(context.projectRoot);
75
+ }
73
76
  const localAiFiles = (0, project_1.findLocalAiFiles)(context.projectRoot, context.profileDir);
74
77
  if (localAiFiles.length === 0) {
75
78
  return code;
@@ -77,11 +80,34 @@ function postflightProjectCheck(context, allowLocal, code) {
77
80
  (0, project_1.warnForLocalAiFiles)(null, context.projectRoot, localAiFiles);
78
81
  return allowLocal ? code : 1;
79
82
  }
83
+ function removeClaudeLocalSettings(projectRoot) {
84
+ const claudeDir = path.join(projectRoot, '.claude');
85
+ const localSettingsPath = path.join(claudeDir, 'settings.local.json');
86
+ if (!fs.existsSync(localSettingsPath)) {
87
+ return;
88
+ }
89
+ fs.rmSync(localSettingsPath);
90
+ try {
91
+ fs.rmdirSync(claudeDir);
92
+ }
93
+ catch (error) {
94
+ if (!isDirectoryNotEmptyError(error)) {
95
+ throw error;
96
+ }
97
+ }
98
+ process.stderr.write(`agent-run: removed Claude's project-local settings: ${localSettingsPath}\n`);
99
+ }
100
+ function isDirectoryNotEmptyError(error) {
101
+ return error instanceof Error && 'code' in error && error.code === 'ENOTEMPTY';
102
+ }
80
103
  function failMissingConfig(tool, agentDir) {
81
104
  process.stderr.write(`agent-run: no ${tool} config found for this project: ${agentDir}\n`);
82
105
  process.stderr.write(`agent-run: run \`agent-run ${tool} --none\` to bypass agent setup, or \`agent-run ${tool} --create\` to create profile files.\n`);
83
106
  process.exit(1);
84
107
  }
108
+ function getDangerArgs(tool) {
109
+ return tool === 'codex' ? ['-a', 'never', '-s', 'danger-full-access'] : ['--dangerously-skip-permissions'];
110
+ }
85
111
  function getPermissionArgs(tool) {
86
112
  if (process.env.AGENT_WRAPPER_FORCE_PERMISSIVE !== '1') {
87
113
  return [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@technomoron/agent-run",
3
- "version": "0.99.25",
3
+ "version": "0.99.26",
4
4
  "packageManager": "pnpm@10.28.1",
5
5
  "bin": {
6
6
  "agent-run": "dist/agent-run.js"