@technomoron/agent-run 0.99.13 → 0.99.14

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,10 @@
1
1
  CHANGES
2
2
  =======
3
3
 
4
+ Version 0.99.14 (2026-04-30)
5
+ ----------------------------
6
+ * Add `--show` for Codex and Claude runs to print the tool-specific source templates/includes and generated files without launching the underlying tool.
7
+
4
8
  Version 0.99.13 (2026-04-27)
5
9
  ----------------------------
6
10
  * Render each profile's generated files and runtime state under `live/`, leaving the profile root for source config and templates.
package/dist/agent-run.js CHANGED
@@ -202,6 +202,7 @@ function parseRunCommand(command, inputArgs) {
202
202
  none: false,
203
203
  create: false,
204
204
  local: false,
205
+ show: false,
205
206
  codexSandboxMode: null,
206
207
  codexNetwork: false
207
208
  };
@@ -228,6 +229,10 @@ function parseRunCommand(command, inputArgs) {
228
229
  wrapperArgs.local = true;
229
230
  continue;
230
231
  }
232
+ if (arg === '--show') {
233
+ wrapperArgs.show = true;
234
+ continue;
235
+ }
231
236
  if (arg === '--danger') {
232
237
  if (command !== 'codex') {
233
238
  fail('--danger is only supported for agent-run codex');
@@ -402,9 +407,9 @@ function renderHelp(topic) {
402
407
  ' agent-run --init [config-root]',
403
408
  '',
404
409
  'Commands:',
405
- ' codex [--none] [--create] [--local] [--danger|--sandboxed] [--network] [args...]',
410
+ ' codex [--none] [--create] [--local] [--show] [--danger|--sandboxed] [--network] [args...]',
406
411
  ' Run codex with generated private config',
407
- ' claude [--none] [--create] [--local] [args...]',
412
+ ' claude [--none] [--create] [--local] [--show] [args...]',
408
413
  ' Run claude with generated private config',
409
414
  ' check [--all] [path] Validate generated profile output',
410
415
  ' init [path] Create profile source files and render output',
@@ -419,8 +424,11 @@ function renderHelp(topic) {
419
424
  ' --config-root DIR Override the agent-config root',
420
425
  ' --init [DIR] Copy the packaged starter config root to DIR (default ~/.agent-config)',
421
426
  '',
422
- 'Codex wrapper options:',
427
+ 'Run wrapper options:',
423
428
  ' --local Warn about local AI files instead of failing',
429
+ ' --show Show read/include and generated files without running the tool',
430
+ '',
431
+ 'Codex wrapper options:',
424
432
  ' --danger Run Codex with no sandbox: -a never -s danger-full-access (default)',
425
433
  ' --sandboxed Run Codex with workspace-write sandbox',
426
434
  ' --network Enable network for --sandboxed via config override',
@@ -474,30 +482,41 @@ function normalizeCommandName(value) {
474
482
  }
475
483
  function runTool(parsed) {
476
484
  const { args, command, wrapperArgs } = parsed;
477
- const realBinary = findRealBinary(command);
478
- const permissionArgs = getPermissionArgs(command);
479
485
  const projectRoot = findProjectRoot(process.cwd());
480
486
  verbose(`run ${command}: cwd=${process.cwd()} projectRoot=${projectRoot}`);
487
+ if (wrapperArgs.show && wrapperArgs.none) {
488
+ fail('--show cannot be combined with --none');
489
+ }
490
+ if (wrapperArgs.show && isIgnoredDir(projectRoot)) {
491
+ fail(`cannot show generated ${command} files for ignored project: ${projectRoot}`);
492
+ }
481
493
  if (wrapperArgs.none || isIgnoredDir(projectRoot)) {
494
+ const realBinary = findRealBinary(command);
495
+ const permissionArgs = getPermissionArgs(command);
482
496
  verbose(`wrapper bypassed for ${command}${wrapperArgs.none ? ' via --none' : ' because project is ignored'}`);
483
497
  execTool(realBinary, [...permissionArgs, ...args]);
484
498
  return;
485
499
  }
486
500
  const profileResult = resolveProfileResult(projectRoot);
487
- const excludedDir = profileResult.profile === null ? null : resolveAgentDir(projectRoot);
488
- const localAiFiles = findLocalAiFiles(projectRoot, excludedDir);
489
- if (localAiFiles.length > 0) {
490
- if (!wrapperArgs.local) {
491
- failForLocalAiFiles(command, projectRoot, localAiFiles);
492
- }
493
- warnForLocalAiFiles(command, projectRoot, localAiFiles);
494
- }
495
501
  if (profileResult.profile === null) {
496
502
  fail(profileResult.reason);
497
503
  }
498
504
  const profile = profileResult.profile;
499
505
  const configRoot = defaultConfigRoot(projectRoot);
500
506
  const agentDir = resolveAgentDir(projectRoot);
507
+ if (wrapperArgs.show) {
508
+ showToolProfile(command, projectRoot, agentDir);
509
+ return;
510
+ }
511
+ const localAiFiles = findLocalAiFiles(projectRoot, agentDir);
512
+ if (localAiFiles.length > 0) {
513
+ if (!wrapperArgs.local) {
514
+ failForLocalAiFiles(command, projectRoot, localAiFiles);
515
+ }
516
+ warnForLocalAiFiles(command, projectRoot, localAiFiles);
517
+ }
518
+ const realBinary = findRealBinary(command);
519
+ const permissionArgs = getPermissionArgs(command);
501
520
  if (wrapperArgs.create) {
502
521
  runInit({ command: 'init', targetPath: projectRoot });
503
522
  }
@@ -509,6 +528,31 @@ function runTool(parsed) {
509
528
  }
510
529
  runClaude(realBinary, permissionArgs, agentDir, configRoot, args, projectRoot, wrapperArgs);
511
530
  }
531
+ function showToolProfile(command, projectRoot, agentDir) {
532
+ const trace = { sourceFiles: new Set() };
533
+ const rendered = renderProfile(projectRoot, agentDir, true, command, trace);
534
+ const generatedFiles = uniqueSorted(rendered.files.map((file) => file.path));
535
+ const sourceFiles = uniqueSorted([...trace.sourceFiles]);
536
+ process.stdout.write([
537
+ `Agent: ${command}`,
538
+ `Profile: ${rendered.profile}`,
539
+ `Project root: ${projectRoot}`,
540
+ `Profile dir: ${agentDir}`,
541
+ '',
542
+ 'Reads/includes:',
543
+ ...formatPathList(sourceFiles),
544
+ '',
545
+ 'Generates:',
546
+ ...formatPathList(generatedFiles),
547
+ ''
548
+ ].join('\n'));
549
+ }
550
+ function uniqueSorted(values) {
551
+ return [...new Set(values.map((value) => path.resolve(value)))].sort((a, b) => a.localeCompare(b));
552
+ }
553
+ function formatPathList(paths) {
554
+ return paths.length === 0 ? [' (none)'] : paths.map((entry) => ` ${entry}`);
555
+ }
512
556
  function runInit(parsed) {
513
557
  const projectRoot = findProjectRoot(parsed.targetPath);
514
558
  verbose(`init target=${parsed.targetPath} projectRoot=${projectRoot}`);
@@ -859,7 +903,7 @@ function createDefaultLocalFile(agentDir, profile) {
859
903
  function ensureProfileOverridesDir(agentDir) {
860
904
  fs.mkdirSync(path.join(agentDir, 'overrides'), { recursive: true });
861
905
  }
862
- function loadManifest(_configRoot, agentDir, profile) {
906
+ function loadManifest(_configRoot, agentDir, profile, trace) {
863
907
  const manifestPath = path.join(agentDir, MANIFEST_FILE_NAME);
864
908
  if (!fs.existsSync(manifestPath)) {
865
909
  const manifest = defaultManifest(profile);
@@ -879,6 +923,7 @@ function loadManifest(_configRoot, agentDir, profile) {
879
923
  }
880
924
  return manifest;
881
925
  }
926
+ trace?.sourceFiles.add(manifestPath);
882
927
  const text = fs.readFileSync(manifestPath, 'utf8');
883
928
  const errors = [];
884
929
  const parsed = (0, jsonc_parser_1.parse)(text, errors, { allowTrailingComma: true });
@@ -1037,19 +1082,48 @@ function resolveRuntimePath(configRoot, pathTemplate, env, context) {
1037
1082
  const rendered = renderInlineTemplate(env, pathTemplate, context);
1038
1083
  return path.isAbsolute(rendered) ? path.resolve(rendered) : path.resolve(configRoot, rendered);
1039
1084
  }
1040
- function renderTemplateFile(env, configRoot, templatePath, context) {
1085
+ function renderTemplateFile(env, configRoot, templatePath, context, trace) {
1041
1086
  const resolvedPath = resolveConfigPath(configRoot, templatePath, context);
1042
1087
  if (!fs.existsSync(resolvedPath)) {
1043
1088
  throw new Error(`missing template: ${resolvedPath}`);
1044
1089
  }
1045
1090
  const relativePath = path.relative(configRoot, resolvedPath).replace(/\\/g, '/');
1046
1091
  let content = fs.readFileSync(resolvedPath, 'utf8');
1092
+ traceTemplateSource(configRoot, resolvedPath, content, context, trace);
1047
1093
  if (path.basename(resolvedPath) === 'AGENTS-MODS.md') {
1048
- content = renderLegacyAgentsMods(resolvedPath);
1094
+ content = renderLegacyAgentsMods(resolvedPath, [], trace);
1049
1095
  return renderInlineTemplate(env, content, context);
1050
1096
  }
1051
1097
  return env.render(relativePath, context);
1052
1098
  }
1099
+ function traceTemplateSource(configRoot, sourcePath, content, context, trace, stack = []) {
1100
+ if (trace === undefined) {
1101
+ return;
1102
+ }
1103
+ const resolvedSource = path.resolve(sourcePath);
1104
+ trace.sourceFiles.add(resolvedSource);
1105
+ if (stack.includes(resolvedSource)) {
1106
+ return;
1107
+ }
1108
+ const nextStack = [...stack, resolvedSource];
1109
+ const includeRe = /{%\s*(?:include|extends|import)\s+["']([^"']+)["']|{%\s*from\s+["']([^"']+)["']/g;
1110
+ for (;;) {
1111
+ const match = includeRe.exec(content);
1112
+ if (match === null) {
1113
+ break;
1114
+ }
1115
+ const includePath = match[1] ?? match[2];
1116
+ if (!includePath) {
1117
+ continue;
1118
+ }
1119
+ const includedPath = resolveConfigPath(configRoot, includePath, context);
1120
+ if (!fs.existsSync(includedPath)) {
1121
+ continue;
1122
+ }
1123
+ const includedContent = fs.readFileSync(includedPath, 'utf8');
1124
+ traceTemplateSource(configRoot, includedPath, includedContent, context, trace, nextStack);
1125
+ }
1126
+ }
1053
1127
  function renderInlineTemplate(env, source, context) {
1054
1128
  return env.renderString(source, context);
1055
1129
  }
@@ -1090,11 +1164,11 @@ function copySkeletonTree(sourceDir, targetDir) {
1090
1164
  fs.copyFileSync(sourcePath, targetPath);
1091
1165
  }
1092
1166
  }
1093
- function renderProfile(projectRoot, agentDir, checkOnly = false) {
1167
+ function renderProfile(projectRoot, agentDir, checkOnly = false, targetTool = null, trace) {
1094
1168
  const configRoot = defaultConfigRoot(projectRoot);
1095
1169
  const profile = resolveProfile(projectRoot);
1096
1170
  const env = createNunjucksEnv(configRoot);
1097
- const manifest = normalizeManifest(loadManifest(configRoot, agentDir, profile), profile);
1171
+ const manifest = normalizeManifest(loadManifest(configRoot, agentDir, profile, trace), profile);
1098
1172
  if (manifest.profile !== profile) {
1099
1173
  const parsed = parseProfile(manifest.profile, `${path.join(agentDir, MANIFEST_FILE_NAME)} profile`);
1100
1174
  if (parsed.profile === null) {
@@ -1105,7 +1179,7 @@ function renderProfile(projectRoot, agentDir, checkOnly = false) {
1105
1179
  ensureConfigRootGitignore(configRoot);
1106
1180
  }
1107
1181
  const context = buildRenderContext(projectRoot, agentDir, configRoot, manifest, env);
1108
- const sections = [renderTemplateFile(env, configRoot, manifest.agent.base, context)];
1182
+ const sections = [renderTemplateFile(env, configRoot, manifest.agent.base, context, trace)];
1109
1183
  for (const include of manifest.agent.includes) {
1110
1184
  const includePath = resolveConfigPath(configRoot, include, context);
1111
1185
  if (!fs.existsSync(includePath)) {
@@ -1114,26 +1188,31 @@ function renderProfile(projectRoot, agentDir, checkOnly = false) {
1114
1188
  }
1115
1189
  throw new Error(`missing template: ${includePath}`);
1116
1190
  }
1117
- sections.push(renderTemplateFile(env, configRoot, include, context));
1191
+ sections.push(renderTemplateFile(env, configRoot, include, context, trace));
1118
1192
  }
1119
1193
  context.renderedAgentSections = sections.map((section, index) => {
1120
1194
  const label = index === 0 ? manifest.agent.base : manifest.agent.includes[index - 1] ?? `section ${index}`;
1121
1195
  assertNoUnexpandedTemplateVars(label, section);
1122
1196
  return section.trimEnd();
1123
1197
  });
1124
- context.skills = renderSkills(env, configRoot, manifest, context);
1198
+ context.skills = renderSkills(env, configRoot, manifest, context, trace);
1125
1199
  const files = [];
1126
- const agentsContent = renderToolInstructions('AGENTS.md', env, configRoot, context, false);
1127
- const claudeContent = renderToolInstructions('CLAUDE.md', env, configRoot, context, true);
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
- });
1136
- files.push(...renderNativeSkillFiles(context));
1200
+ if (targetTool === null || targetTool === 'codex') {
1201
+ const agentsContent = renderToolInstructions('AGENTS.md', env, configRoot, context, false, trace);
1202
+ files.push({ path: path.join(context.paths.liveDir, 'AGENTS.md'), content: agentsContent });
1203
+ files.push({ path: path.join(context.paths.liveDir, 'config.toml'), content: renderCodexConfig(env, configRoot, context, trace) });
1204
+ files.push(...renderNativeSkillFiles(context, 'codex'));
1205
+ }
1206
+ if (targetTool === null || targetTool === 'claude') {
1207
+ const claudeContent = renderToolInstructions('CLAUDE.md', env, configRoot, context, true, trace);
1208
+ files.push({ path: path.join(context.paths.liveDir, 'CLAUDE.md'), content: claudeContent });
1209
+ files.push({ path: path.join(context.paths.liveDir, '.claude', 'CLAUDE.md'), content: claudeContent });
1210
+ files.push({
1211
+ path: path.join(context.paths.liveDir, '.claude', 'agent-run-settings.json'),
1212
+ content: renderClaudeSettings(env, configRoot, context, trace)
1213
+ });
1214
+ files.push(...renderNativeSkillFiles(context, 'claude'));
1215
+ }
1137
1216
  files.push(...renderGuardShims(context));
1138
1217
  return {
1139
1218
  agentDir,
@@ -1225,7 +1304,7 @@ function checkRenderedProfile(projectRoot, agentDir) {
1225
1304
  }
1226
1305
  return findings;
1227
1306
  }
1228
- function renderSkills(env, configRoot, manifest, context) {
1307
+ function renderSkills(env, configRoot, manifest, context, trace) {
1229
1308
  const skills = [];
1230
1309
  for (const name of manifest.skills.install) {
1231
1310
  const sourceTemplate = manifest.skills.overrides[name] ?? `global/skills/${name}/SKILL.md.njk`;
@@ -1233,7 +1312,7 @@ function renderSkills(env, configRoot, manifest, context) {
1233
1312
  if (!fs.existsSync(sourcePath)) {
1234
1313
  throw new Error(`missing skill template for ${name}: ${sourcePath}`);
1235
1314
  }
1236
- const renderedContent = renderTemplateFile(env, configRoot, sourceTemplate, context);
1315
+ const renderedContent = renderTemplateFile(env, configRoot, sourceTemplate, context, trace);
1237
1316
  assertNoUnexpandedTemplateVars(`skill ${name}`, renderedContent);
1238
1317
  validateRenderedSkill(renderedContent, sourcePath);
1239
1318
  const description = extractSkillDescription(renderedContent);
@@ -1241,41 +1320,45 @@ function renderSkills(env, configRoot, manifest, context) {
1241
1320
  }
1242
1321
  return skills;
1243
1322
  }
1244
- function renderNativeSkillFiles(context) {
1323
+ function renderNativeSkillFiles(context, targetTool = null) {
1245
1324
  const files = [];
1246
1325
  for (const skill of context.skills) {
1247
- files.push({
1248
- path: path.join(context.paths.codexSkillsDir, skill.name, 'SKILL.md'),
1249
- content: skill.renderedContent
1250
- });
1251
- files.push({
1252
- path: path.join(context.paths.claudeSkillsDir, skill.name, 'SKILL.md'),
1253
- content: skill.renderedContent
1254
- });
1326
+ if (targetTool === null || targetTool === 'codex') {
1327
+ files.push({
1328
+ path: path.join(context.paths.codexSkillsDir, skill.name, 'SKILL.md'),
1329
+ content: skill.renderedContent
1330
+ });
1331
+ }
1332
+ if (targetTool === null || targetTool === 'claude') {
1333
+ files.push({
1334
+ path: path.join(context.paths.claudeSkillsDir, skill.name, 'SKILL.md'),
1335
+ content: skill.renderedContent
1336
+ });
1337
+ }
1255
1338
  }
1256
1339
  return files;
1257
1340
  }
1258
- function renderToolInstructions(templateName, env, configRoot, context, isClaude) {
1341
+ function renderToolInstructions(templateName, env, configRoot, context, isClaude, trace) {
1259
1342
  const templatePath = `global/tool-templates/${templateName}.njk`;
1260
1343
  const absoluteTemplate = path.join(configRoot, templatePath);
1261
1344
  const content = fs.existsSync(absoluteTemplate)
1262
- ? renderTemplateFile(env, configRoot, templatePath, context)
1345
+ ? renderTemplateFile(env, configRoot, templatePath, context, trace)
1263
1346
  : renderInlineTemplate(env, defaultToolInstructionsTemplate(isClaude), context);
1264
1347
  assertNoUnexpandedTemplateVars(templateName, content);
1265
1348
  return content.replace(/\n*$/, '\n');
1266
1349
  }
1267
- function renderCodexConfig(env, configRoot, context) {
1350
+ function renderCodexConfig(env, configRoot, context, trace) {
1268
1351
  const templatePath = resolveProfileOverrideTemplate(configRoot, context, 'codex-config.toml.njk', 'global/tool-templates/codex-config.toml.njk');
1269
1352
  const content = templatePath !== null
1270
- ? renderTemplateFile(env, configRoot, templatePath, context)
1353
+ ? renderTemplateFile(env, configRoot, templatePath, context, trace)
1271
1354
  : defaultCodexConfigContent(context);
1272
1355
  assertNoUnexpandedTemplateVars('config.toml', content);
1273
1356
  return content.replace(/\n*$/, '\n');
1274
1357
  }
1275
- function renderClaudeSettings(env, configRoot, context) {
1358
+ function renderClaudeSettings(env, configRoot, context, trace) {
1276
1359
  const templatePath = resolveProfileOverrideTemplate(configRoot, context, 'claude-settings.json.njk', 'global/tool-templates/claude-settings.json.njk');
1277
1360
  const content = templatePath !== null
1278
- ? renderTemplateFile(env, configRoot, templatePath, context)
1361
+ ? renderTemplateFile(env, configRoot, templatePath, context, trace)
1279
1362
  : defaultClaudeSettingsContent(context);
1280
1363
  assertNoUnexpandedTemplateVars('claude settings.json', content);
1281
1364
  return content.replace(/\n*$/, '\n');
@@ -1347,8 +1430,9 @@ function extractSkillDescription(content) {
1347
1430
  }
1348
1431
  return '';
1349
1432
  }
1350
- function renderLegacyAgentsMods(sourceFile, stack = []) {
1433
+ function renderLegacyAgentsMods(sourceFile, stack = [], trace) {
1351
1434
  const resolvedSource = path.resolve(sourceFile);
1435
+ trace?.sourceFiles.add(resolvedSource);
1352
1436
  if (stack.includes(resolvedSource)) {
1353
1437
  throw new Error(`Include cycle detected: ${[...stack, resolvedSource].join(' -> ')}`);
1354
1438
  }
@@ -1368,7 +1452,9 @@ function renderLegacyAgentsMods(sourceFile, stack = []) {
1368
1452
  if (!includePath) {
1369
1453
  continue;
1370
1454
  }
1371
- output.push(renderLegacyAgentsMods(resolveIncludePath(resolvedSource, includePath), nextStack));
1455
+ const resolvedInclude = resolveIncludePath(resolvedSource, includePath);
1456
+ trace?.sourceFiles.add(resolvedInclude);
1457
+ output.push(renderLegacyAgentsMods(resolvedInclude, nextStack, trace));
1372
1458
  if (!contentStarted) {
1373
1459
  sawLeadingInclude = true;
1374
1460
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@technomoron/agent-run",
3
- "version": "0.99.13",
3
+ "version": "0.99.14",
4
4
  "packageManager": "pnpm@10.28.1",
5
5
  "bin": {
6
6
  "agent-run": "dist/agent-run.js"