@technomoron/agent-run 0.99.11 → 0.99.12
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 +6 -0
- package/README.md +6 -1
- package/dist/agent-run.js +88 -22
- package/examples/basic-config/agent-config/global/tool-templates/claude-settings.json.njk +15 -1
- package/examples/basic-config/agent-config/starter/basic-project/overrides/claude-settings.json.njk +16 -1
- package/package.json +1 -1
package/CHANGES
CHANGED
|
@@ -4,6 +4,12 @@ CHANGES
|
|
|
4
4
|
Unreleased (2026-04-24)
|
|
5
5
|
-----------------------
|
|
6
6
|
|
|
7
|
+
Version 0.99.12 (2026-04-27)
|
|
8
|
+
----------------------------
|
|
9
|
+
* Add `--local` for Codex and Claude runs to warn about local AI files instead of failing.
|
|
10
|
+
* Limit generated Claude permission allow entries to configured checks instead of broad blocked command families.
|
|
11
|
+
* Write agent-run's Claude settings to `.claude/agent-run-settings.json` and remove only exact legacy generated `.claude/settings.json` files.
|
|
12
|
+
|
|
7
13
|
Version 0.99.11 (2026-04-27)
|
|
8
14
|
----------------------------
|
|
9
15
|
* Show the package version in `agent-run --help` and add `agent-run --version`.
|
package/README.md
CHANGED
|
@@ -118,10 +118,15 @@ generated guard shims on `PATH`. Use `--sandboxed` to request Codex
|
|
|
118
118
|
`sandbox_workspace_write.network_access=true`.
|
|
119
119
|
|
|
120
120
|
Claude Code currently has no `--cd` equivalent. `agent-run` keeps Claude's
|
|
121
|
-
process cwd at the project root, passes the generated `.claude/settings.json`
|
|
121
|
+
process cwd at the project root, passes the generated `.claude/agent-run-settings.json`
|
|
122
122
|
with `--settings`, and allows both the project root and private agent directory
|
|
123
123
|
with `--add-dir`.
|
|
124
124
|
|
|
125
|
+
By default, `agent-run codex` and `agent-run claude` fail when local AI files
|
|
126
|
+
such as `AGENTS.md`, `CLAUDE.md`, `.agents`, `.claude`, or `.codex` are present
|
|
127
|
+
inside the project repository. Use `--local` to warn and continue for a specific
|
|
128
|
+
invocation.
|
|
129
|
+
|
|
125
130
|
Initialize mapped files for the current repo:
|
|
126
131
|
|
|
127
132
|
```sh
|
package/dist/agent-run.js
CHANGED
|
@@ -216,6 +216,7 @@ function parseRunCommand(command, inputArgs) {
|
|
|
216
216
|
const wrapperArgs = {
|
|
217
217
|
none: false,
|
|
218
218
|
create: false,
|
|
219
|
+
local: false,
|
|
219
220
|
codexSandboxMode: null,
|
|
220
221
|
codexNetwork: false
|
|
221
222
|
};
|
|
@@ -238,6 +239,10 @@ function parseRunCommand(command, inputArgs) {
|
|
|
238
239
|
wrapperArgs.create = true;
|
|
239
240
|
continue;
|
|
240
241
|
}
|
|
242
|
+
if (arg === '--local') {
|
|
243
|
+
wrapperArgs.local = true;
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
241
246
|
if (arg === '--danger') {
|
|
242
247
|
if (command !== 'codex') {
|
|
243
248
|
fail('--danger is only supported for agent-run codex');
|
|
@@ -412,9 +417,10 @@ function renderHelp(topic) {
|
|
|
412
417
|
' agent-run --init [config-root]',
|
|
413
418
|
'',
|
|
414
419
|
'Commands:',
|
|
415
|
-
' codex [--none] [--create] [--danger|--sandboxed] [--network] [args...]',
|
|
420
|
+
' codex [--none] [--create] [--local] [--danger|--sandboxed] [--network] [args...]',
|
|
416
421
|
' Run codex with generated private config',
|
|
417
|
-
' claude [--none] [--create] [args...]
|
|
422
|
+
' claude [--none] [--create] [--local] [args...]',
|
|
423
|
+
' Run claude with generated private config',
|
|
418
424
|
' check [--all] [path] Validate generated profile output',
|
|
419
425
|
' init [path] Create profile source files and render output',
|
|
420
426
|
' edit [path] Open local.md.njk or legacy AGENTS-MODS.md',
|
|
@@ -429,6 +435,7 @@ function renderHelp(topic) {
|
|
|
429
435
|
' --init [DIR] Copy the packaged starter config root to DIR (default ~/.agent-config)',
|
|
430
436
|
'',
|
|
431
437
|
'Codex wrapper options:',
|
|
438
|
+
' --local Warn about local AI files instead of failing',
|
|
432
439
|
' --danger Run Codex with no sandbox: -a never -s danger-full-access (default)',
|
|
433
440
|
' --sandboxed Run Codex with workspace-write sandbox',
|
|
434
441
|
' --network Enable network for --sandboxed via config override',
|
|
@@ -495,7 +502,10 @@ function runTool(parsed) {
|
|
|
495
502
|
const excludedDir = profileResult.profile === null ? null : resolveAgentDir(projectRoot);
|
|
496
503
|
const localAiFiles = findLocalAiFiles(projectRoot, excludedDir);
|
|
497
504
|
if (localAiFiles.length > 0) {
|
|
498
|
-
|
|
505
|
+
if (!wrapperArgs.local) {
|
|
506
|
+
failForLocalAiFiles(command, projectRoot, localAiFiles);
|
|
507
|
+
}
|
|
508
|
+
warnForLocalAiFiles(command, projectRoot, localAiFiles);
|
|
499
509
|
}
|
|
500
510
|
if (profileResult.profile === null) {
|
|
501
511
|
fail(profileResult.reason);
|
|
@@ -512,7 +522,7 @@ function runTool(parsed) {
|
|
|
512
522
|
runCodex(realBinary, permissionArgs, agentDir, configRoot, args, projectRoot, wrapperArgs);
|
|
513
523
|
return;
|
|
514
524
|
}
|
|
515
|
-
runClaude(realBinary, permissionArgs, agentDir, configRoot, args, projectRoot);
|
|
525
|
+
runClaude(realBinary, permissionArgs, agentDir, configRoot, args, projectRoot, wrapperArgs);
|
|
516
526
|
}
|
|
517
527
|
function runInit(parsed) {
|
|
518
528
|
const projectRoot = findProjectRoot(parsed.targetPath);
|
|
@@ -1009,10 +1019,21 @@ function buildRenderContext(projectRoot, agentDir, configRoot, manifest, env) {
|
|
|
1009
1019
|
return {
|
|
1010
1020
|
...baseContext,
|
|
1011
1021
|
paths,
|
|
1022
|
+
permissionsAllow: buildPermissionsAllow(manifest),
|
|
1012
1023
|
skills: [],
|
|
1013
1024
|
renderedAgentSections: []
|
|
1014
1025
|
};
|
|
1015
1026
|
}
|
|
1027
|
+
function buildPermissionsAllow(manifest) {
|
|
1028
|
+
const allow = new Set();
|
|
1029
|
+
for (const check of manifest.checks) {
|
|
1030
|
+
const normalizedCheck = check.trim();
|
|
1031
|
+
if (normalizedCheck) {
|
|
1032
|
+
allow.add(`Bash(${normalizedCheck})`);
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
return [...allow];
|
|
1036
|
+
}
|
|
1016
1037
|
function resolveConfigPath(configRoot, relativePath, context) {
|
|
1017
1038
|
const env = createNunjucksEnv(configRoot);
|
|
1018
1039
|
const rendered = renderInlineTemplate(env, relativePath, context);
|
|
@@ -1118,7 +1139,7 @@ function renderProfile(projectRoot, agentDir, checkOnly = false) {
|
|
|
1118
1139
|
files.push({ path: path.join(agentDir, 'CLAUDE.md'), content: claudeContent });
|
|
1119
1140
|
files.push({ path: path.join(agentDir, '.claude', 'CLAUDE.md'), content: claudeContent });
|
|
1120
1141
|
files.push({ path: path.join(agentDir, 'config.toml'), content: renderCodexConfig(env, configRoot, context) });
|
|
1121
|
-
files.push({ path: path.join(agentDir, '.claude', 'settings.json'), content: renderClaudeSettings(env, configRoot, context) });
|
|
1142
|
+
files.push({ path: path.join(agentDir, '.claude', 'agent-run-settings.json'), content: renderClaudeSettings(env, configRoot, context) });
|
|
1122
1143
|
files.push(...renderNativeSkillFiles(context));
|
|
1123
1144
|
files.push(...renderGuardShims(context));
|
|
1124
1145
|
return {
|
|
@@ -1136,8 +1157,21 @@ function syncAgentProfile(projectRoot, agentDir) {
|
|
|
1136
1157
|
for (const file of rendered.files) {
|
|
1137
1158
|
writeGeneratedFile(file.path, file.content, file.executable ?? false);
|
|
1138
1159
|
}
|
|
1160
|
+
removeLegacyGeneratedClaudeSettings(rendered.context);
|
|
1139
1161
|
return rendered;
|
|
1140
1162
|
}
|
|
1163
|
+
function removeLegacyGeneratedClaudeSettings(context) {
|
|
1164
|
+
const legacyPath = path.join(context.agentDir, '.claude', 'settings.json');
|
|
1165
|
+
if (!fs.existsSync(legacyPath)) {
|
|
1166
|
+
return;
|
|
1167
|
+
}
|
|
1168
|
+
const actual = fs.readFileSync(legacyPath, 'utf8').replace(/\r\n/g, '\n');
|
|
1169
|
+
const legacyGeneratedContent = legacyDefaultClaudeSettingsContent(context);
|
|
1170
|
+
if (actual === legacyGeneratedContent) {
|
|
1171
|
+
fs.rmSync(legacyPath);
|
|
1172
|
+
verbose(`removed legacy generated Claude settings ${legacyPath}`);
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1141
1175
|
function checkRenderedProfile(projectRoot, agentDir) {
|
|
1142
1176
|
const findings = [];
|
|
1143
1177
|
const configRoot = defaultConfigRoot(projectRoot);
|
|
@@ -1517,7 +1551,7 @@ function runCodex(realBinary, permissionArgs, agentDir, configRoot, args, projec
|
|
|
1517
1551
|
? ['--config', 'sandbox_workspace_write.network_access=true']
|
|
1518
1552
|
: []),
|
|
1519
1553
|
...args
|
|
1520
|
-
], shouldUseShell(realBinary), env, codexHomeDir, (code) => postflightProjectCheck(projectRoot, agentDir, code));
|
|
1554
|
+
], shouldUseShell(realBinary), env, codexHomeDir, (code) => postflightProjectCheck(projectRoot, agentDir, wrapperArgs.local, code));
|
|
1521
1555
|
}
|
|
1522
1556
|
function buildCodexRuntimeArgs(wrapperArgs) {
|
|
1523
1557
|
const mode = wrapperArgs.codexSandboxMode ?? 'danger';
|
|
@@ -1526,7 +1560,7 @@ function buildCodexRuntimeArgs(wrapperArgs) {
|
|
|
1526
1560
|
}
|
|
1527
1561
|
return ['-a', 'never', '-s', 'danger-full-access'];
|
|
1528
1562
|
}
|
|
1529
|
-
function runClaude(realBinary, permissionArgs, agentDir, configRoot, args, projectRoot) {
|
|
1563
|
+
function runClaude(realBinary, permissionArgs, agentDir, configRoot, args, projectRoot, wrapperArgs) {
|
|
1530
1564
|
const claudePath = path.join(agentDir, 'CLAUDE.md');
|
|
1531
1565
|
if (!fs.existsSync(claudePath)) {
|
|
1532
1566
|
failMissingConfig('claude', agentDir);
|
|
@@ -1543,14 +1577,14 @@ function runClaude(realBinary, permissionArgs, agentDir, configRoot, args, proje
|
|
|
1543
1577
|
execCommand(realBinary, [
|
|
1544
1578
|
...permissionArgs,
|
|
1545
1579
|
'--settings',
|
|
1546
|
-
path.join(claudeConfigDir, 'settings.json'),
|
|
1580
|
+
path.join(claudeConfigDir, 'agent-run-settings.json'),
|
|
1547
1581
|
'--add-dir',
|
|
1548
1582
|
projectRoot,
|
|
1549
1583
|
'--add-dir',
|
|
1550
1584
|
agentDir,
|
|
1551
1585
|
...globalMemoryArgs(configRoot),
|
|
1552
1586
|
...args
|
|
1553
|
-
], shouldUseShell(realBinary), env, projectRoot, (code) => postflightProjectCheck(projectRoot, agentDir, code));
|
|
1587
|
+
], shouldUseShell(realBinary), env, projectRoot, (code) => postflightProjectCheck(projectRoot, agentDir, wrapperArgs.local, code));
|
|
1554
1588
|
}
|
|
1555
1589
|
function globalMemoryArgs(configRoot) {
|
|
1556
1590
|
const memoryDir = globalMemoryDir(configRoot);
|
|
@@ -1559,16 +1593,15 @@ function globalMemoryArgs(configRoot) {
|
|
|
1559
1593
|
function globalMemoryDir(configRoot) {
|
|
1560
1594
|
return path.join(configRoot, 'notes', 'memory');
|
|
1561
1595
|
}
|
|
1562
|
-
function postflightProjectCheck(projectRoot, agentDir, code) {
|
|
1596
|
+
function postflightProjectCheck(projectRoot, agentDir, allowLocal, code) {
|
|
1563
1597
|
const localAiFiles = findLocalAiFiles(projectRoot, agentDir);
|
|
1564
|
-
if (localAiFiles.length
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
process.stderr.write(`agent-run: ${file}\n`);
|
|
1598
|
+
if (localAiFiles.length > 0) {
|
|
1599
|
+
warnForLocalAiFiles(null, projectRoot, localAiFiles);
|
|
1600
|
+
if (!allowLocal) {
|
|
1601
|
+
return 1;
|
|
1602
|
+
}
|
|
1570
1603
|
}
|
|
1571
|
-
return
|
|
1604
|
+
return code;
|
|
1572
1605
|
}
|
|
1573
1606
|
function failMissingConfig(tool, agentDir) {
|
|
1574
1607
|
process.stderr.write(`agent-run: no ${tool} config found for this project: ${agentDir}\n`);
|
|
@@ -1648,6 +1681,7 @@ function isSamePathOrDescendant(candidatePath, parentPath) {
|
|
|
1648
1681
|
function shouldPruneProjectEntry(entry) {
|
|
1649
1682
|
return (entry.isDirectory() &&
|
|
1650
1683
|
(entry.name === '.git' ||
|
|
1684
|
+
entry.name === '.claude' ||
|
|
1651
1685
|
entry.name === 'node_modules' ||
|
|
1652
1686
|
entry.name === '.pnpm-store' ||
|
|
1653
1687
|
entry.name === 'dist' ||
|
|
@@ -1666,13 +1700,21 @@ function isIgnoredDir(dir) {
|
|
|
1666
1700
|
const env = readAgentRunEnv(dir);
|
|
1667
1701
|
return parseBooleanEnv(env.AGENT_RUN_IGNORE);
|
|
1668
1702
|
}
|
|
1703
|
+
function warnForLocalAiFiles(tool, projectRoot, localAiFiles) {
|
|
1704
|
+
process.stderr.write(`WARNING: local AI files found in project root ${projectRoot}\n`);
|
|
1705
|
+
for (const file of localAiFiles) {
|
|
1706
|
+
process.stderr.write(`WARNING: ${path.relative(projectRoot, file)}\n`);
|
|
1707
|
+
}
|
|
1708
|
+
if (tool !== null) {
|
|
1709
|
+
process.stderr.write(`WARNING: consider moving these files out of the project, or run \`agent-run ${tool} --none\` to bypass the wrapper.\n`);
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1669
1712
|
function failForLocalAiFiles(tool, projectRoot, localAiFiles) {
|
|
1670
1713
|
process.stderr.write(`agent-run: found local AI files in project root ${projectRoot}\n`);
|
|
1671
1714
|
for (const file of localAiFiles) {
|
|
1672
1715
|
process.stderr.write(`agent-run: ${file}\n`);
|
|
1673
1716
|
}
|
|
1674
|
-
process.stderr.write(`agent-run: move these files manually out of the project,
|
|
1675
|
-
process.stderr.write(`agent-run: run \`agent-run ${tool} --none\` to bypass the wrapper for this invocation.\n`);
|
|
1717
|
+
process.stderr.write(`agent-run: move these files manually out of the project, run \`agent-run ${tool} --local\` to warn and continue, or run \`agent-run ${tool} --none\` to bypass the wrapper for this invocation.\n`);
|
|
1676
1718
|
process.exit(1);
|
|
1677
1719
|
}
|
|
1678
1720
|
function findProjectRoot(cwd) {
|
|
@@ -2296,15 +2338,26 @@ function defaultCodexConfigTemplate() {
|
|
|
2296
2338
|
].join('\n');
|
|
2297
2339
|
}
|
|
2298
2340
|
function defaultClaudeSettingsTemplate() {
|
|
2299
|
-
|
|
2300
|
-
'{',
|
|
2341
|
+
const envBlock = [
|
|
2301
2342
|
' "env": {',
|
|
2302
2343
|
' "AGENT_DIR": "{{ agentDir }}",',
|
|
2303
2344
|
' "AGENT_RUN_PROJECT_ROOT": "{{ projectRoot }}",',
|
|
2304
2345
|
' "AGENT_GLOBAL_MEMORY_DIR": "{{ paths.globalMemoryDir }}"',
|
|
2346
|
+
' }'
|
|
2347
|
+
].join('\n');
|
|
2348
|
+
return [
|
|
2349
|
+
'{% if permissionsAllow.length %}{',
|
|
2350
|
+
envBlock + ',',
|
|
2351
|
+
' "permissions": {',
|
|
2352
|
+
' "allow": [',
|
|
2353
|
+
' "{{ permissionsAllow | join(\'",\\n "\') }}"',
|
|
2354
|
+
' ]',
|
|
2305
2355
|
' }',
|
|
2306
2356
|
'}',
|
|
2307
|
-
''
|
|
2357
|
+
'{% else %}{',
|
|
2358
|
+
envBlock,
|
|
2359
|
+
'}',
|
|
2360
|
+
'{% endif %}'
|
|
2308
2361
|
].join('\n');
|
|
2309
2362
|
}
|
|
2310
2363
|
function defaultCodexConfigContent(context) {
|
|
@@ -2325,6 +2378,19 @@ function defaultCodexConfigContent(context) {
|
|
|
2325
2378
|
].join('\n');
|
|
2326
2379
|
}
|
|
2327
2380
|
function defaultClaudeSettingsContent(context) {
|
|
2381
|
+
const settings = {
|
|
2382
|
+
env: {
|
|
2383
|
+
AGENT_DIR: context.agentDir,
|
|
2384
|
+
AGENT_RUN_PROJECT_ROOT: context.projectRoot,
|
|
2385
|
+
AGENT_GLOBAL_MEMORY_DIR: context.paths.globalMemoryDir
|
|
2386
|
+
}
|
|
2387
|
+
};
|
|
2388
|
+
if (context.permissionsAllow.length > 0) {
|
|
2389
|
+
settings.permissions = { allow: context.permissionsAllow };
|
|
2390
|
+
}
|
|
2391
|
+
return `${JSON.stringify(settings, null, 2)}\n`;
|
|
2392
|
+
}
|
|
2393
|
+
function legacyDefaultClaudeSettingsContent(context) {
|
|
2328
2394
|
return `${JSON.stringify({
|
|
2329
2395
|
env: {
|
|
2330
2396
|
AGENT_DIR: context.agentDir,
|
|
@@ -1,8 +1,22 @@
|
|
|
1
|
-
{
|
|
1
|
+
{% if permissionsAllow.length %}{
|
|
2
2
|
"env": {
|
|
3
3
|
"AGENT_DIR": "{{ agentDir }}",
|
|
4
4
|
"AGENT_RUN_PROJECT_ROOT": "{{ projectRoot }}",
|
|
5
5
|
"AGENT_GLOBAL_MEMORY_DIR": "{{ paths.globalMemoryDir }}",
|
|
6
6
|
"STARTER_PROFILE": "{{ profile }}"
|
|
7
|
+
},
|
|
8
|
+
"permissions": {
|
|
9
|
+
"allow": [
|
|
10
|
+
"{{ permissionsAllow | join('",\n "') }}"
|
|
11
|
+
]
|
|
7
12
|
}
|
|
8
13
|
}
|
|
14
|
+
{% else %}{
|
|
15
|
+
"env": {
|
|
16
|
+
"AGENT_DIR": "{{ agentDir }}",
|
|
17
|
+
"AGENT_RUN_PROJECT_ROOT": "{{ projectRoot }}",
|
|
18
|
+
"AGENT_GLOBAL_MEMORY_DIR": "{{ paths.globalMemoryDir }}",
|
|
19
|
+
"STARTER_PROFILE": "{{ profile }}"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
{% endif %}
|
package/examples/basic-config/agent-config/starter/basic-project/overrides/claude-settings.json.njk
CHANGED
|
@@ -1,9 +1,24 @@
|
|
|
1
|
-
{
|
|
1
|
+
{% if permissionsAllow.length %}{
|
|
2
2
|
"env": {
|
|
3
3
|
"AGENT_DIR": "{{ agentDir }}",
|
|
4
4
|
"AGENT_RUN_PROJECT_ROOT": "{{ projectRoot }}",
|
|
5
5
|
"AGENT_GLOBAL_MEMORY_DIR": "{{ paths.globalMemoryDir }}",
|
|
6
6
|
"STARTER_PROFILE": "{{ profile }}",
|
|
7
7
|
"STARTER_OVERRIDE": "true"
|
|
8
|
+
},
|
|
9
|
+
"permissions": {
|
|
10
|
+
"allow": [
|
|
11
|
+
"{{ permissionsAllow | join('",\n "') }}"
|
|
12
|
+
]
|
|
8
13
|
}
|
|
9
14
|
}
|
|
15
|
+
{% else %}{
|
|
16
|
+
"env": {
|
|
17
|
+
"AGENT_DIR": "{{ agentDir }}",
|
|
18
|
+
"AGENT_RUN_PROJECT_ROOT": "{{ projectRoot }}",
|
|
19
|
+
"AGENT_GLOBAL_MEMORY_DIR": "{{ paths.globalMemoryDir }}",
|
|
20
|
+
"STARTER_PROFILE": "{{ profile }}",
|
|
21
|
+
"STARTER_OVERRIDE": "true"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
{% endif %}
|