@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 CHANGED
@@ -1,8 +1,15 @@
1
1
  CHANGES
2
2
  =======
3
3
 
4
- Unreleased (2026-04-24)
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 files',
30
- '**/AGENTS.md',
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...] Run claude with generated private config',
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
- failForLocalAiFiles(command, projectRoot, localAiFiles);
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(`Agent dir: ${rendered.agentDir}\n`);
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, agentDir, configRoot, manifest, env) {
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(agentDir, 'overrides'),
1005
- codexSkillsDir: path.join(agentDir, '.agents', 'skills'),
1006
- claudeSkillsDir: path.join(agentDir, '.claude', 'skills'),
1007
- binDir: path.join(agentDir, 'bin')
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(agentDir, 'AGENTS.md'), content: agentsContent });
1118
- files.push({ path: path.join(agentDir, 'CLAUDE.md'), content: claudeContent });
1119
- files.push({ path: path.join(agentDir, '.claude', 'CLAUDE.md'), content: claudeContent });
1120
- 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) });
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.agentDir, '.claude')
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 agentsPath = path.join(agentDir, 'AGENTS.md');
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(agentDir, 'bin');
1496
- const codexHomeDir = path.join(agentDir, 'memories', 'codex-home');
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: agentDir,
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 claudePath = path.join(agentDir, 'CLAUDE.md');
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(agentDir, 'bin');
1535
- const claudeConfigDir = path.join(agentDir, '.claude');
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: agentDir,
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
- agentDir,
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 === 0) {
1565
- return code;
1566
- }
1567
- process.stderr.write(`agent-run: postflight found local AI files in project root ${projectRoot}\n`);
1568
- for (const file of localAiFiles) {
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 1;
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, or run \`${tool}\` directly if you want to use the local files.\n`);
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
- 'Agent-only files belong under {{ agentDir }}.',
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
- '{{ agentDir }}/agent-run.jsonc',
2211
- '{{ agentDir }}/local.md.njk',
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 {{ agentDir }}/.claude and may read {{ agentDir }} via `--add-dir`.'
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
- 'Agent-only files must be stored under the agent directory shown above.',
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
- return [
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
- return `${JSON.stringify({
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 files
2
- **/AGENTS.md
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/
@@ -7,3 +7,9 @@ Agent directory:
7
7
  ```text
8
8
  {{ agentDir }}
9
9
  ```
10
+
11
+ Profile source directory:
12
+
13
+ ```text
14
+ {{ profileDir }}
15
+ ```
@@ -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 %}
@@ -6,6 +6,7 @@ sandbox_mode = "workspace-write"
6
6
  writable_roots = [
7
7
  "{{ projectRoot }}",
8
8
  "{{ agentDir }}",
9
+ "{{ profileDir }}",
9
10
  "{{ paths.memoriesDir }}",
10
11
  "{{ paths.globalMemoryDir }}"
11
12
  ]
@@ -3,3 +3,4 @@
3
3
  This starter profile belongs to `{{ profile }}`.
4
4
 
5
5
  Use the project root at `{{ projectRoot }}` and keep generated files in `{{ agentDir }}`.
6
+ Keep source profile edits in `{{ profileDir }}`.
@@ -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 %}
@@ -6,6 +6,7 @@ sandbox_mode = "workspace-write"
6
6
  writable_roots = [
7
7
  "{{ projectRoot }}",
8
8
  "{{ agentDir }}",
9
+ "{{ profileDir }}",
9
10
  "{{ paths.memoriesDir }}",
10
11
  "{{ paths.globalMemoryDir }}"
11
12
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@technomoron/agent-run",
3
- "version": "0.99.11",
3
+ "version": "0.99.13",
4
4
  "packageManager": "pnpm@10.28.1",
5
5
  "bin": {
6
6
  "agent-run": "dist/agent-run.js"