@technomoron/agent-run 0.99.11 → 0.99.13
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 +9 -2
- package/README.md +6 -1
- package/dist/agent-run.js +159 -67
- package/examples/basic-config/agent-config/gitignore +2 -18
- package/examples/basic-config/agent-config/global/snippets/no-ai-files.md.njk +6 -0
- package/examples/basic-config/agent-config/global/tool-templates/AGENTS.md.njk +1 -0
- package/examples/basic-config/agent-config/global/tool-templates/claude-settings.json.njk +17 -1
- package/examples/basic-config/agent-config/global/tool-templates/codex-config.toml.njk +1 -0
- package/examples/basic-config/agent-config/starter/basic-project/local.md.njk +1 -0
- package/examples/basic-config/agent-config/starter/basic-project/overrides/claude-settings.json.njk +18 -1
- package/examples/basic-config/agent-config/starter/basic-project/overrides/codex-config.toml.njk +1 -0
- package/package.json +1 -1
package/CHANGES
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
CHANGES
|
|
2
2
|
=======
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
Version 0.99.13 (2026-04-27)
|
|
5
|
+
----------------------------
|
|
6
|
+
* Render each profile's generated files and runtime state under `live/`, leaving the profile root for source config and templates.
|
|
7
|
+
|
|
8
|
+
Version 0.99.12 (2026-04-27)
|
|
9
|
+
----------------------------
|
|
10
|
+
* Add `--local` for Codex and Claude runs to warn about local AI files instead of failing.
|
|
11
|
+
* Limit generated Claude permission allow entries to configured checks instead of broad blocked command families.
|
|
12
|
+
* Write agent-run's Claude settings to `.claude/agent-run-settings.json` and remove only exact legacy generated `.claude/settings.json` files.
|
|
6
13
|
|
|
7
14
|
Version 0.99.11 (2026-04-27)
|
|
8
15
|
----------------------------
|
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
|
@@ -22,28 +22,13 @@ const CONFIG_DIR_ENV = 'AGENT_CONFIG_DIR';
|
|
|
22
22
|
const VERBOSE_ENV = 'AGENT_RUN_VERBOSE';
|
|
23
23
|
const MANIFEST_FILE_NAME = 'agent-run.jsonc';
|
|
24
24
|
const LOCAL_TEMPLATE_FILE_NAME = 'local.md.njk';
|
|
25
|
+
const LIVE_DIR_NAME = 'live';
|
|
25
26
|
const PACKAGE_VERSION = '0.99.10';
|
|
26
27
|
const UNEXPANDED_TEMPLATE_RE = /\{\{[^}]+\}\}|\{%[^%]+%\}/;
|
|
27
28
|
const agentRunEnvCache = new Map();
|
|
28
29
|
const GENERATED_GITIGNORE_ENTRIES = [
|
|
29
|
-
'# Generated agent-run
|
|
30
|
-
'**/
|
|
31
|
-
'**/CLAUDE.md',
|
|
32
|
-
'**/GEMINI.md',
|
|
33
|
-
'**/config.toml',
|
|
34
|
-
'',
|
|
35
|
-
'# Generated native agent homes',
|
|
36
|
-
'**/.agents/',
|
|
37
|
-
'**/.claude/',
|
|
38
|
-
'**/.codex/',
|
|
39
|
-
'',
|
|
40
|
-
'# Generated runtime files',
|
|
41
|
-
'**/bin/',
|
|
42
|
-
'**/reviews/',
|
|
43
|
-
'**/memories/',
|
|
44
|
-
'',
|
|
45
|
-
'# Generated review reports',
|
|
46
|
-
'**/REVIEW-*.md',
|
|
30
|
+
'# Generated agent-run live profiles',
|
|
31
|
+
'**/live/',
|
|
47
32
|
'',
|
|
48
33
|
'# Optional generated caches',
|
|
49
34
|
'**/.agent-run-cache/'
|
|
@@ -216,6 +201,7 @@ function parseRunCommand(command, inputArgs) {
|
|
|
216
201
|
const wrapperArgs = {
|
|
217
202
|
none: false,
|
|
218
203
|
create: false,
|
|
204
|
+
local: false,
|
|
219
205
|
codexSandboxMode: null,
|
|
220
206
|
codexNetwork: false
|
|
221
207
|
};
|
|
@@ -238,6 +224,10 @@ function parseRunCommand(command, inputArgs) {
|
|
|
238
224
|
wrapperArgs.create = true;
|
|
239
225
|
continue;
|
|
240
226
|
}
|
|
227
|
+
if (arg === '--local') {
|
|
228
|
+
wrapperArgs.local = true;
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
241
231
|
if (arg === '--danger') {
|
|
242
232
|
if (command !== 'codex') {
|
|
243
233
|
fail('--danger is only supported for agent-run codex');
|
|
@@ -412,9 +402,10 @@ function renderHelp(topic) {
|
|
|
412
402
|
' agent-run --init [config-root]',
|
|
413
403
|
'',
|
|
414
404
|
'Commands:',
|
|
415
|
-
' codex [--none] [--create] [--danger|--sandboxed] [--network] [args...]',
|
|
405
|
+
' codex [--none] [--create] [--local] [--danger|--sandboxed] [--network] [args...]',
|
|
416
406
|
' Run codex with generated private config',
|
|
417
|
-
' claude [--none] [--create] [args...]
|
|
407
|
+
' claude [--none] [--create] [--local] [args...]',
|
|
408
|
+
' Run claude with generated private config',
|
|
418
409
|
' check [--all] [path] Validate generated profile output',
|
|
419
410
|
' init [path] Create profile source files and render output',
|
|
420
411
|
' edit [path] Open local.md.njk or legacy AGENTS-MODS.md',
|
|
@@ -429,6 +420,7 @@ function renderHelp(topic) {
|
|
|
429
420
|
' --init [DIR] Copy the packaged starter config root to DIR (default ~/.agent-config)',
|
|
430
421
|
'',
|
|
431
422
|
'Codex wrapper options:',
|
|
423
|
+
' --local Warn about local AI files instead of failing',
|
|
432
424
|
' --danger Run Codex with no sandbox: -a never -s danger-full-access (default)',
|
|
433
425
|
' --sandboxed Run Codex with workspace-write sandbox',
|
|
434
426
|
' --network Enable network for --sandboxed via config override',
|
|
@@ -495,7 +487,10 @@ function runTool(parsed) {
|
|
|
495
487
|
const excludedDir = profileResult.profile === null ? null : resolveAgentDir(projectRoot);
|
|
496
488
|
const localAiFiles = findLocalAiFiles(projectRoot, excludedDir);
|
|
497
489
|
if (localAiFiles.length > 0) {
|
|
498
|
-
|
|
490
|
+
if (!wrapperArgs.local) {
|
|
491
|
+
failForLocalAiFiles(command, projectRoot, localAiFiles);
|
|
492
|
+
}
|
|
493
|
+
warnForLocalAiFiles(command, projectRoot, localAiFiles);
|
|
499
494
|
}
|
|
500
495
|
if (profileResult.profile === null) {
|
|
501
496
|
fail(profileResult.reason);
|
|
@@ -512,7 +507,7 @@ function runTool(parsed) {
|
|
|
512
507
|
runCodex(realBinary, permissionArgs, agentDir, configRoot, args, projectRoot, wrapperArgs);
|
|
513
508
|
return;
|
|
514
509
|
}
|
|
515
|
-
runClaude(realBinary, permissionArgs, agentDir, configRoot, args, projectRoot);
|
|
510
|
+
runClaude(realBinary, permissionArgs, agentDir, configRoot, args, projectRoot, wrapperArgs);
|
|
516
511
|
}
|
|
517
512
|
function runInit(parsed) {
|
|
518
513
|
const projectRoot = findProjectRoot(parsed.targetPath);
|
|
@@ -660,7 +655,8 @@ function runCheck(parsed) {
|
|
|
660
655
|
}
|
|
661
656
|
function printUpdateSummary(rendered) {
|
|
662
657
|
process.stdout.write(`OK profile ${rendered.profile}\n`);
|
|
663
|
-
process.stdout.write(`
|
|
658
|
+
process.stdout.write(`Profile dir: ${rendered.agentDir}\n`);
|
|
659
|
+
process.stdout.write(`Live dir: ${rendered.context.paths.liveDir}\n`);
|
|
664
660
|
process.stdout.write(`Generated files: ${rendered.files.length}\n`);
|
|
665
661
|
process.stdout.write(`Installed skills: ${rendered.skills.map((skill) => skill.name).join(', ') || '(none)'}\n`);
|
|
666
662
|
}
|
|
@@ -982,37 +978,52 @@ function createNunjucksEnv(configRoot) {
|
|
|
982
978
|
throwOnUndefined: true
|
|
983
979
|
});
|
|
984
980
|
}
|
|
985
|
-
function buildRenderContext(projectRoot,
|
|
981
|
+
function buildRenderContext(projectRoot, profileDir, configRoot, manifest, env) {
|
|
986
982
|
const date = localDateString();
|
|
983
|
+
const liveDir = path.join(profileDir, LIVE_DIR_NAME);
|
|
987
984
|
const baseContext = {
|
|
988
985
|
profile: manifest.profile,
|
|
989
986
|
kind: manifest.kind,
|
|
990
987
|
projectRoot,
|
|
991
|
-
agentDir,
|
|
988
|
+
agentDir: liveDir,
|
|
989
|
+
profileDir,
|
|
992
990
|
configRoot,
|
|
993
991
|
date,
|
|
994
992
|
checks: manifest.checks,
|
|
995
993
|
guardrails: manifest.guardrails
|
|
996
994
|
};
|
|
997
995
|
const paths = {
|
|
996
|
+
profileDir,
|
|
997
|
+
liveDir,
|
|
998
998
|
changesFile: resolveRuntimePath(configRoot, manifest.paths.changesFile, env, baseContext),
|
|
999
999
|
reviewDir: resolveRuntimePath(configRoot, manifest.paths.reviewDir, env, baseContext),
|
|
1000
1000
|
reviewFile: resolveRuntimePath(configRoot, manifest.paths.reviewFile, env, baseContext),
|
|
1001
1001
|
memoriesDir: resolveRuntimePath(configRoot, manifest.paths.memoriesDir, env, baseContext),
|
|
1002
1002
|
globalMemoryDir: globalMemoryDir(configRoot),
|
|
1003
1003
|
codexHomeDir: path.join(resolveRuntimePath(configRoot, manifest.paths.memoriesDir, env, baseContext), 'codex-home'),
|
|
1004
|
-
overridesDir: path.join(
|
|
1005
|
-
codexSkillsDir: path.join(
|
|
1006
|
-
claudeSkillsDir: path.join(
|
|
1007
|
-
binDir: path.join(
|
|
1004
|
+
overridesDir: path.join(profileDir, 'overrides'),
|
|
1005
|
+
codexSkillsDir: path.join(liveDir, '.agents', 'skills'),
|
|
1006
|
+
claudeSkillsDir: path.join(liveDir, '.claude', 'skills'),
|
|
1007
|
+
binDir: path.join(liveDir, 'bin')
|
|
1008
1008
|
};
|
|
1009
1009
|
return {
|
|
1010
1010
|
...baseContext,
|
|
1011
1011
|
paths,
|
|
1012
|
+
permissionsAllow: buildPermissionsAllow(manifest),
|
|
1012
1013
|
skills: [],
|
|
1013
1014
|
renderedAgentSections: []
|
|
1014
1015
|
};
|
|
1015
1016
|
}
|
|
1017
|
+
function buildPermissionsAllow(manifest) {
|
|
1018
|
+
const allow = new Set();
|
|
1019
|
+
for (const check of manifest.checks) {
|
|
1020
|
+
const normalizedCheck = check.trim();
|
|
1021
|
+
if (normalizedCheck) {
|
|
1022
|
+
allow.add(`Bash(${normalizedCheck})`);
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
return [...allow];
|
|
1026
|
+
}
|
|
1016
1027
|
function resolveConfigPath(configRoot, relativePath, context) {
|
|
1017
1028
|
const env = createNunjucksEnv(configRoot);
|
|
1018
1029
|
const rendered = renderInlineTemplate(env, relativePath, context);
|
|
@@ -1114,11 +1125,14 @@ function renderProfile(projectRoot, agentDir, checkOnly = false) {
|
|
|
1114
1125
|
const files = [];
|
|
1115
1126
|
const agentsContent = renderToolInstructions('AGENTS.md', env, configRoot, context, false);
|
|
1116
1127
|
const claudeContent = renderToolInstructions('CLAUDE.md', env, configRoot, context, true);
|
|
1117
|
-
files.push({ path: path.join(
|
|
1118
|
-
files.push({ path: path.join(
|
|
1119
|
-
files.push({ path: path.join(
|
|
1120
|
-
files.push({ path: path.join(
|
|
1121
|
-
files.push({
|
|
1128
|
+
files.push({ path: path.join(context.paths.liveDir, 'AGENTS.md'), content: agentsContent });
|
|
1129
|
+
files.push({ path: path.join(context.paths.liveDir, 'CLAUDE.md'), content: claudeContent });
|
|
1130
|
+
files.push({ path: path.join(context.paths.liveDir, '.claude', 'CLAUDE.md'), content: claudeContent });
|
|
1131
|
+
files.push({ path: path.join(context.paths.liveDir, 'config.toml'), content: renderCodexConfig(env, configRoot, context) });
|
|
1132
|
+
files.push({
|
|
1133
|
+
path: path.join(context.paths.liveDir, '.claude', 'agent-run-settings.json'),
|
|
1134
|
+
content: renderClaudeSettings(env, configRoot, context)
|
|
1135
|
+
});
|
|
1122
1136
|
files.push(...renderNativeSkillFiles(context));
|
|
1123
1137
|
files.push(...renderGuardShims(context));
|
|
1124
1138
|
return {
|
|
@@ -1136,8 +1150,28 @@ function syncAgentProfile(projectRoot, agentDir) {
|
|
|
1136
1150
|
for (const file of rendered.files) {
|
|
1137
1151
|
writeGeneratedFile(file.path, file.content, file.executable ?? false);
|
|
1138
1152
|
}
|
|
1153
|
+
removeLegacyGeneratedClaudeSettings(rendered.context);
|
|
1139
1154
|
return rendered;
|
|
1140
1155
|
}
|
|
1156
|
+
function removeLegacyGeneratedClaudeSettings(context) {
|
|
1157
|
+
for (const legacyPath of [
|
|
1158
|
+
path.join(context.paths.liveDir, '.claude', 'settings.json'),
|
|
1159
|
+
path.join(context.profileDir, '.claude', 'settings.json')
|
|
1160
|
+
]) {
|
|
1161
|
+
if (!fs.existsSync(legacyPath)) {
|
|
1162
|
+
continue;
|
|
1163
|
+
}
|
|
1164
|
+
const actual = fs.readFileSync(legacyPath, 'utf8').replace(/\r\n/g, '\n');
|
|
1165
|
+
const legacyGeneratedContents = [
|
|
1166
|
+
legacyDefaultClaudeSettingsContent(context, context.agentDir),
|
|
1167
|
+
legacyDefaultClaudeSettingsContent(context, context.profileDir)
|
|
1168
|
+
];
|
|
1169
|
+
if (legacyGeneratedContents.includes(actual)) {
|
|
1170
|
+
fs.rmSync(legacyPath);
|
|
1171
|
+
verbose(`removed legacy generated Claude settings ${legacyPath}`);
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1141
1175
|
function checkRenderedProfile(projectRoot, agentDir) {
|
|
1142
1176
|
const findings = [];
|
|
1143
1177
|
const configRoot = defaultConfigRoot(projectRoot);
|
|
@@ -1157,6 +1191,7 @@ function checkRenderedProfile(projectRoot, agentDir) {
|
|
|
1157
1191
|
rendered.context.paths.reviewDir,
|
|
1158
1192
|
rendered.context.paths.memoriesDir,
|
|
1159
1193
|
rendered.context.paths.codexHomeDir,
|
|
1194
|
+
rendered.context.paths.liveDir,
|
|
1160
1195
|
rendered.context.paths.overridesDir,
|
|
1161
1196
|
rendered.context.paths.codexSkillsDir,
|
|
1162
1197
|
rendered.context.paths.claudeSkillsDir,
|
|
@@ -1278,7 +1313,7 @@ function syncRuntimeDirs(context) {
|
|
|
1278
1313
|
context.paths.codexSkillsDir,
|
|
1279
1314
|
context.paths.claudeSkillsDir,
|
|
1280
1315
|
context.paths.binDir,
|
|
1281
|
-
path.join(context.
|
|
1316
|
+
path.join(context.paths.liveDir, '.claude')
|
|
1282
1317
|
]) {
|
|
1283
1318
|
fs.mkdirSync(dir, { recursive: true });
|
|
1284
1319
|
}
|
|
@@ -1488,17 +1523,19 @@ function formatError(error) {
|
|
|
1488
1523
|
return error instanceof Error ? error.message : String(error);
|
|
1489
1524
|
}
|
|
1490
1525
|
function runCodex(realBinary, permissionArgs, agentDir, configRoot, args, projectRoot, wrapperArgs) {
|
|
1491
|
-
const
|
|
1526
|
+
const liveDir = profileLiveDir(agentDir);
|
|
1527
|
+
const agentsPath = path.join(liveDir, 'AGENTS.md');
|
|
1492
1528
|
if (!fs.existsSync(agentsPath)) {
|
|
1493
1529
|
failMissingConfig('codex', agentDir);
|
|
1494
1530
|
}
|
|
1495
|
-
const guardBin = path.join(
|
|
1496
|
-
const codexHomeDir = path.join(
|
|
1531
|
+
const guardBin = path.join(liveDir, 'bin');
|
|
1532
|
+
const codexHomeDir = path.join(liveDir, 'memories', 'codex-home');
|
|
1497
1533
|
fs.mkdirSync(codexHomeDir, { recursive: true });
|
|
1498
1534
|
const env = {
|
|
1499
1535
|
...process.env,
|
|
1500
1536
|
CODEX_HOME: codexHomeDir,
|
|
1501
|
-
AGENT_DIR:
|
|
1537
|
+
AGENT_DIR: liveDir,
|
|
1538
|
+
AGENT_PROFILE_DIR: agentDir,
|
|
1502
1539
|
AGENT_RUN_PROJECT_ROOT: projectRoot,
|
|
1503
1540
|
PATH: `${guardBin}${path.delimiter}${process.env.PATH ?? ''}`
|
|
1504
1541
|
};
|
|
@@ -1517,7 +1554,7 @@ function runCodex(realBinary, permissionArgs, agentDir, configRoot, args, projec
|
|
|
1517
1554
|
? ['--config', 'sandbox_workspace_write.network_access=true']
|
|
1518
1555
|
: []),
|
|
1519
1556
|
...args
|
|
1520
|
-
], shouldUseShell(realBinary), env, codexHomeDir, (code) => postflightProjectCheck(projectRoot, agentDir, code));
|
|
1557
|
+
], shouldUseShell(realBinary), env, codexHomeDir, (code) => postflightProjectCheck(projectRoot, agentDir, wrapperArgs.local, code));
|
|
1521
1558
|
}
|
|
1522
1559
|
function buildCodexRuntimeArgs(wrapperArgs) {
|
|
1523
1560
|
const mode = wrapperArgs.codexSandboxMode ?? 'danger';
|
|
@@ -1526,31 +1563,36 @@ function buildCodexRuntimeArgs(wrapperArgs) {
|
|
|
1526
1563
|
}
|
|
1527
1564
|
return ['-a', 'never', '-s', 'danger-full-access'];
|
|
1528
1565
|
}
|
|
1529
|
-
function runClaude(realBinary, permissionArgs, agentDir, configRoot, args, projectRoot) {
|
|
1530
|
-
const
|
|
1566
|
+
function runClaude(realBinary, permissionArgs, agentDir, configRoot, args, projectRoot, wrapperArgs) {
|
|
1567
|
+
const liveDir = profileLiveDir(agentDir);
|
|
1568
|
+
const claudePath = path.join(liveDir, 'CLAUDE.md');
|
|
1531
1569
|
if (!fs.existsSync(claudePath)) {
|
|
1532
1570
|
failMissingConfig('claude', agentDir);
|
|
1533
1571
|
}
|
|
1534
|
-
const guardBin = path.join(
|
|
1535
|
-
const claudeConfigDir = path.join(
|
|
1572
|
+
const guardBin = path.join(liveDir, 'bin');
|
|
1573
|
+
const claudeConfigDir = path.join(liveDir, '.claude');
|
|
1536
1574
|
const env = {
|
|
1537
1575
|
...process.env,
|
|
1538
1576
|
CLAUDE_CONFIG_DIR: claudeConfigDir,
|
|
1539
|
-
AGENT_DIR:
|
|
1577
|
+
AGENT_DIR: liveDir,
|
|
1578
|
+
AGENT_PROFILE_DIR: agentDir,
|
|
1540
1579
|
AGENT_RUN_PROJECT_ROOT: projectRoot,
|
|
1541
1580
|
PATH: `${guardBin}${path.delimiter}${process.env.PATH ?? ''}`
|
|
1542
1581
|
};
|
|
1543
1582
|
execCommand(realBinary, [
|
|
1544
1583
|
...permissionArgs,
|
|
1545
1584
|
'--settings',
|
|
1546
|
-
path.join(claudeConfigDir, 'settings.json'),
|
|
1585
|
+
path.join(claudeConfigDir, 'agent-run-settings.json'),
|
|
1547
1586
|
'--add-dir',
|
|
1548
1587
|
projectRoot,
|
|
1549
1588
|
'--add-dir',
|
|
1550
|
-
|
|
1589
|
+
liveDir,
|
|
1551
1590
|
...globalMemoryArgs(configRoot),
|
|
1552
1591
|
...args
|
|
1553
|
-
], shouldUseShell(realBinary), env, projectRoot, (code) => postflightProjectCheck(projectRoot, agentDir, code));
|
|
1592
|
+
], shouldUseShell(realBinary), env, projectRoot, (code) => postflightProjectCheck(projectRoot, agentDir, wrapperArgs.local, code));
|
|
1593
|
+
}
|
|
1594
|
+
function profileLiveDir(agentDir) {
|
|
1595
|
+
return path.join(agentDir, LIVE_DIR_NAME);
|
|
1554
1596
|
}
|
|
1555
1597
|
function globalMemoryArgs(configRoot) {
|
|
1556
1598
|
const memoryDir = globalMemoryDir(configRoot);
|
|
@@ -1559,16 +1601,15 @@ function globalMemoryArgs(configRoot) {
|
|
|
1559
1601
|
function globalMemoryDir(configRoot) {
|
|
1560
1602
|
return path.join(configRoot, 'notes', 'memory');
|
|
1561
1603
|
}
|
|
1562
|
-
function postflightProjectCheck(projectRoot, agentDir, code) {
|
|
1604
|
+
function postflightProjectCheck(projectRoot, agentDir, allowLocal, code) {
|
|
1563
1605
|
const localAiFiles = findLocalAiFiles(projectRoot, agentDir);
|
|
1564
|
-
if (localAiFiles.length
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
process.stderr.write(`agent-run: ${file}\n`);
|
|
1606
|
+
if (localAiFiles.length > 0) {
|
|
1607
|
+
warnForLocalAiFiles(null, projectRoot, localAiFiles);
|
|
1608
|
+
if (!allowLocal) {
|
|
1609
|
+
return 1;
|
|
1610
|
+
}
|
|
1570
1611
|
}
|
|
1571
|
-
return
|
|
1612
|
+
return code;
|
|
1572
1613
|
}
|
|
1573
1614
|
function failMissingConfig(tool, agentDir) {
|
|
1574
1615
|
process.stderr.write(`agent-run: no ${tool} config found for this project: ${agentDir}\n`);
|
|
@@ -1648,6 +1689,7 @@ function isSamePathOrDescendant(candidatePath, parentPath) {
|
|
|
1648
1689
|
function shouldPruneProjectEntry(entry) {
|
|
1649
1690
|
return (entry.isDirectory() &&
|
|
1650
1691
|
(entry.name === '.git' ||
|
|
1692
|
+
entry.name === '.claude' ||
|
|
1651
1693
|
entry.name === 'node_modules' ||
|
|
1652
1694
|
entry.name === '.pnpm-store' ||
|
|
1653
1695
|
entry.name === 'dist' ||
|
|
@@ -1666,13 +1708,21 @@ function isIgnoredDir(dir) {
|
|
|
1666
1708
|
const env = readAgentRunEnv(dir);
|
|
1667
1709
|
return parseBooleanEnv(env.AGENT_RUN_IGNORE);
|
|
1668
1710
|
}
|
|
1711
|
+
function warnForLocalAiFiles(tool, projectRoot, localAiFiles) {
|
|
1712
|
+
process.stderr.write(`WARNING: local AI files found in project root ${projectRoot}\n`);
|
|
1713
|
+
for (const file of localAiFiles) {
|
|
1714
|
+
process.stderr.write(`WARNING: ${path.relative(projectRoot, file)}\n`);
|
|
1715
|
+
}
|
|
1716
|
+
if (tool !== null) {
|
|
1717
|
+
process.stderr.write(`WARNING: consider moving these files out of the project, or run \`agent-run ${tool} --none\` to bypass the wrapper.\n`);
|
|
1718
|
+
}
|
|
1719
|
+
}
|
|
1669
1720
|
function failForLocalAiFiles(tool, projectRoot, localAiFiles) {
|
|
1670
1721
|
process.stderr.write(`agent-run: found local AI files in project root ${projectRoot}\n`);
|
|
1671
1722
|
for (const file of localAiFiles) {
|
|
1672
1723
|
process.stderr.write(`agent-run: ${file}\n`);
|
|
1673
1724
|
}
|
|
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`);
|
|
1725
|
+
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
1726
|
process.exit(1);
|
|
1677
1727
|
}
|
|
1678
1728
|
function findProjectRoot(cwd) {
|
|
@@ -2093,6 +2143,12 @@ function defaultLocalTemplate(_profile) {
|
|
|
2093
2143
|
'{{ agentDir }}',
|
|
2094
2144
|
'```',
|
|
2095
2145
|
'',
|
|
2146
|
+
'Profile source directory:',
|
|
2147
|
+
'',
|
|
2148
|
+
'```text',
|
|
2149
|
+
'{{ profileDir }}',
|
|
2150
|
+
'```',
|
|
2151
|
+
'',
|
|
2096
2152
|
'Add project-specific rules here.',
|
|
2097
2153
|
''
|
|
2098
2154
|
].join('\n');
|
|
@@ -2135,7 +2191,8 @@ function defaultNoAiFilesSnippet() {
|
|
|
2135
2191
|
'## Agent File Storage',
|
|
2136
2192
|
'',
|
|
2137
2193
|
'Do not create AGENTS.md, CLAUDE.md, .agents, .claude, .codex, or other agent runtime files inside the project repository.',
|
|
2138
|
-
'
|
|
2194
|
+
'Generated agent-only files belong under {{ paths.liveDir }}.',
|
|
2195
|
+
'Source config files belong under {{ profileDir }}.',
|
|
2139
2196
|
''
|
|
2140
2197
|
].join('\n');
|
|
2141
2198
|
}
|
|
@@ -2207,8 +2264,8 @@ function defaultToolInstructionsTemplate(isClaude) {
|
|
|
2207
2264
|
'Do not edit this file directly. Edit:',
|
|
2208
2265
|
'',
|
|
2209
2266
|
'```text',
|
|
2210
|
-
'{{
|
|
2211
|
-
'{{
|
|
2267
|
+
'{{ profileDir }}/agent-run.jsonc',
|
|
2268
|
+
'{{ profileDir }}/local.md.njk',
|
|
2212
2269
|
'```',
|
|
2213
2270
|
'',
|
|
2214
2271
|
'{% for section in renderedAgentSections %}',
|
|
@@ -2229,6 +2286,12 @@ function defaultToolInstructionsTemplate(isClaude) {
|
|
|
2229
2286
|
'{{ agentDir }}',
|
|
2230
2287
|
'```',
|
|
2231
2288
|
'',
|
|
2289
|
+
'Profile source directory:',
|
|
2290
|
+
'',
|
|
2291
|
+
'```text',
|
|
2292
|
+
'{{ profileDir }}',
|
|
2293
|
+
'```',
|
|
2294
|
+
'',
|
|
2232
2295
|
'Review directory:',
|
|
2233
2296
|
'',
|
|
2234
2297
|
'```text',
|
|
@@ -2268,13 +2331,14 @@ function defaultToolInstructionsTemplate(isClaude) {
|
|
|
2268
2331
|
'## Tool Note',
|
|
2269
2332
|
'',
|
|
2270
2333
|
isClaude
|
|
2271
|
-
? 'Claude uses the generated config directory under {{
|
|
2334
|
+
? 'Claude uses the generated config directory under {{ paths.liveDir }}/.claude and may read {{ paths.liveDir }} via `--add-dir`.'
|
|
2272
2335
|
: 'Codex uses {{ agentDir }}/AGENTS.md as `system_prompt_file` and {{ paths.codexHomeDir }} as CODEX_HOME.',
|
|
2273
2336
|
'',
|
|
2274
2337
|
'## Mandatory Path Rule',
|
|
2275
2338
|
'',
|
|
2276
2339
|
'Do not create AGENTS.md, CLAUDE.md, .agents, .claude, .codex, or AI-related files inside the project repository.',
|
|
2277
|
-
'
|
|
2340
|
+
'Generated agent-only files must be stored under the agent directory shown above.',
|
|
2341
|
+
'Source config files must be stored under the profile source directory shown above.',
|
|
2278
2342
|
''
|
|
2279
2343
|
].join('\n');
|
|
2280
2344
|
}
|
|
@@ -2289,6 +2353,7 @@ function defaultCodexConfigTemplate() {
|
|
|
2289
2353
|
'writable_roots = [',
|
|
2290
2354
|
' "{{ projectRoot }}",',
|
|
2291
2355
|
' "{{ agentDir }}",',
|
|
2356
|
+
' "{{ profileDir }}",',
|
|
2292
2357
|
' "{{ paths.globalMemoryDir }}"',
|
|
2293
2358
|
']',
|
|
2294
2359
|
'network_access = false',
|
|
@@ -2296,15 +2361,27 @@ function defaultCodexConfigTemplate() {
|
|
|
2296
2361
|
].join('\n');
|
|
2297
2362
|
}
|
|
2298
2363
|
function defaultClaudeSettingsTemplate() {
|
|
2299
|
-
|
|
2300
|
-
'{',
|
|
2364
|
+
const envBlock = [
|
|
2301
2365
|
' "env": {',
|
|
2302
2366
|
' "AGENT_DIR": "{{ agentDir }}",',
|
|
2367
|
+
' "AGENT_PROFILE_DIR": "{{ profileDir }}",',
|
|
2303
2368
|
' "AGENT_RUN_PROJECT_ROOT": "{{ projectRoot }}",',
|
|
2304
2369
|
' "AGENT_GLOBAL_MEMORY_DIR": "{{ paths.globalMemoryDir }}"',
|
|
2370
|
+
' }'
|
|
2371
|
+
].join('\n');
|
|
2372
|
+
return [
|
|
2373
|
+
'{% if permissionsAllow.length %}{',
|
|
2374
|
+
envBlock + ',',
|
|
2375
|
+
' "permissions": {',
|
|
2376
|
+
' "allow": [',
|
|
2377
|
+
' "{{ permissionsAllow | join(\'",\\n "\') }}"',
|
|
2378
|
+
' ]',
|
|
2305
2379
|
' }',
|
|
2306
2380
|
'}',
|
|
2307
|
-
''
|
|
2381
|
+
'{% else %}{',
|
|
2382
|
+
envBlock,
|
|
2383
|
+
'}',
|
|
2384
|
+
'{% endif %}'
|
|
2308
2385
|
].join('\n');
|
|
2309
2386
|
}
|
|
2310
2387
|
function defaultCodexConfigContent(context) {
|
|
@@ -2318,6 +2395,7 @@ function defaultCodexConfigContent(context) {
|
|
|
2318
2395
|
'writable_roots = [',
|
|
2319
2396
|
` ${jsonString(context.projectRoot)},`,
|
|
2320
2397
|
` ${jsonString(context.agentDir)},`,
|
|
2398
|
+
` ${jsonString(context.profileDir)},`,
|
|
2321
2399
|
` ${jsonString(context.paths.globalMemoryDir)}`,
|
|
2322
2400
|
']',
|
|
2323
2401
|
'network_access = false',
|
|
@@ -2325,9 +2403,23 @@ function defaultCodexConfigContent(context) {
|
|
|
2325
2403
|
].join('\n');
|
|
2326
2404
|
}
|
|
2327
2405
|
function defaultClaudeSettingsContent(context) {
|
|
2328
|
-
|
|
2406
|
+
const settings = {
|
|
2329
2407
|
env: {
|
|
2330
2408
|
AGENT_DIR: context.agentDir,
|
|
2409
|
+
AGENT_PROFILE_DIR: context.profileDir,
|
|
2410
|
+
AGENT_RUN_PROJECT_ROOT: context.projectRoot,
|
|
2411
|
+
AGENT_GLOBAL_MEMORY_DIR: context.paths.globalMemoryDir
|
|
2412
|
+
}
|
|
2413
|
+
};
|
|
2414
|
+
if (context.permissionsAllow.length > 0) {
|
|
2415
|
+
settings.permissions = { allow: context.permissionsAllow };
|
|
2416
|
+
}
|
|
2417
|
+
return `${JSON.stringify(settings, null, 2)}\n`;
|
|
2418
|
+
}
|
|
2419
|
+
function legacyDefaultClaudeSettingsContent(context, agentDir) {
|
|
2420
|
+
return `${JSON.stringify({
|
|
2421
|
+
env: {
|
|
2422
|
+
AGENT_DIR: agentDir,
|
|
2331
2423
|
AGENT_RUN_PROJECT_ROOT: context.projectRoot,
|
|
2332
2424
|
AGENT_GLOBAL_MEMORY_DIR: context.paths.globalMemoryDir
|
|
2333
2425
|
}
|
|
@@ -1,21 +1,5 @@
|
|
|
1
|
-
# Generated agent-run
|
|
2
|
-
**/
|
|
3
|
-
**/CLAUDE.md
|
|
4
|
-
**/GEMINI.md
|
|
5
|
-
**/config.toml
|
|
6
|
-
|
|
7
|
-
# Generated native agent homes
|
|
8
|
-
**/.agents/
|
|
9
|
-
**/.claude/
|
|
10
|
-
**/.codex/
|
|
11
|
-
|
|
12
|
-
# Generated runtime files
|
|
13
|
-
**/bin/
|
|
14
|
-
**/reviews/
|
|
15
|
-
**/memories/
|
|
16
|
-
|
|
17
|
-
# Generated review reports
|
|
18
|
-
**/REVIEW-*.md
|
|
1
|
+
# Generated agent-run live profiles
|
|
2
|
+
**/live/
|
|
19
3
|
|
|
20
4
|
# Optional generated caches
|
|
21
5
|
**/.agent-run-cache/
|
|
@@ -10,6 +10,7 @@ Do not edit this generated file. Edit `agent-run.jsonc` and `local.md.njk`.
|
|
|
10
10
|
|
|
11
11
|
- projectRoot: `{{ projectRoot }}`
|
|
12
12
|
- agentDir: `{{ agentDir }}`
|
|
13
|
+
- profileDir: `{{ profileDir }}`
|
|
13
14
|
- reviewFile: `{{ paths.reviewFile }}`
|
|
14
15
|
- memoriesDir: `{{ paths.memoriesDir }}`
|
|
15
16
|
- globalMemoryDir: `{{ paths.globalMemoryDir }}`
|
|
@@ -1,8 +1,24 @@
|
|
|
1
|
-
{
|
|
1
|
+
{% if permissionsAllow.length %}{
|
|
2
2
|
"env": {
|
|
3
3
|
"AGENT_DIR": "{{ agentDir }}",
|
|
4
|
+
"AGENT_PROFILE_DIR": "{{ profileDir }}",
|
|
4
5
|
"AGENT_RUN_PROJECT_ROOT": "{{ projectRoot }}",
|
|
5
6
|
"AGENT_GLOBAL_MEMORY_DIR": "{{ paths.globalMemoryDir }}",
|
|
6
7
|
"STARTER_PROFILE": "{{ profile }}"
|
|
8
|
+
},
|
|
9
|
+
"permissions": {
|
|
10
|
+
"allow": [
|
|
11
|
+
"{{ permissionsAllow | join('",\n "') }}"
|
|
12
|
+
]
|
|
7
13
|
}
|
|
8
14
|
}
|
|
15
|
+
{% else %}{
|
|
16
|
+
"env": {
|
|
17
|
+
"AGENT_DIR": "{{ agentDir }}",
|
|
18
|
+
"AGENT_PROFILE_DIR": "{{ profileDir }}",
|
|
19
|
+
"AGENT_RUN_PROJECT_ROOT": "{{ projectRoot }}",
|
|
20
|
+
"AGENT_GLOBAL_MEMORY_DIR": "{{ paths.globalMemoryDir }}",
|
|
21
|
+
"STARTER_PROFILE": "{{ profile }}"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
{% endif %}
|
package/examples/basic-config/agent-config/starter/basic-project/overrides/claude-settings.json.njk
CHANGED
|
@@ -1,9 +1,26 @@
|
|
|
1
|
-
{
|
|
1
|
+
{% if permissionsAllow.length %}{
|
|
2
2
|
"env": {
|
|
3
3
|
"AGENT_DIR": "{{ agentDir }}",
|
|
4
|
+
"AGENT_PROFILE_DIR": "{{ profileDir }}",
|
|
4
5
|
"AGENT_RUN_PROJECT_ROOT": "{{ projectRoot }}",
|
|
5
6
|
"AGENT_GLOBAL_MEMORY_DIR": "{{ paths.globalMemoryDir }}",
|
|
6
7
|
"STARTER_PROFILE": "{{ profile }}",
|
|
7
8
|
"STARTER_OVERRIDE": "true"
|
|
9
|
+
},
|
|
10
|
+
"permissions": {
|
|
11
|
+
"allow": [
|
|
12
|
+
"{{ permissionsAllow | join('",\n "') }}"
|
|
13
|
+
]
|
|
8
14
|
}
|
|
9
15
|
}
|
|
16
|
+
{% else %}{
|
|
17
|
+
"env": {
|
|
18
|
+
"AGENT_DIR": "{{ agentDir }}",
|
|
19
|
+
"AGENT_PROFILE_DIR": "{{ profileDir }}",
|
|
20
|
+
"AGENT_RUN_PROJECT_ROOT": "{{ projectRoot }}",
|
|
21
|
+
"AGENT_GLOBAL_MEMORY_DIR": "{{ paths.globalMemoryDir }}",
|
|
22
|
+
"STARTER_PROFILE": "{{ profile }}",
|
|
23
|
+
"STARTER_OVERRIDE": "true"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
{% endif %}
|