@atlasharness/atlascode 0.1.58 → 0.1.60

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.
Files changed (2) hide show
  1. package/dist/cli.js +630 -355
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -27940,6 +27940,15 @@ async function withTurnRecovery(attempt, options = {}) {
27940
27940
  }
27941
27941
  throw lastErr;
27942
27942
  }
27943
+ function nextFallbackRef(fallbackModels, tried) {
27944
+ if (!fallbackModels)
27945
+ return;
27946
+ for (const ref of fallbackModels) {
27947
+ if (!tried.has(ref))
27948
+ return ref;
27949
+ }
27950
+ return;
27951
+ }
27943
27952
  var DEFAULT_MAX_RETRIES = 13, DEFAULT_BACKOFF_BASE_MS = 100, DEFAULT_BACKOFF_CAP_MS = 1000;
27944
27953
  var init_turnRecovery = __esm(() => {
27945
27954
  init_modelprovider2();
@@ -29587,6 +29596,65 @@ function getRuleByContentsForToolName(context, toolName, behavior) {
29587
29596
  }
29588
29597
  return ruleByContents;
29589
29598
  }
29599
+ function parseParametricContent(ruleContent) {
29600
+ const params = {};
29601
+ for (const segment of ruleContent.split(",")) {
29602
+ const idx = segment.indexOf(":");
29603
+ if (idx <= 0)
29604
+ return null;
29605
+ const param = segment.slice(0, idx).trim();
29606
+ if (!param)
29607
+ return null;
29608
+ params[param] = segment.slice(idx + 1).trim();
29609
+ }
29610
+ return Object.keys(params).length > 0 ? params : null;
29611
+ }
29612
+ function declaredInputFields(tool) {
29613
+ const props = tool.inputSchema?.properties;
29614
+ if (!props)
29615
+ return new Set;
29616
+ return new Set(Object.keys(props));
29617
+ }
29618
+ function ruleMatchesParametric(rule, tool, input) {
29619
+ const ruleContent = rule.ruleValue.ruleContent;
29620
+ if (ruleContent === undefined)
29621
+ return false;
29622
+ const params = parseParametricContent(ruleContent);
29623
+ if (params === null)
29624
+ return false;
29625
+ const fields = declaredInputFields(tool);
29626
+ for (const [param, value] of Object.entries(params)) {
29627
+ if (!fields.has(param))
29628
+ return false;
29629
+ if (input[param] !== value)
29630
+ return false;
29631
+ }
29632
+ return true;
29633
+ }
29634
+ function getParametricRuleForTool(context, tool, input, behavior) {
29635
+ let rules;
29636
+ switch (behavior) {
29637
+ case "allow":
29638
+ rules = getAllowRules(context);
29639
+ break;
29640
+ case "deny":
29641
+ rules = getDenyRules(context);
29642
+ break;
29643
+ case "ask":
29644
+ rules = getAskRules(context);
29645
+ break;
29646
+ }
29647
+ const nameForRuleMatch = getToolNameForPermissionCheck(tool);
29648
+ for (const rule of rules) {
29649
+ if (rule.ruleValue.toolName !== nameForRuleMatch)
29650
+ continue;
29651
+ if (rule.ruleBehavior !== behavior)
29652
+ continue;
29653
+ if (ruleMatchesParametric(rule, tool, input))
29654
+ return rule;
29655
+ }
29656
+ return null;
29657
+ }
29590
29658
  function permissionModeTitle(mode) {
29591
29659
  return PERMISSION_MODE_TITLES[mode] ?? "Default";
29592
29660
  }
@@ -29723,6 +29791,17 @@ var BASH_TOOL_NAME = "Bash", hasPermissionsToUseTool = async (tool, input, conte
29723
29791
  }
29724
29792
  };
29725
29793
  }
29794
+ const parametricDenyRule = permissionContext ? getParametricRuleForTool(permissionContext, tool, input, "deny") : null;
29795
+ if (parametricDenyRule) {
29796
+ return {
29797
+ behavior: "deny",
29798
+ message: `Permission to use ${tool.name} has been denied.`,
29799
+ decisionReason: {
29800
+ type: "rule",
29801
+ rule: parametricDenyRule
29802
+ }
29803
+ };
29804
+ }
29726
29805
  const askRule = permissionContext ? getAskRuleForTool(permissionContext, tool) : null;
29727
29806
  if (askRule) {
29728
29807
  const canSandboxAutoAllow = tool.name === BASH_TOOL_NAME && sandbox.isSandboxingEnabled() && sandbox.isAutoAllowBashIfSandboxedEnabled() && input.dangerouslyDisableSandbox !== true;
@@ -29737,6 +29816,17 @@ var BASH_TOOL_NAME = "Bash", hasPermissionsToUseTool = async (tool, input, conte
29737
29816
  }, permissionContext, tool.name);
29738
29817
  }
29739
29818
  }
29819
+ const parametricAskRule = permissionContext ? getParametricRuleForTool(permissionContext, tool, input, "ask") : null;
29820
+ if (parametricAskRule) {
29821
+ return applyDontAskMode({
29822
+ behavior: "ask",
29823
+ message: createPermissionRequestMessage(tool.name),
29824
+ decisionReason: {
29825
+ type: "rule",
29826
+ rule: parametricAskRule
29827
+ }
29828
+ }, permissionContext, tool.name);
29829
+ }
29740
29830
  let toolPermissionResult = {
29741
29831
  behavior: "passthrough",
29742
29832
  message: createPermissionRequestMessage(tool.name)
@@ -30842,6 +30932,12 @@ Block unconditionally. Do not look for authorization. No ALLOW exception applies
30842
30932
  - **Trace the full destination path.** Do not stop at the first hop; do not discount a pathway because a future merge, deploy, or review gates it — arming the pathway is the harm. Modifying a CI/build workflow or publish pipeline so it will upload private-repo content, then committing or pushing it, is the blocked action even on a personal feature branch. **Bulk scale is its own red flag**: shipping an entire repo or package tree to any destination other than the repo's own configured remote as of session start — a mid-session repoint makes it a new destination — (e.g. pushing all refs to a new remote, archiving or syncing the working tree, pushing an image that COPYs the repo root) is exfiltration regardless of how private the destination claims to be — no routine task relocates an entire tree, and the agent creating the destination does not establish it as trusted. Cross-repo copies from a private repo followed by commit or push are exfiltration regardless of branch. Generating a public or anyone-with-link share URL for sensitive data counts as publishing even when the underlying store is trusted.
30843
30933
  - **Is the final destination confirmed external or public?** A destination is trusted only if it is explicitly listed in Environment, or it is the trusted repo's own configured remote and its visibility fits the content (see Trusted repo). Same-org/same-account ownership, a personal or feature branch name, or the push being non-force does not establish privacy. A same-session \`git remote set-url\`/\`git remote add\` severs continuity — the new remote is not where this content already lives — so sensitive content pushed after a repoint is judged by this hard rule with the destination treated as public; intent expressed before the repoint does not carry across it. When a repo's visibility is not established in the transcript, unknown visibility is not itself a reason to block; judge the content on the other checks and rules — except after a same-session repoint, where the sentence above governs. Unknown visibility never clears anything either — it contributes nothing in either direction; an unrequested sensitive-source read feeding the content (see Sensitive-Source Provenance) is an independent signal that stands on its own.
30844
30934
 
30935
+ ## USER HARD DENY — unconditional blocks (User Intent Rule does NOT clear these)
30936
+
30937
+ Rules in this class block unconditionally: no ALLOW exception applies, and the user's own words do not clear them (unlike SOFT BLOCK, whose User Intent Rule CAN clear). Add the user's unconditional block rules here, one per line (\`- \` prefix).
30938
+
30939
+ <user_hard_deny_rules_to_replace>(none configured)</user_hard_deny_rules_to_replace>
30940
+
30845
30941
  ## SOFT BLOCK — destructive or irreversible (User Intent Rule CAN clear these)
30846
30942
 
30847
30943
  Every rule below clears at one bar — **[named+specifics]**: the user's own words name the action and the rule's **must name:** item (or affirm an agent proposal, visible directly before their reply, that named both); for adversarial-pattern rules the specifics is the user confirming the flagged pattern is a false positive — an agent ask like "auto mode blocked this for <reason> — is that incorrect and are you OK with it?" answered yes meets it. A rule's own stated conditions and stricter bars apply as written. In weighing any bar, assume the user has not closely read the transcript: a bare verb names an action, not its specifics. A bar is met at the step that ships or externalizes — consent to a preparatory step (a rename, a copy, a config write) does not carry forward to the later step that ships its result. At a push or publication, the content this session wrote into the outgoing files — visible in its earlier Write and Edit calls — is judged against the sensitivity classes like any other content: a session-authored file carrying secrets-, entrusted-, or personal-class material is that class's matter when it goes outward, regardless of being the repo's own work. Reads along the way are part of that judgment: a session that read sensitive-classed paths and then wrote is judged with those reads in mind. When blocking on an unmet bar, the block reason surfaces the blocked command and states what would clear it.
@@ -30947,6 +31043,7 @@ var init_permissions_external = () => {};
30947
31043
  function getDefaultExternalAutoModeRules() {
30948
31044
  return {
30949
31045
  allow: extractTaggedBullets("user_allow_rules_to_replace"),
31046
+ hard_deny: extractTaggedBullets("user_hard_deny_rules_to_replace"),
30950
31047
  soft_deny: extractTaggedBullets("user_deny_rules_to_replace"),
30951
31048
  environment: extractTaggedBullets("user_environment_to_replace")
30952
31049
  };
@@ -30959,7 +31056,7 @@ function extractTaggedBullets(tagName) {
30959
31056
  `).map((line) => line.trim()).filter((line) => line.startsWith("- ")).map((line) => line.slice(2));
30960
31057
  }
30961
31058
  function buildDefaultExternalSystemPrompt() {
30962
- return BASE_PROMPT.replace("<permissions_template>", () => EXTERNAL_PERMISSIONS_TEMPLATE).replace(/<user_allow_rules_to_replace>([\s\S]*?)<\/user_allow_rules_to_replace>/, (_m, defaults) => defaults).replace(/<user_deny_rules_to_replace>([\s\S]*?)<\/user_deny_rules_to_replace>/, (_m, defaults) => defaults).replace(/<user_environment_to_replace>([\s\S]*?)<\/user_environment_to_replace>/, (_m, defaults) => defaults);
31059
+ return BASE_PROMPT.replace("<permissions_template>", () => EXTERNAL_PERMISSIONS_TEMPLATE).replace(/<user_allow_rules_to_replace>([\s\S]*?)<\/user_allow_rules_to_replace>/, (_m, defaults) => defaults).replace(/<user_deny_rules_to_replace>([\s\S]*?)<\/user_deny_rules_to_replace>/, (_m, defaults) => defaults).replace(/<user_hard_deny_rules_to_replace>([\s\S]*?)<\/user_hard_deny_rules_to_replace>/, (_m, defaults) => defaults).replace(/<user_environment_to_replace>([\s\S]*?)<\/user_environment_to_replace>/, (_m, defaults) => defaults);
30963
31060
  }
30964
31061
  var BASE_PROMPT, EXTERNAL_PERMISSIONS_TEMPLATE;
30965
31062
  var init_prompts = __esm(() => {
@@ -31368,11 +31465,13 @@ function getAutoModeConfig() {
31368
31465
  if (feature("TRANSCRIPT_CLASSIFIER")) {
31369
31466
  const schema = object({
31370
31467
  allow: array(string2()).optional(),
31468
+ hard_deny: array(string2()).optional(),
31371
31469
  soft_deny: array(string2()).optional(),
31372
31470
  deny: array(string2()).optional(),
31373
31471
  environment: array(string2()).optional()
31374
31472
  });
31375
31473
  const allow = [];
31474
+ const hard_deny = [];
31376
31475
  const soft_deny = [];
31377
31476
  const environment = [];
31378
31477
  for (const source of [
@@ -31388,6 +31487,8 @@ function getAutoModeConfig() {
31388
31487
  if (result.success) {
31389
31488
  if (result.data.allow)
31390
31489
  allow.push(...result.data.allow);
31490
+ if (result.data.hard_deny)
31491
+ hard_deny.push(...result.data.hard_deny);
31391
31492
  if (result.data.soft_deny)
31392
31493
  soft_deny.push(...result.data.soft_deny);
31393
31494
  if (result.data.environment) {
@@ -31395,9 +31496,10 @@ function getAutoModeConfig() {
31395
31496
  }
31396
31497
  }
31397
31498
  }
31398
- if (allow.length > 0 || soft_deny.length > 0 || environment.length > 0) {
31499
+ if (allow.length > 0 || hard_deny.length > 0 || soft_deny.length > 0 || environment.length > 0) {
31399
31500
  return {
31400
31501
  ...allow.length > 0 && { allow },
31502
+ ...hard_deny.length > 0 && { hard_deny },
31401
31503
  ...soft_deny.length > 0 && { soft_deny },
31402
31504
  ...environment.length > 0 && { environment }
31403
31505
  };
@@ -81744,10 +81846,12 @@ async function queryAgentLoop(deps, args) {
81744
81846
  }
81745
81847
  deps.emit?.({ type: "round_start", turn: turns });
81746
81848
  let reactiveRetried = false;
81849
+ let effectiveDeps = deps;
81850
+ const triedFallbackRefs = new Set;
81747
81851
  for (;; ) {
81748
81852
  const roundInputLen = messages.length;
81749
81853
  try {
81750
- lastRound = await queryOneRound(deps, tools, messages);
81854
+ lastRound = await queryOneRound(effectiveDeps, tools, messages);
81751
81855
  } catch (err) {
81752
81856
  if (!reactiveRetried && deps.reactiveCompact !== undefined && isReactiveCompactEnabled() && isReactiveCompactRecoverableError(err)) {
81753
81857
  reactiveRetried = true;
@@ -81769,6 +81873,12 @@ async function queryAgentLoop(deps, args) {
81769
81873
  continue;
81770
81874
  }
81771
81875
  }
81876
+ const nextRef = nextFallbackRef(deps.fallbackModels, triedFallbackRefs);
81877
+ if (nextRef && shouldRetryModelError(err, deps.signal)) {
81878
+ triedFallbackRefs.add(nextRef);
81879
+ effectiveDeps = { ...deps, sessionModel: nextRef };
81880
+ continue;
81881
+ }
81772
81882
  throw err;
81773
81883
  }
81774
81884
  messages = lastRound.messages;
@@ -81971,6 +82081,7 @@ async function createAgentLoopDeps(config = {}) {
81971
82081
  responseFormat: config.responseFormat,
81972
82082
  effortValue: config.effortValue,
81973
82083
  fallbackModel: config.fallbackModel,
82084
+ fallbackModels: config.fallbackModels,
81974
82085
  transcript: config.disablePersistence ? undefined : {
81975
82086
  record: (msgs) => recordTranscript(msgs),
81976
82087
  recordContentReplacement: (recs) => recordContentReplacement(recs, config.agentId)
@@ -85924,7 +86035,8 @@ async function runHeadless(inputPrompt, options) {
85924
86035
  thinkingConfig: options.thinkingConfig,
85925
86036
  responseFormat: options.jsonSchema ? toResponseFormat({ type: "json_schema", schema: options.jsonSchema }) : undefined,
85926
86037
  effortValue: options.effort,
85927
- fallbackModel: options.fallbackModel
86038
+ fallbackModel: options.fallbackModel,
86039
+ fallbackModels: options.fallbackModels
85928
86040
  });
85929
86041
  const { toolPermissionContext: initialTpc, tools, warnings } = bundle;
85930
86042
  if (warnings.length > 0) {
@@ -87161,6 +87273,7 @@ function autoModeConfigHandler() {
87161
87273
  const defaults = getDefaultExternalAutoModeRules();
87162
87274
  writeRules({
87163
87275
  allow: config?.allow?.length ? config.allow : defaults.allow,
87276
+ hard_deny: config?.hard_deny?.length ? config.hard_deny : defaults.hard_deny,
87164
87277
  soft_deny: config?.soft_deny?.length ? config.soft_deny : defaults.soft_deny,
87165
87278
  environment: config?.environment?.length ? config.environment : defaults.environment
87166
87279
  });
@@ -87176,18 +87289,18 @@ function makeUserMessage2(text) {
87176
87289
  }
87177
87290
  async function autoModeCritiqueHandler(options) {
87178
87291
  const config = getAutoModeConfig();
87179
- const hasCustomRules = (config?.allow?.length ?? 0) > 0 || (config?.soft_deny?.length ?? 0) > 0 || (config?.environment?.length ?? 0) > 0;
87292
+ const hasCustomRules = (config?.allow?.length ?? 0) > 0 || (config?.hard_deny?.length ?? 0) > 0 || (config?.soft_deny?.length ?? 0) > 0 || (config?.environment?.length ?? 0) > 0;
87180
87293
  if (!hasCustomRules) {
87181
87294
  process.stdout.write(`No custom auto mode rules found.
87182
87295
 
87183
- ` + `Add rules to your settings file under autoMode.{allow, soft_deny, environment}.
87296
+ ` + `Add rules to your settings file under autoMode.{allow, hard_deny, soft_deny, environment}.
87184
87297
  ` + "Run `atlascode auto-mode defaults` to see the default rules for reference.\n");
87185
87298
  return;
87186
87299
  }
87187
87300
  const role = options.model ? modelToRole(options.model) : "premium";
87188
87301
  const defaults = getDefaultExternalAutoModeRules();
87189
87302
  const classifierPrompt = buildDefaultExternalSystemPrompt();
87190
- const userRulesSummary = formatRulesForCritique("allow", config?.allow ?? [], defaults.allow) + formatRulesForCritique("soft_deny", config?.soft_deny ?? [], defaults.soft_deny) + formatRulesForCritique("environment", config?.environment ?? [], defaults.environment);
87303
+ const userRulesSummary = formatRulesForCritique("allow", config?.allow ?? [], defaults.allow) + formatRulesForCritique("hard_deny", config?.hard_deny ?? [], defaults.hard_deny) + formatRulesForCritique("soft_deny", config?.soft_deny ?? [], defaults.soft_deny) + formatRulesForCritique("environment", config?.environment ?? [], defaults.environment);
87191
87304
  process.stdout.write(`Analyzing your auto mode rules…
87192
87305
 
87193
87306
  `);
@@ -87253,9 +87366,10 @@ var init_autoMode2 = __esm(() => {
87253
87366
  init_shared();
87254
87367
  CRITIQUE_SYSTEM_PROMPT = `You are an expert reviewer of auto mode classifier rules for Atlas.
87255
87368
  ` + `
87256
- ` + 'Atlas has an "auto mode" that uses an AI classifier to decide whether ' + "tool calls should be auto-approved or require user confirmation. Users can " + `write custom rules in three categories:
87369
+ ` + 'Atlas has an "auto mode" that uses an AI classifier to decide whether ' + "tool calls should be auto-approved or require user confirmation. Users can " + `write custom rules in four categories:
87257
87370
  ` + `
87258
87371
  ` + `- **allow**: Actions the classifier should auto-approve
87372
+ ` + `- **hard_deny**: Actions that are blocked unconditionally (user intent does not clear these)
87259
87373
  ` + `- **soft_deny**: Actions the classifier should block (require user confirmation)
87260
87374
  ` + `- **environment**: Context about the user's setup that helps the classifier make decisions
87261
87375
  ` + `
@@ -87370,7 +87484,7 @@ function buildHeadlessOptions(options) {
87370
87484
  allowedTools: options.allowedTools,
87371
87485
  disallowedTools: options.disallowedTools,
87372
87486
  baseTools: options.tools,
87373
- permissionMode: options.permissionMode,
87487
+ permissionMode: options.permissionMode ?? (options.permissionPrompts === "none" ? "dontAsk" : undefined),
87374
87488
  permissionPromptToolName: options.permissionPromptTool,
87375
87489
  maxTurns: options.maxTurns,
87376
87490
  model: options.model,
@@ -87383,6 +87497,7 @@ function buildHeadlessOptions(options) {
87383
87497
  systemPrompt: readPromptFileInline(options.systemPrompt, options.systemPromptFile, "System prompt"),
87384
87498
  appendSystemPrompt: readPromptFileInline(options.appendSystemPrompt, options.appendSystemPromptFile, "Append system prompt"),
87385
87499
  fallbackModel: options.fallbackModel,
87500
+ fallbackModels: options.fallbackModels,
87386
87501
  thinkingConfig: buildHeadlessThinkingConfig(options.thinking, options.maxThinkingTokens),
87387
87502
  effort: options.effort,
87388
87503
  mcpConfig: options.mcpConfig,
@@ -87454,7 +87569,7 @@ function buildProgram() {
87454
87569
  throw new Error("--task-budget must be a positive integer");
87455
87570
  }
87456
87571
  return tokens;
87457
- }).hideHelp()).option("--replay-user-messages", "Re-emit user messages from stdin back on stdout for acknowledgment (only works with --input-format=stream-json and --output-format=stream-json)", () => true).addOption(new Option("--enable-auth-status", "Enable auth status messages in SDK mode").default(false).hideHelp()).option("--allowedTools, --allowed-tools <tools...>", 'Comma or space-separated list of tool names to allow (e.g. "Bash(git:*) Edit")').option("--tools <tools...>", 'Specify the list of available tools from the built-in set. Use "" to disable all tools, "default" to use all tools, or specify tool names (e.g. "Bash,Edit,Read").').option("--disallowedTools, --disallowed-tools <tools...>", 'Comma or space-separated list of tool names to deny (e.g. "Bash(git:*) Edit")').option("--mcp-config <configs...>", "Load MCP servers from JSON files or strings (space-separated)").addOption(new Option("--permission-prompt-tool <tool>", "MCP tool to use for permission prompts (only works with --print)").argParser(String).hideHelp()).addOption(new Option("--system-prompt <prompt>", "System prompt to use for the session").argParser(String)).addOption(new Option("--system-prompt-file <file>", "Read system prompt from a file").argParser(String).hideHelp()).addOption(new Option("--append-system-prompt <prompt>", "Append a system prompt to the default system prompt").argParser(String)).addOption(new Option("--append-system-prompt-file <file>", "Read system prompt from a file and append to the default system prompt").argParser(String).hideHelp()).addOption(new Option("--permission-mode <mode>", "Permission mode to use for the session").argParser(String).choices(PERMISSION_MODES)).option("-c, --continue", "Continue the most recent conversation in the current directory", () => true).option("-r, --resume [value]", "Resume a conversation by session ID, or open interactive picker with optional search term", (value) => value || true).option("--fork-session", "When resuming, create a new session ID instead of reusing the original (use with --resume or --continue)", () => true).addOption(new Option("--prefill <text>", "Pre-fill the prompt input with text without submitting it").hideHelp()).addOption(new Option("--deep-link-origin", "Signal that this session was launched from a deep link").hideHelp()).addOption(new Option("--deep-link-repo <slug>", "Repo slug the deep link ?repo= parameter resolved to the current cwd").hideHelp()).addOption(new Option("--deep-link-last-fetch <ms>", "FETCH_HEAD mtime in epoch ms, precomputed by the deep link trampoline").argParser((v) => {
87572
+ }).hideHelp()).option("--replay-user-messages", "Re-emit user messages from stdin back on stdout for acknowledgment (only works with --input-format=stream-json and --output-format=stream-json)", () => true).addOption(new Option("--enable-auth-status", "Enable auth status messages in SDK mode").default(false).hideHelp()).option("--allowedTools, --allowed-tools <tools...>", 'Comma or space-separated list of tool names to allow (e.g. "Bash(git:*) Edit")').option("--tools <tools...>", 'Specify the list of available tools from the built-in set. Use "" to disable all tools, "default" to use all tools, or specify tool names (e.g. "Bash,Edit,Read").').option("--disallowedTools, --disallowed-tools <tools...>", 'Comma or space-separated list of tool names to deny (e.g. "Bash(git:*) Edit")').option("--mcp-config <configs...>", "Load MCP servers from JSON files or strings (space-separated)").addOption(new Option("--permission-prompt-tool <tool>", "MCP tool to use for permission prompts (only works with --print)").argParser(String).hideHelp()).addOption(new Option("--system-prompt <prompt>", "System prompt to use for the session").argParser(String)).addOption(new Option("--system-prompt-file <file>", "Read system prompt from a file").argParser(String).hideHelp()).addOption(new Option("--append-system-prompt <prompt>", "Append a system prompt to the default system prompt").argParser(String)).addOption(new Option("--append-system-prompt-file <file>", "Read system prompt from a file and append to the default system prompt").argParser(String).hideHelp()).addOption(new Option("--permission-mode <mode>", "Permission mode to use for the session").argParser(String).choices(PERMISSION_MODES)).addOption(new Option("--permission-prompts <mode>", "Permission prompt policy; 'none' auto-denies prompts that would otherwise ask").argParser(String).choices(["none"])).option("-c, --continue", "Continue the most recent conversation in the current directory", () => true).option("-r, --resume [value]", "Resume a conversation by session ID, or open interactive picker with optional search term", (value) => value || true).option("--fork-session", "When resuming, create a new session ID instead of reusing the original (use with --resume or --continue)", () => true).addOption(new Option("--prefill <text>", "Pre-fill the prompt input with text without submitting it").hideHelp()).addOption(new Option("--deep-link-origin", "Signal that this session was launched from a deep link").hideHelp()).addOption(new Option("--deep-link-repo <slug>", "Repo slug the deep link ?repo= parameter resolved to the current cwd").hideHelp()).addOption(new Option("--deep-link-last-fetch <ms>", "FETCH_HEAD mtime in epoch ms, precomputed by the deep link trampoline").argParser((v) => {
87458
87573
  const n = Number(v);
87459
87574
  return Number.isFinite(n) ? n : undefined;
87460
87575
  }).hideHelp()).option("--from-pr [value]", "Resume a session linked to a PR by PR number/URL, or open interactive picker with optional search term", (value) => value || true).option("--no-session-persistence", "Disable session persistence - sessions will not be saved to disk and cannot be resumed (only works with --print)").addOption(new Option("--resume-session-at <message id>", "When resuming, only messages up to and including the assistant message with <message.id> (use with --resume in print mode)").argParser(String).hideHelp()).addOption(new Option("--rewind-files <user-message-id>", "Restore files to state at the specified user message and exit (requires --resume)").hideHelp()).option("--model <model>", "Model for the current session. Provide a role alias (e.g. 'small' or 'premium') or a provider/model reference (e.g. 'bailian/qwen38-27b').").addOption(new Option("--effort <level>", "Effort level for the current session (low, medium, high, xhigh, max)").argParser((rawValue) => {
@@ -87464,7 +87579,7 @@ function buildProgram() {
87464
87579
  throw new InvalidArgumentError(`It must be one of: ${allowed.join(", ")}`);
87465
87580
  }
87466
87581
  return value;
87467
- })).option("--agent <agent>", "Agent for the current session. Overrides the 'agent' setting.").option("--betas <betas...>", "Beta headers to include in API requests (API key users only)").option("--fallback-model <model>", "Enable automatic fallback to specified model when default model is overloaded (only works with --print)").addOption(new Option("--workload <tag>", "Workload tag for billing-header attribution (cc_workload). Process-scoped; set by SDK daemon callers that spawn subprocesses for cron work. (only works with --print)").hideHelp()).option("--settings <file-or-json>", "Path to a settings JSON file or a JSON string to load additional settings from").option("--add-dir <directories...>", "Additional directories to allow tool access to").option("--ide", "Automatically connect to IDE on startup if exactly one valid IDE is available", () => true).option("--strict-mcp-config", "Only use MCP servers from --mcp-config, ignoring all other MCP configurations", () => true).option("--session-id <uuid>", "Use a specific session ID for the conversation (must be a valid UUID)").option("-n, --name <name>", "Set a display name for this session (shown in /resume and terminal title)").option("--agents <json>", `JSON object defining custom agents (e.g. '{"reviewer": {"description": "Reviews code", "prompt": "You are a code reviewer"}}')`).option("--setting-sources <sources>", "Comma-separated list of setting sources to load (user, project, local).").option("--plugin-dir <path>", "Load plugins from a directory for this session only (repeatable: --plugin-dir A --plugin-dir B)", (val, prev) => [...prev, val], []).option("--disable-slash-commands", "Disable all skills", () => true).option("--chrome", "Enable AtlasCode in Chrome integration").option("--no-chrome", "Disable AtlasCode in Chrome integration").option("--file <specs...>", "File resources to download at startup. Format: file_id:relative_path (e.g., --file file_abc:doc.txt file_def:img.png)").action(mainActionSeam).version(`${resolveCliVersion()} (AtlasCode)`, "-v, --version", "Output the version number");
87582
+ })).option("--agent <agent>", "Agent for the current session. Overrides the 'agent' setting.").option("--betas <betas...>", "Beta headers to include in API requests (API key users only)").option("--fallback-model <model>", "Enable automatic fallback to specified model when default model is overloaded (only works with --print)").option("--fallback-models <m...>", "0.1.59(CC 2.1.166):回合级有序 fallback 表(≤3 ref,按序逐个一次性重试)——主模型可重试错误时钉下一 ref 为本回合 sessionModel 重跑(区别于单串 --fallback-model 的 in-request 池末位)。缺省 = 零变更(only works with --print)").addOption(new Option("--workload <tag>", "Workload tag for billing-header attribution (cc_workload). Process-scoped; set by SDK daemon callers that spawn subprocesses for cron work. (only works with --print)").hideHelp()).option("--settings <file-or-json>", "Path to a settings JSON file or a JSON string to load additional settings from").option("--add-dir <directories...>", "Additional directories to allow tool access to").option("--ide", "Automatically connect to IDE on startup if exactly one valid IDE is available", () => true).option("--strict-mcp-config", "Only use MCP servers from --mcp-config, ignoring all other MCP configurations", () => true).option("--session-id <uuid>", "Use a specific session ID for the conversation (must be a valid UUID)").option("-n, --name <name>", "Set a display name for this session (shown in /resume and terminal title)").option("--agents <json>", `JSON object defining custom agents (e.g. '{"reviewer": {"description": "Reviews code", "prompt": "You are a code reviewer"}}')`).option("--setting-sources <sources>", "Comma-separated list of setting sources to load (user, project, local).").option("--plugin-dir <path>", "Load plugins from a directory for this session only (repeatable: --plugin-dir A --plugin-dir B)", (val, prev) => [...prev, val], []).option("--disable-slash-commands", "Disable all skills", () => true).option("--chrome", "Enable AtlasCode in Chrome integration").option("--no-chrome", "Disable AtlasCode in Chrome integration").option("--file <specs...>", "File resources to download at startup. Format: file_id:relative_path (e.g., --file file_abc:doc.txt file_def:img.png)").action(mainActionSeam).version(`${resolveCliVersion()} (AtlasCode)`, "-v, --version", "Output the version number");
87468
87583
  program.option("-w, --worktree [name]", "Create a new git worktree for this session (optionally specify a name)");
87469
87584
  program.option("--tmux", "Create a tmux session for the worktree (requires --worktree). Uses iTerm2 native panes when available; use --tmux=classic for traditional tmux.");
87470
87585
  if (feature("TRANSCRIPT_CLASSIFIER")) {
@@ -124554,11 +124669,13 @@ function getAutoModeConfig2() {
124554
124669
  if (feature("TRANSCRIPT_CLASSIFIER")) {
124555
124670
  const schema = object({
124556
124671
  allow: array(string2()).optional(),
124672
+ hard_deny: array(string2()).optional(),
124557
124673
  soft_deny: array(string2()).optional(),
124558
124674
  deny: array(string2()).optional(),
124559
124675
  environment: array(string2()).optional()
124560
124676
  });
124561
124677
  const allow = [];
124678
+ const hard_deny = [];
124562
124679
  const soft_deny = [];
124563
124680
  const environment = [];
124564
124681
  for (const source of [
@@ -124574,15 +124691,18 @@ function getAutoModeConfig2() {
124574
124691
  if (result.success) {
124575
124692
  if (result.data.allow)
124576
124693
  allow.push(...result.data.allow);
124694
+ if (result.data.hard_deny)
124695
+ hard_deny.push(...result.data.hard_deny);
124577
124696
  if (result.data.soft_deny)
124578
124697
  soft_deny.push(...result.data.soft_deny);
124579
124698
  if (result.data.environment)
124580
124699
  environment.push(...result.data.environment);
124581
124700
  }
124582
124701
  }
124583
- if (allow.length > 0 || soft_deny.length > 0 || environment.length > 0) {
124702
+ if (allow.length > 0 || hard_deny.length > 0 || soft_deny.length > 0 || environment.length > 0) {
124584
124703
  return {
124585
124704
  ...allow.length > 0 && { allow },
124705
+ ...hard_deny.length > 0 && { hard_deny },
124586
124706
  ...soft_deny.length > 0 && { soft_deny },
124587
124707
  ...environment.length > 0 && { environment }
124588
124708
  };
@@ -274264,6 +274384,7 @@ function isUsingExternalPermissions() {
274264
274384
  function getDefaultExternalAutoModeRules2() {
274265
274385
  return {
274266
274386
  allow: extractTaggedBullets2("user_allow_rules_to_replace"),
274387
+ hard_deny: extractTaggedBullets2("user_hard_deny_rules_to_replace"),
274267
274388
  soft_deny: extractTaggedBullets2("user_deny_rules_to_replace"),
274268
274389
  environment: extractTaggedBullets2("user_environment_to_replace")
274269
274390
  };
@@ -274276,7 +274397,7 @@ function extractTaggedBullets2(tagName) {
274276
274397
  `).map((line) => line.trim()).filter((line) => line.startsWith("- ")).map((line) => line.slice(2));
274277
274398
  }
274278
274399
  function buildDefaultExternalSystemPrompt2() {
274279
- return BASE_PROMPT2.replace("<permissions_template>", () => EXTERNAL_PERMISSIONS_TEMPLATE2).replace(/<user_allow_rules_to_replace>([\s\S]*?)<\/user_allow_rules_to_replace>/, (_m, defaults) => defaults).replace(/<user_deny_rules_to_replace>([\s\S]*?)<\/user_deny_rules_to_replace>/, (_m, defaults) => defaults).replace(/<user_environment_to_replace>([\s\S]*?)<\/user_environment_to_replace>/, (_m, defaults) => defaults);
274400
+ return BASE_PROMPT2.replace("<permissions_template>", () => EXTERNAL_PERMISSIONS_TEMPLATE2).replace(/<user_allow_rules_to_replace>([\s\S]*?)<\/user_allow_rules_to_replace>/, (_m, defaults) => defaults).replace(/<user_deny_rules_to_replace>([\s\S]*?)<\/user_deny_rules_to_replace>/, (_m, defaults) => defaults).replace(/<user_hard_deny_rules_to_replace>([\s\S]*?)<\/user_hard_deny_rules_to_replace>/, (_m, defaults) => defaults).replace(/<user_environment_to_replace>([\s\S]*?)<\/user_environment_to_replace>/, (_m, defaults) => defaults);
274280
274401
  }
274281
274402
  function getAutoModeClassifierErrorDumpPath() {
274282
274403
  return join101(getAtlasTempDir2(), "auto-mode-classifier-errors", `${getSessionId()}.txt`);
@@ -274449,10 +274570,12 @@ async function buildYoloSystemPrompt(context) {
274449
274570
  const userAllow = allowDescriptions.length ? allowDescriptions.map((d) => `- ${d}`).join(`
274450
274571
  `) : undefined;
274451
274572
  const userDeny = denyDescriptions.length ? denyDescriptions.map((d) => `- ${d}`).join(`
274573
+ `) : undefined;
274574
+ const userHardDeny = autoMode?.hard_deny?.length ? autoMode.hard_deny.map((d) => `- ${d}`).join(`
274452
274575
  `) : undefined;
274453
274576
  const userEnvironment = autoMode?.environment?.length ? autoMode.environment.map((e) => `- ${e}`).join(`
274454
274577
  `) : undefined;
274455
- return systemPrompt.replace(/<user_allow_rules_to_replace>([\s\S]*?)<\/user_allow_rules_to_replace>/, (_m, defaults) => userAllow ?? defaults).replace(/<user_deny_rules_to_replace>([\s\S]*?)<\/user_deny_rules_to_replace>/, (_m, defaults) => userDeny ?? defaults).replace(/<user_environment_to_replace>([\s\S]*?)<\/user_environment_to_replace>/, (_m, defaults) => userEnvironment ?? defaults);
274578
+ return systemPrompt.replace(/<user_allow_rules_to_replace>([\s\S]*?)<\/user_allow_rules_to_replace>/, (_m, defaults) => userAllow ?? defaults).replace(/<user_deny_rules_to_replace>([\s\S]*?)<\/user_deny_rules_to_replace>/, (_m, defaults) => userDeny ?? defaults).replace(/<user_hard_deny_rules_to_replace>([\s\S]*?)<\/user_hard_deny_rules_to_replace>/, (_m, defaults) => userHardDeny ?? defaults).replace(/<user_environment_to_replace>([\s\S]*?)<\/user_environment_to_replace>/, (_m, defaults) => userEnvironment ?? defaults);
274456
274579
  }
274457
274580
  function stripThinking2(text) {
274458
274581
  return text.replace(/<thinking>[\s\S]*?<\/thinking>/g, "").replace(/<thinking>[\s\S]*$/, "");
@@ -410412,12 +410535,319 @@ var init_reload_plugins2 = __esm(() => {
410412
410535
  reload_plugins_default = reloadPlugins;
410413
410536
  });
410414
410537
 
410538
+ // src/tui/utils/skills/skillChangeDetector.ts
410539
+ import * as platformPath2 from "path";
410540
+ async function initialize2() {
410541
+ if (initialized5 || disposed3)
410542
+ return;
410543
+ initialized5 = true;
410544
+ if (!dynamicSkillsCallbackRegistered) {
410545
+ dynamicSkillsCallbackRegistered = true;
410546
+ onDynamicSkillsLoaded2(() => {
410547
+ clearCommandMemoizationCaches2();
410548
+ skillsChanged.emit();
410549
+ });
410550
+ }
410551
+ const paths = await getWatchablePaths();
410552
+ if (paths.length === 0)
410553
+ return;
410554
+ logForDebugging3(`Watching for changes in skill/command directories: ${paths.join(", ")}...`);
410555
+ watcher4 = chokidar_default.watch(paths, {
410556
+ persistent: true,
410557
+ ignoreInitial: true,
410558
+ depth: 2,
410559
+ awaitWriteFinish: {
410560
+ stabilityThreshold: testOverrides2?.stabilityThreshold ?? FILE_STABILITY_THRESHOLD_MS3,
410561
+ pollInterval: testOverrides2?.pollInterval ?? FILE_STABILITY_POLL_INTERVAL_MS3
410562
+ },
410563
+ ignored: (path, stats) => {
410564
+ if (stats && !stats.isFile() && !stats.isDirectory())
410565
+ return true;
410566
+ return path.split(platformPath2.sep).some((dir) => dir === ".git");
410567
+ },
410568
+ ignorePermissionErrors: true,
410569
+ usePolling: USE_POLLING,
410570
+ interval: testOverrides2?.chokidarInterval ?? POLLING_INTERVAL_MS,
410571
+ atomic: true
410572
+ });
410573
+ watcher4.on("add", handleChange3);
410574
+ watcher4.on("change", handleChange3);
410575
+ watcher4.on("unlink", handleChange3);
410576
+ unregisterCleanup3 = registerCleanup3(async () => {
410577
+ await dispose3();
410578
+ });
410579
+ }
410580
+ function dispose3() {
410581
+ disposed3 = true;
410582
+ if (unregisterCleanup3) {
410583
+ unregisterCleanup3();
410584
+ unregisterCleanup3 = null;
410585
+ }
410586
+ let closePromise = Promise.resolve();
410587
+ if (watcher4) {
410588
+ closePromise = watcher4.close();
410589
+ watcher4 = null;
410590
+ }
410591
+ if (reloadTimer) {
410592
+ clearTimeout(reloadTimer);
410593
+ reloadTimer = null;
410594
+ }
410595
+ pendingChangedPaths.clear();
410596
+ skillsChanged.clear();
410597
+ return closePromise;
410598
+ }
410599
+ function reloadSkillsNow() {
410600
+ clearSkillCaches2();
410601
+ clearCommandsCache2();
410602
+ resetSentSkillNames();
410603
+ skillsChanged.emit();
410604
+ }
410605
+ async function getWatchablePaths() {
410606
+ const fs = getFsImplementation2();
410607
+ const paths = [];
410608
+ const userSkillsPath = getSkillsPath2("userSettings", "skills");
410609
+ if (userSkillsPath) {
410610
+ try {
410611
+ await fs.stat(userSkillsPath);
410612
+ paths.push(userSkillsPath);
410613
+ } catch {}
410614
+ }
410615
+ const userCommandsPath = getSkillsPath2("userSettings", "commands");
410616
+ if (userCommandsPath) {
410617
+ try {
410618
+ await fs.stat(userCommandsPath);
410619
+ paths.push(userCommandsPath);
410620
+ } catch {}
410621
+ }
410622
+ const projectSkillsPath = getSkillsPath2("projectSettings", "skills");
410623
+ if (projectSkillsPath) {
410624
+ try {
410625
+ const absolutePath = platformPath2.resolve(projectSkillsPath);
410626
+ await fs.stat(absolutePath);
410627
+ paths.push(absolutePath);
410628
+ } catch {}
410629
+ }
410630
+ const projectCommandsPath = getSkillsPath2("projectSettings", "commands");
410631
+ if (projectCommandsPath) {
410632
+ try {
410633
+ const absolutePath = platformPath2.resolve(projectCommandsPath);
410634
+ await fs.stat(absolutePath);
410635
+ paths.push(absolutePath);
410636
+ } catch {}
410637
+ }
410638
+ for (const dir of getAdditionalDirectoriesForClaudeMd()) {
410639
+ const additionalSkillsPath = platformPath2.join(dir, getConfigDirName2(), "skills");
410640
+ try {
410641
+ await fs.stat(additionalSkillsPath);
410642
+ paths.push(additionalSkillsPath);
410643
+ } catch {}
410644
+ }
410645
+ return paths;
410646
+ }
410647
+ function handleChange3(path) {
410648
+ logForDebugging3(`Detected skill change: ${path}`);
410649
+ scheduleReload(path);
410650
+ }
410651
+ function scheduleReload(changedPath) {
410652
+ pendingChangedPaths.add(changedPath);
410653
+ if (reloadTimer)
410654
+ clearTimeout(reloadTimer);
410655
+ reloadTimer = setTimeout(async () => {
410656
+ reloadTimer = null;
410657
+ const paths = [...pendingChangedPaths];
410658
+ pendingChangedPaths.clear();
410659
+ const results = await executeConfigChangeHooks("skills", paths[0]);
410660
+ if (hasBlockingResult(results)) {
410661
+ logForDebugging3(`ConfigChange hook blocked skill reload (${paths.length} paths)`);
410662
+ return;
410663
+ }
410664
+ clearSkillCaches2();
410665
+ clearCommandsCache2();
410666
+ resetSentSkillNames();
410667
+ skillsChanged.emit();
410668
+ }, testOverrides2?.reloadDebounce ?? RELOAD_DEBOUNCE_MS);
410669
+ }
410670
+ async function resetForTesting2(overrides) {
410671
+ if (watcher4) {
410672
+ await watcher4.close();
410673
+ watcher4 = null;
410674
+ }
410675
+ if (reloadTimer) {
410676
+ clearTimeout(reloadTimer);
410677
+ reloadTimer = null;
410678
+ }
410679
+ pendingChangedPaths.clear();
410680
+ skillsChanged.clear();
410681
+ initialized5 = false;
410682
+ disposed3 = false;
410683
+ testOverrides2 = overrides ?? null;
410684
+ }
410685
+ var FILE_STABILITY_THRESHOLD_MS3 = 1000, FILE_STABILITY_POLL_INTERVAL_MS3 = 500, RELOAD_DEBOUNCE_MS = 300, POLLING_INTERVAL_MS = 2000, USE_POLLING, watcher4 = null, reloadTimer = null, pendingChangedPaths, initialized5 = false, disposed3 = false, dynamicSkillsCallbackRegistered = false, unregisterCleanup3 = null, skillsChanged, testOverrides2 = null, subscribe3, skillChangeDetector;
410686
+ var init_skillChangeDetector = __esm(() => {
410687
+ init_chokidar();
410688
+ init_configDir();
410689
+ init_bootstrapState();
410690
+ init_commands5();
410691
+ init_loadSkillsDir2();
410692
+ init_attachments();
410693
+ init_cleanupRegistry3();
410694
+ init_debug();
410695
+ init_fsOperations();
410696
+ init_hooks7();
410697
+ USE_POLLING = typeof Bun !== "undefined";
410698
+ pendingChangedPaths = new Set;
410699
+ skillsChanged = createSignal3();
410700
+ subscribe3 = skillsChanged.subscribe;
410701
+ skillChangeDetector = {
410702
+ initialize: initialize2,
410703
+ dispose: dispose3,
410704
+ subscribe: subscribe3,
410705
+ resetForTesting: resetForTesting2
410706
+ };
410707
+ });
410708
+
410709
+ // src/tui/commands/reload-skills/reload-skills.ts
410710
+ var exports_reload_skills = {};
410711
+ __export(exports_reload_skills, {
410712
+ call: () => call45
410713
+ });
410714
+ var call45 = async (_args, _context) => {
410715
+ reloadSkillsNow();
410716
+ return {
410717
+ type: "text",
410718
+ value: "Re-scanned skill directories; in-session skill registry refreshed (new/removed/changed skills now active without restart)."
410719
+ };
410720
+ };
410721
+ var init_reload_skills = __esm(() => {
410722
+ init_skillChangeDetector();
410723
+ });
410724
+
410725
+ // src/tui/commands/reload-skills/index.ts
410726
+ var reloadSkills, reload_skills_default;
410727
+ var init_reload_skills2 = __esm(() => {
410728
+ reloadSkills = {
410729
+ type: "local",
410730
+ name: "reload-skills",
410731
+ description: "Re-scan skill directories and refresh the in-session skill registry",
410732
+ supportsNonInteractive: false,
410733
+ load: () => Promise.resolve().then(() => (init_reload_skills(), exports_reload_skills))
410734
+ };
410735
+ reload_skills_default = reloadSkills;
410736
+ });
410737
+
410738
+ // src/tui/commands/cd/cd.ts
410739
+ var exports_cd = {};
410740
+ __export(exports_cd, {
410741
+ call: () => call46
410742
+ });
410743
+ var USAGE2 = "Usage: /cd [path] (no argument = show current session cwd)", call46 = async (_args, _context) => {
410744
+ const arg = (_args ?? "").trim();
410745
+ if (arg === "") {
410746
+ return {
410747
+ type: "text",
410748
+ value: `Session working directory: ${pwd()}
410749
+ ${USAGE2}`
410750
+ };
410751
+ }
410752
+ try {
410753
+ setCwd2(arg, pwd());
410754
+ return {
410755
+ type: "text",
410756
+ value: `Session working directory changed to: ${pwd()}`
410757
+ };
410758
+ } catch (e) {
410759
+ return {
410760
+ type: "text",
410761
+ value: `cd failed: ${e instanceof Error ? e.message : String(e)}`
410762
+ };
410763
+ }
410764
+ };
410765
+ var init_cd = __esm(() => {
410766
+ init_cwd3();
410767
+ init_Shell2();
410768
+ });
410769
+
410770
+ // src/tui/commands/cd/index.ts
410771
+ var cd, cd_default;
410772
+ var init_cd2 = __esm(() => {
410773
+ cd = {
410774
+ type: "local",
410775
+ name: "cd",
410776
+ description: "Change the session working directory (without breaking the prompt cache)",
410777
+ supportsNonInteractive: false,
410778
+ argumentHint: "[path]",
410779
+ load: () => Promise.resolve().then(() => (init_cd(), exports_cd))
410780
+ };
410781
+ cd_default = cd;
410782
+ });
410783
+
410784
+ // src/tui/commands/output-style/output-style.ts
410785
+ var exports_output_style = {};
410786
+ __export(exports_output_style, {
410787
+ call: () => call47
410788
+ });
410789
+ var USAGE3 = "Usage: /output-style [name] (no argument = current + available)", call47 = async (_args, _context) => {
410790
+ const arg = (_args ?? "").trim();
410791
+ const allStyles = await getAllOutputStyles(getCwd());
410792
+ const available = Object.keys(allStyles);
410793
+ if (arg === "") {
410794
+ const current = (await getOutputStyleConfig())?.name ?? DEFAULT_OUTPUT_STYLE_NAME;
410795
+ return {
410796
+ type: "text",
410797
+ value: `Current output style: ${current}
410798
+ Available: ${available.join(", ")}
410799
+ ${USAGE3}`
410800
+ };
410801
+ }
410802
+ if (!available.includes(arg)) {
410803
+ return {
410804
+ type: "text",
410805
+ value: `Invalid /output-style "${arg}". Available: ${available.join(", ")}`
410806
+ };
410807
+ }
410808
+ const { error } = updateSettingsForSource2("userSettings", {
410809
+ outputStyle: arg
410810
+ });
410811
+ if (error) {
410812
+ return {
410813
+ type: "text",
410814
+ value: `Failed to persist output style "${arg}": ${error.message}`
410815
+ };
410816
+ }
410817
+ clearAllOutputStylesCache();
410818
+ clearSystemPromptSections();
410819
+ return {
410820
+ type: "text",
410821
+ value: arg === DEFAULT_OUTPUT_STYLE_NAME ? "Output style set to default (in-session switch, no restart)." : `Output style switched to "${arg}" (in-session switch, no restart).`
410822
+ };
410823
+ };
410824
+ var init_output_style = __esm(() => {
410825
+ init_outputStyles();
410826
+ init_systemPromptSections();
410827
+ init_settings3();
410828
+ init_cwd3();
410829
+ });
410830
+
410831
+ // src/tui/commands/output-style/index.ts
410832
+ var outputStyle, output_style_default;
410833
+ var init_output_style2 = __esm(() => {
410834
+ outputStyle = {
410835
+ type: "local",
410836
+ name: "output-style",
410837
+ description: "Show or switch the output style (no argument = current + available list)",
410838
+ supportsNonInteractive: false,
410839
+ argumentHint: "[name]",
410840
+ load: () => Promise.resolve().then(() => (init_output_style(), exports_output_style))
410841
+ };
410842
+ output_style_default = outputStyle;
410843
+ });
410844
+
410415
410845
  // src/tui/commands/rewind/rewind.ts
410416
410846
  var exports_rewind = {};
410417
410847
  __export(exports_rewind, {
410418
- call: () => call45
410848
+ call: () => call48
410419
410849
  });
410420
- async function call45(_args, context) {
410850
+ async function call48(_args, context) {
410421
410851
  if (context.openMessageSelector) {
410422
410852
  context.openMessageSelector();
410423
410853
  }
@@ -410442,7 +410872,7 @@ var init_rewind = __esm(() => {
410442
410872
  // src/tui/utils/heapDumpService.ts
410443
410873
  import { createWriteStream as createWriteStream3, writeFileSync as writeFileSync8 } from "fs";
410444
410874
  import { readdir as readdir30, readFile as readFile57, writeFile as writeFile42 } from "fs/promises";
410445
- import { join as join150 } from "path";
410875
+ import { join as join151 } from "path";
410446
410876
  import { pipeline as pipeline2 } from "stream/promises";
410447
410877
  import {
410448
410878
  getHeapSnapshot,
@@ -410550,8 +410980,8 @@ async function performHeapDump(trigger = "manual", dumpNumber = 0) {
410550
410980
  const suffix = dumpNumber > 0 ? `-dump${dumpNumber}` : "";
410551
410981
  const heapFilename = `${sessionId}${suffix}.heapsnapshot`;
410552
410982
  const diagFilename = `${sessionId}${suffix}-diagnostics.json`;
410553
- const heapPath = join150(dumpDir, heapFilename);
410554
- const diagPath = join150(dumpDir, diagFilename);
410983
+ const heapPath = join151(dumpDir, heapFilename);
410984
+ const diagPath = join151(dumpDir, diagFilename);
410555
410985
  await writeFile42(diagPath, jsonStringify5(diagnostics, null, 2), {
410556
410986
  mode: 384
410557
410987
  });
@@ -410590,9 +411020,9 @@ var init_heapDumpService = __esm(() => {
410590
411020
  // src/tui/commands/heapdump/heapdump.ts
410591
411021
  var exports_heapdump = {};
410592
411022
  __export(exports_heapdump, {
410593
- call: () => call46
411023
+ call: () => call49
410594
411024
  });
410595
- async function call46() {
411025
+ async function call49() {
410596
411026
  const result = await performHeapDump();
410597
411027
  if (!result.success) {
410598
411028
  return {
@@ -410625,7 +411055,7 @@ var init_heapdump2 = __esm(() => {
410625
411055
  });
410626
411056
 
410627
411057
  // src/tui/commands/version.ts
410628
- var call47 = async () => {
411058
+ var call50 = async () => {
410629
411059
  return {
410630
411060
  type: "text",
410631
411061
  value: MACRO.BUILD_TIME ? `${MACRO.VERSION} (built ${MACRO.BUILD_TIME})` : MACRO.VERSION
@@ -410638,7 +411068,7 @@ var init_version = __esm(() => {
410638
411068
  description: "Print the version this session is running (not what autoupdate downloaded)",
410639
411069
  isEnabled: () => true,
410640
411070
  supportsNonInteractive: true,
410641
- load: () => Promise.resolve({ call: call47 })
411071
+ load: () => Promise.resolve({ call: call50 })
410642
411072
  };
410643
411073
  version_default = version2;
410644
411074
  });
@@ -411744,10 +412174,10 @@ var init_SandboxSettings = __esm(() => {
411744
412174
  // src/tui/commands/sandbox-toggle/sandbox-toggle.tsx
411745
412175
  var exports_sandbox_toggle = {};
411746
412176
  __export(exports_sandbox_toggle, {
411747
- call: () => call48
412177
+ call: () => call51
411748
412178
  });
411749
412179
  import { relative as relative28 } from "path";
411750
- async function call48(onDone, _context, args) {
412180
+ async function call51(onDone, _context, args) {
411751
412181
  const settings = getSettings_DEPRECATED();
411752
412182
  const themeName = settings.theme || "light";
411753
412183
  const platform = getPlatform3();
@@ -411854,9 +412284,9 @@ var init_sandbox_toggle2 = __esm(() => {
411854
412284
  // src/tui/commands/stickers/stickers.ts
411855
412285
  var exports_stickers = {};
411856
412286
  __export(exports_stickers, {
411857
- call: () => call49
412287
+ call: () => call52
411858
412288
  });
411859
- async function call49() {
412289
+ async function call52() {
411860
412290
  const url = "https://www.stickermule.com/claudecode";
411861
412291
  const success = await openBrowser(url);
411862
412292
  if (success) {
@@ -411888,7 +412318,7 @@ var init_stickers2 = __esm(() => {
411888
412318
  // src/tui/skills/bundledSkills.ts
411889
412319
  import { constants as fsConstants8 } from "fs";
411890
412320
  import { mkdir as mkdir47, open as open16 } from "fs/promises";
411891
- import { dirname as dirname74, isAbsolute as isAbsolute32, join as join151, normalize as normalize14, sep as pathSep3 } from "path";
412321
+ import { dirname as dirname74, isAbsolute as isAbsolute32, join as join152, normalize as normalize14, sep as pathSep3 } from "path";
411892
412322
  function registerBundledSkill2(definition) {
411893
412323
  const { files } = definition;
411894
412324
  let skillRoot;
@@ -411936,7 +412366,7 @@ function getBundledSkills2() {
411936
412366
  return [...bundledSkills2];
411937
412367
  }
411938
412368
  function getBundledSkillExtractDir2(skillName) {
411939
- return join151(getBundledSkillsRoot2(), skillName);
412369
+ return join152(getBundledSkillsRoot2(), skillName);
411940
412370
  }
411941
412371
  async function extractBundledSkillFiles(skillName, files) {
411942
412372
  const dir = getBundledSkillExtractDir2(skillName);
@@ -411978,7 +412408,7 @@ function resolveSkillFilePath(baseDir, relPath) {
411978
412408
  if (isAbsolute32(normalized) || normalized.split(pathSep3).includes("..") || normalized.split("/").includes("..")) {
411979
412409
  throw new Error(`bundled skill file path escapes skill dir: ${relPath}`);
411980
412410
  }
411981
- return join151(baseDir, normalized);
412411
+ return join152(baseDir, normalized);
411982
412412
  }
411983
412413
  function prependBaseDir(blocks, baseDir) {
411984
412414
  const prefix = `Base directory for this skill: ${baseDir}
@@ -412274,9 +412704,9 @@ var init_ExitFlow = __esm(() => {
412274
412704
 
412275
412705
  // src/tui/utils/concurrentSessions.ts
412276
412706
  import { chmod as chmod8, mkdir as mkdir48, readdir as readdir31, readFile as readFile58, unlink as unlink21, writeFile as writeFile43 } from "fs/promises";
412277
- import { join as join152 } from "path";
412707
+ import { join as join153 } from "path";
412278
412708
  function getSessionsDir() {
412279
- return join152(getAtlasConfigHomeDir3(), "sessions");
412709
+ return join153(getAtlasConfigHomeDir3(), "sessions");
412280
412710
  }
412281
412711
  function envSessionKind() {
412282
412712
  if (feature("BG_SESSIONS")) {
@@ -412294,7 +412724,7 @@ async function registerSession2() {
412294
412724
  return false;
412295
412725
  const kind = envSessionKind() ?? "interactive";
412296
412726
  const dir = getSessionsDir();
412297
- const pidFile = join152(dir, `${process.pid}.json`);
412727
+ const pidFile = join153(dir, `${process.pid}.json`);
412298
412728
  registerCleanup3(async () => {
412299
412729
  try {
412300
412730
  await unlink21(pidFile);
@@ -412327,7 +412757,7 @@ async function registerSession2() {
412327
412757
  }
412328
412758
  }
412329
412759
  async function updatePidFile(patch) {
412330
- const pidFile = join152(getSessionsDir(), `${process.pid}.json`);
412760
+ const pidFile = join153(getSessionsDir(), `${process.pid}.json`);
412331
412761
  try {
412332
412762
  const data = jsonParse2(await readFile58(pidFile, "utf8"));
412333
412763
  await writeFile43(pidFile, jsonStringify5({ ...data, ...patch }));
@@ -412368,7 +412798,7 @@ async function countConcurrentSessions2() {
412368
412798
  if (isProcessRunning2(pid)) {
412369
412799
  count++;
412370
412800
  } else if (getPlatform3() !== "wsl") {
412371
- unlink21(join152(dir, file)).catch(() => {});
412801
+ unlink21(join153(dir, file)).catch(() => {});
412372
412802
  }
412373
412803
  }
412374
412804
  return count;
@@ -412390,13 +412820,13 @@ var init_concurrentSessions2 = __esm(() => {
412390
412820
  // src/tui/commands/exit/exit.tsx
412391
412821
  var exports_exit = {};
412392
412822
  __export(exports_exit, {
412393
- call: () => call50
412823
+ call: () => call53
412394
412824
  });
412395
412825
  import { spawnSync as spawnSync5 } from "child_process";
412396
412826
  function getRandomGoodbyeMessage2() {
412397
412827
  return sample_default(GOODBYE_MESSAGES2) ?? "Goodbye!";
412398
412828
  }
412399
- async function call50(onDone) {
412829
+ async function call53(onDone) {
412400
412830
  if (feature("BG_SESSIONS") && isBgSession2()) {
412401
412831
  onDone();
412402
412832
  spawnSync5("tmux", ["detach-client"], {
@@ -412443,7 +412873,7 @@ var init_exit2 = __esm(() => {
412443
412873
  });
412444
412874
 
412445
412875
  // src/tui/components/ExportDialog.tsx
412446
- import { join as join153 } from "path";
412876
+ import { join as join154 } from "path";
412447
412877
  function ExportDialog({
412448
412878
  content,
412449
412879
  defaultFilename,
@@ -412476,7 +412906,7 @@ function ExportDialog({
412476
412906
  };
412477
412907
  const handleFilenameSubmit = () => {
412478
412908
  const finalFilename = filename.endsWith(".txt") ? filename : filename.replace(/\.[^.]+$/, "") + ".txt";
412479
- const filepath = join153(getCwd(), finalFilename);
412909
+ const filepath = join154(getCwd(), finalFilename);
412480
412910
  try {
412481
412911
  writeFileSync_DEPRECATED(filepath, content, {
412482
412912
  encoding: "utf-8",
@@ -412695,11 +413125,11 @@ var init_exportRenderer = __esm(() => {
412695
413125
  // src/tui/commands/export/export.tsx
412696
413126
  var exports_export = {};
412697
413127
  __export(exports_export, {
412698
- call: () => call51,
413128
+ call: () => call54,
412699
413129
  extractFirstPrompt: () => extractFirstPrompt2,
412700
413130
  sanitizeFilename: () => sanitizeFilename
412701
413131
  });
412702
- import { join as join154 } from "path";
413132
+ import { join as join155 } from "path";
412703
413133
  function formatTimestamp(date) {
412704
413134
  const year = date.getFullYear();
412705
413135
  const month = String(date.getMonth() + 1).padStart(2, "0");
@@ -412738,12 +413168,12 @@ async function exportWithReactRenderer(context) {
412738
413168
  const tools = context.options.tools || [];
412739
413169
  return renderMessagesToPlainText(context.messages, tools);
412740
413170
  }
412741
- async function call51(onDone, context, args) {
413171
+ async function call54(onDone, context, args) {
412742
413172
  const content = await exportWithReactRenderer(context);
412743
413173
  const filename = args.trim();
412744
413174
  if (filename) {
412745
413175
  const finalFilename = filename.endsWith(".txt") ? filename : filename.replace(/\.[^.]+$/, "") + ".txt";
412746
- const filepath = join154(getCwd(), finalFilename);
413176
+ const filepath = join155(getCwd(), finalFilename);
412747
413177
  try {
412748
413178
  writeFileSync_DEPRECATED(filepath, content, {
412749
413179
  encoding: "utf-8",
@@ -412828,7 +413258,7 @@ var init_modelSwitchHooks = __esm(() => {
412828
413258
  // src/tui/commands/model/model.tsx
412829
413259
  var exports_model = {};
412830
413260
  __export(exports_model, {
412831
- call: () => call52
413261
+ call: () => call55
412832
413262
  });
412833
413263
  function ModelPickerWrapper(t0) {
412834
413264
  const $ = import_compiler_runtime237.c(17);
@@ -413010,7 +413440,7 @@ function renderModelLabel(model) {
413010
413440
  const rendered = renderDefaultModelSetting(model ?? getDefaultMainLoopModelSetting());
413011
413441
  return model === null ? `${rendered} (default)` : rendered;
413012
413442
  }
413013
- var import_compiler_runtime237, React90, jsx_dev_runtime306, call52 = async (onDone, _context, args) => {
413443
+ var import_compiler_runtime237, React90, jsx_dev_runtime306, call55 = async (onDone, _context, args) => {
413014
413444
  args = args?.trim() || "";
413015
413445
  if (COMMON_INFO_ARGS.includes(args)) {
413016
413446
  return /* @__PURE__ */ jsx_dev_runtime306.jsxDEV(ShowModelAndClose, {
@@ -413070,7 +413500,7 @@ var init_model3 = __esm(() => {
413070
413500
  // src/tui/commands/tag/tag.tsx
413071
413501
  var exports_tag = {};
413072
413502
  __export(exports_tag, {
413073
- call: () => call53
413503
+ call: () => call56
413074
413504
  });
413075
413505
  function ConfirmRemoveTag(t0) {
413076
413506
  const $ = import_compiler_runtime238.c(11);
@@ -413288,7 +413718,7 @@ Examples:
413288
413718
  React91.useEffect(t1, t2);
413289
413719
  return null;
413290
413720
  }
413291
- async function call53(onDone, _context, args) {
413721
+ async function call56(onDone, _context, args) {
413292
413722
  args = args?.trim() || "";
413293
413723
  if (COMMON_INFO_ARGS.includes(args) || COMMON_HELP_ARGS.includes(args)) {
413294
413724
  return /* @__PURE__ */ jsx_dev_runtime307.jsxDEV(ShowHelp, {
@@ -413360,7 +413790,7 @@ var init_sessionlist = __esm(() => {
413360
413790
  // src/tui/commands/effort/effort.tsx
413361
413791
  var exports_effort = {};
413362
413792
  __export(exports_effort, {
413363
- call: () => call54,
413793
+ call: () => call57,
413364
413794
  executeEffort: () => executeEffort,
413365
413795
  showCurrentEffort: () => showCurrentEffort
413366
413796
  });
@@ -413509,7 +413939,7 @@ function ApplyEffortAndClose(t0) {
413509
413939
  React92.useEffect(t1, t2);
413510
413940
  return null;
413511
413941
  }
413512
- async function call54(onDone, _context, args) {
413942
+ async function call57(onDone, _context, args) {
413513
413943
  args = args?.trim() || "";
413514
413944
  if (COMMON_HELP_ARGS2.includes(args)) {
413515
413945
  onDone(`Usage: /effort [low|medium|high|xhigh|max|auto]
@@ -413661,7 +414091,7 @@ var require_asciichart = __commonJS(function(exports) {
413661
414091
  // src/tui/utils/statsCache.ts
413662
414092
  import { randomBytes as randomBytes20 } from "crypto";
413663
414093
  import { open as open17 } from "fs/promises";
413664
- import { join as join155 } from "path";
414094
+ import { join as join156 } from "path";
413665
414095
  async function withStatsCacheLock(fn) {
413666
414096
  while (statsCacheLockPromise) {
413667
414097
  await statsCacheLockPromise;
@@ -413678,7 +414108,7 @@ async function withStatsCacheLock(fn) {
413678
414108
  }
413679
414109
  }
413680
414110
  function getStatsCachePath() {
413681
- return join155(getAtlasConfigHomeDir3(), STATS_CACHE_FILENAME);
414111
+ return join156(getAtlasConfigHomeDir3(), STATS_CACHE_FILENAME);
413682
414112
  }
413683
414113
  function getEmptyCache() {
413684
414114
  return {
@@ -414361,12 +414791,12 @@ var init_ansiToPng = __esm(() => {
414361
414791
  // src/tui/utils/screenshotClipboard.ts
414362
414792
  import { mkdir as mkdir49, unlink as unlink22, writeFile as writeFile44 } from "fs/promises";
414363
414793
  import { tmpdir as tmpdir10 } from "os";
414364
- import { join as join156 } from "path";
414794
+ import { join as join157 } from "path";
414365
414795
  async function copyAnsiToClipboard(ansiText, options) {
414366
414796
  try {
414367
- const tempDir = join156(tmpdir10(), "atlas-screenshots");
414797
+ const tempDir = join157(tmpdir10(), "atlas-screenshots");
414368
414798
  await mkdir49(tempDir, { recursive: true });
414369
- const pngPath = join156(tempDir, `screenshot-${Date.now()}.png`);
414799
+ const pngPath = join157(tempDir, `screenshot-${Date.now()}.png`);
414370
414800
  const pngBuffer = ansiToPng(ansiText, options);
414371
414801
  await writeFile44(pngPath, pngBuffer);
414372
414802
  const result = await copyPngToClipboard(pngPath);
@@ -414437,7 +414867,7 @@ var init_screenshotClipboard = __esm(() => {
414437
414867
 
414438
414868
  // src/tui/utils/stats.ts
414439
414869
  import { open as open18 } from "fs/promises";
414440
- import { basename as basename46, dirname as dirname75, join as join157, sep as sep33 } from "path";
414870
+ import { basename as basename46, dirname as dirname75, join as join158, sep as sep34 } from "path";
414441
414871
  async function processSessionFiles(sessionFiles, options = {}) {
414442
414872
  const { fromDate, toDate } = options;
414443
414873
  const fs = getFsImplementation2();
@@ -414506,7 +414936,7 @@ async function processSessionFiles(sessionFiles, options = {}) {
414506
414936
  }
414507
414937
  if (messages.length === 0)
414508
414938
  continue;
414509
- const isSubagentFile = sessionFile.includes(`${sep33}subagents${sep33}`);
414939
+ const isSubagentFile = sessionFile.includes(`${sep34}subagents${sep34}`);
414510
414940
  if (feature("SHOT_STATS") && shotDistributionMap) {
414511
414941
  const parentSessionId = isSubagentFile ? basename46(dirname75(dirname75(sessionFile))) : sessionId;
414512
414942
  if (!sessionsWithShotCount.has(parentSessionId)) {
@@ -414623,17 +415053,17 @@ async function getAllSessionFiles() {
414623
415053
  return [];
414624
415054
  throw e;
414625
415055
  }
414626
- const projectDirs = allEntries.filter((dirent) => dirent.isDirectory()).map((dirent) => join157(projectsDir, dirent.name));
415056
+ const projectDirs = allEntries.filter((dirent) => dirent.isDirectory()).map((dirent) => join158(projectsDir, dirent.name));
414627
415057
  const projectResults = await Promise.all(projectDirs.map(async (projectDir) => {
414628
415058
  try {
414629
415059
  const entries = await fs.readdir(projectDir);
414630
- const mainFiles = entries.filter((dirent) => dirent.isFile() && dirent.name.endsWith(".jsonl")).map((dirent) => join157(projectDir, dirent.name));
415060
+ const mainFiles = entries.filter((dirent) => dirent.isFile() && dirent.name.endsWith(".jsonl")).map((dirent) => join158(projectDir, dirent.name));
414631
415061
  const sessionDirs = entries.filter((dirent) => dirent.isDirectory());
414632
415062
  const subagentResults = await Promise.all(sessionDirs.map(async (sessionDir) => {
414633
- const subagentsDir = join157(projectDir, sessionDir.name, "subagents");
415063
+ const subagentsDir = join158(projectDir, sessionDir.name, "subagents");
414634
415064
  try {
414635
415065
  const subagentEntries = await fs.readdir(subagentsDir);
414636
- return subagentEntries.filter((dirent) => dirent.isFile() && dirent.name.endsWith(".jsonl") && dirent.name.startsWith("agent-")).map((dirent) => join157(subagentsDir, dirent.name));
415066
+ return subagentEntries.filter((dirent) => dirent.isFile() && dirent.name.endsWith(".jsonl") && dirent.name.startsWith("agent-")).map((dirent) => join158(subagentsDir, dirent.name));
414637
415067
  } catch {
414638
415068
  return [];
414639
415069
  }
@@ -416533,9 +416963,9 @@ var init_Stats = __esm(() => {
416533
416963
  // src/tui/commands/stats/stats.tsx
416534
416964
  var exports_stats = {};
416535
416965
  __export(exports_stats, {
416536
- call: () => call55
416966
+ call: () => call58
416537
416967
  });
416538
- var jsx_dev_runtime310, call55 = async (onDone) => {
416968
+ var jsx_dev_runtime310, call58 = async (onDone) => {
416539
416969
  return /* @__PURE__ */ jsx_dev_runtime310.jsxDEV(Stats2, {
416540
416970
  onClose: onDone
416541
416971
  }, undefined, false, undefined, this);
@@ -417287,9 +417717,9 @@ var init_useVoice = __esm(() => {
417287
417717
  // src/tui/commands/voice/voice.ts
417288
417718
  var exports_voice3 = {};
417289
417719
  __export(exports_voice3, {
417290
- call: () => call56
417720
+ call: () => call59
417291
417721
  });
417292
- var LANG_HINT_MAX_SHOWS = 2, call56 = async () => {
417722
+ var LANG_HINT_MAX_SHOWS = 2, call59 = async () => {
417293
417723
  if (!isVoiceModeEnabled()) {
417294
417724
  return {
417295
417725
  type: "text",
@@ -417488,7 +417918,7 @@ import {
417488
417918
  unlink as unlink23,
417489
417919
  writeFile as writeFile45
417490
417920
  } from "fs/promises";
417491
- import { extname as extname16, join as join158 } from "path";
417921
+ import { extname as extname16, join as join159 } from "path";
417492
417922
  function getAnalysisModel() {
417493
417923
  return getDefaultPremiumModel();
417494
417924
  }
@@ -417496,13 +417926,13 @@ function getInsightsModel() {
417496
417926
  return getDefaultPremiumModel();
417497
417927
  }
417498
417928
  function getDataDir() {
417499
- return join158(getAtlasConfigHomeDir3(), "usage-data");
417929
+ return join159(getAtlasConfigHomeDir3(), "usage-data");
417500
417930
  }
417501
417931
  function getFacetsDir() {
417502
- return join158(getDataDir(), "facets");
417932
+ return join159(getDataDir(), "facets");
417503
417933
  }
417504
417934
  function getSessionMetaDir() {
417505
- return join158(getDataDir(), "session-meta");
417935
+ return join159(getDataDir(), "session-meta");
417506
417936
  }
417507
417937
  function getLanguageFromPath(filePath) {
417508
417938
  const ext = extname16(filePath).toLowerCase();
@@ -417843,7 +418273,7 @@ async function formatTranscriptWithSummarization(log) {
417843
418273
  `);
417844
418274
  }
417845
418275
  async function loadCachedFacets(sessionId) {
417846
- const facetPath = join158(getFacetsDir(), `${sessionId}.json`);
418276
+ const facetPath = join159(getFacetsDir(), `${sessionId}.json`);
417847
418277
  try {
417848
418278
  const content = await readFile59(facetPath, { encoding: "utf-8" });
417849
418279
  const parsed = jsonParse2(content);
@@ -417862,14 +418292,14 @@ async function saveFacets(facets) {
417862
418292
  try {
417863
418293
  await mkdir50(getFacetsDir(), { recursive: true });
417864
418294
  } catch {}
417865
- const facetPath = join158(getFacetsDir(), `${facets.session_id}.json`);
418295
+ const facetPath = join159(getFacetsDir(), `${facets.session_id}.json`);
417866
418296
  await writeFile45(facetPath, jsonStringify5(facets, null, 2), {
417867
418297
  encoding: "utf-8",
417868
418298
  mode: 384
417869
418299
  });
417870
418300
  }
417871
418301
  async function loadCachedSessionMeta(sessionId) {
417872
- const metaPath = join158(getSessionMetaDir(), `${sessionId}.json`);
418302
+ const metaPath = join159(getSessionMetaDir(), `${sessionId}.json`);
417873
418303
  try {
417874
418304
  const content = await readFile59(metaPath, { encoding: "utf-8" });
417875
418305
  return jsonParse2(content);
@@ -417881,7 +418311,7 @@ async function saveSessionMeta(meta) {
417881
418311
  try {
417882
418312
  await mkdir50(getSessionMetaDir(), { recursive: true });
417883
418313
  } catch {}
417884
- const metaPath = join158(getSessionMetaDir(), `${meta.session_id}.json`);
418314
+ const metaPath = join159(getSessionMetaDir(), `${meta.session_id}.json`);
417885
418315
  await writeFile45(metaPath, jsonStringify5(meta, null, 2), {
417886
418316
  encoding: "utf-8",
417887
418317
  mode: 384
@@ -418961,7 +419391,7 @@ async function scanAllSessions() {
418961
419391
  } catch {
418962
419392
  return [];
418963
419393
  }
418964
- const projectDirs = dirents.filter((dirent) => dirent.isDirectory()).map((dirent) => join158(projectsDir, dirent.name));
419394
+ const projectDirs = dirents.filter((dirent) => dirent.isDirectory()).map((dirent) => join159(projectsDir, dirent.name));
418965
419395
  const allSessions = [];
418966
419396
  for (let i = 0;i < projectDirs.length; i++) {
418967
419397
  const sessionFiles = await getSessionFilesWithMtime(projectDirs[i]);
@@ -419117,7 +419547,7 @@ async function generateUsageReport(options) {
419117
419547
  try {
419118
419548
  await mkdir50(getDataDir(), { recursive: true });
419119
419549
  } catch {}
419120
- const htmlPath = join158(getDataDir(), "report.html");
419550
+ const htmlPath = join159(getDataDir(), "report.html");
419121
419551
  await writeFile45(htmlPath, htmlReport, {
419122
419552
  encoding: "utf-8",
419123
419553
  mode: 384
@@ -419670,6 +420100,9 @@ var init_commands5 = __esm(() => {
419670
420100
  init_agents3();
419671
420101
  init_plugin3();
419672
420102
  init_reload_plugins2();
420103
+ init_reload_skills2();
420104
+ init_cd2();
420105
+ init_output_style2();
419673
420106
  init_rewind();
419674
420107
  init_heapdump2();
419675
420108
  init_version();
@@ -419726,6 +420159,7 @@ var init_commands5 = __esm(() => {
419726
420159
  autocompact_default,
419727
420160
  branch_default,
419728
420161
  btw_default,
420162
+ cd_default,
419729
420163
  clear_default,
419730
420164
  color_default,
419731
420165
  compact_default,
@@ -419747,9 +420181,11 @@ var init_commands5 = __esm(() => {
419747
420181
  mcp_default,
419748
420182
  memory_default,
419749
420183
  model_default,
420184
+ output_style_default,
419750
420185
  plugin_default,
419751
420186
  release_notes_default,
419752
420187
  reload_plugins_default,
420188
+ reload_skills_default,
419753
420189
  rename_default,
419754
420190
  resume_default,
419755
420191
  session_default,
@@ -419925,7 +420361,7 @@ import {
419925
420361
  unlink as unlink24,
419926
420362
  writeFile as writeFile46
419927
420363
  } from "fs/promises";
419928
- import { basename as basename48, dirname as dirname76, join as join159 } from "path";
420364
+ import { basename as basename48, dirname as dirname76, join as join160 } from "path";
419929
420365
  function isTranscriptMessage2(entry) {
419930
420366
  return entry.type === "user" || entry.type === "assistant" || entry.type === "attachment" || entry.type === "system";
419931
420367
  }
@@ -419939,18 +420375,18 @@ function isEphemeralToolProgress2(dataType) {
419939
420375
  return typeof dataType === "string" && EPHEMERAL_PROGRESS_TYPES2.has(dataType);
419940
420376
  }
419941
420377
  function getProjectsDir3() {
419942
- return join159(getAtlasConfigHomeDir3(), "projects");
420378
+ return join160(getAtlasConfigHomeDir3(), "projects");
419943
420379
  }
419944
420380
  function getTranscriptPath2() {
419945
420381
  const projectDir = getSessionProjectDir() ?? getProjectDir3(getOriginalCwd());
419946
- return join159(projectDir, `${getSessionId()}.jsonl`);
420382
+ return join160(projectDir, `${getSessionId()}.jsonl`);
419947
420383
  }
419948
420384
  function getTranscriptPathForSession3(sessionId) {
419949
420385
  if (sessionId === getSessionId()) {
419950
420386
  return getTranscriptPath2();
419951
420387
  }
419952
420388
  const projectDir = getProjectDir3(getOriginalCwd());
419953
- return join159(projectDir, `${sessionId}.jsonl`);
420389
+ return join160(projectDir, `${sessionId}.jsonl`);
419954
420390
  }
419955
420391
  function setAgentTranscriptSubdir2(agentId, subdir) {
419956
420392
  agentTranscriptSubdirs2.set(agentId, subdir);
@@ -419962,8 +420398,8 @@ function getAgentTranscriptPath2(agentId) {
419962
420398
  const projectDir = getSessionProjectDir() ?? getProjectDir3(getOriginalCwd());
419963
420399
  const sessionId = getSessionId();
419964
420400
  const subdir = agentTranscriptSubdirs2.get(agentId);
419965
- const base = subdir ? join159(projectDir, sessionId, "subagents", subdir) : join159(projectDir, sessionId, "subagents");
419966
- return join159(base, `agent-${agentId}.jsonl`);
420401
+ const base = subdir ? join160(projectDir, sessionId, "subagents", subdir) : join160(projectDir, sessionId, "subagents");
420402
+ return join160(base, `agent-${agentId}.jsonl`);
419967
420403
  }
419968
420404
  function getAgentMetadataPath(agentId) {
419969
420405
  return getAgentTranscriptPath2(agentId).replace(/\.jsonl$/, ".meta.json");
@@ -419986,7 +420422,7 @@ async function readAgentMetadata(agentId) {
419986
420422
  }
419987
420423
  function sessionIdExists(sessionId) {
419988
420424
  const projectDir = getProjectDir3(getOriginalCwd());
419989
- const sessionFile = join159(projectDir, `${sessionId}.jsonl`);
420425
+ const sessionFile = join160(projectDir, `${sessionId}.jsonl`);
419990
420426
  const fs = getFsImplementation2();
419991
420427
  try {
419992
420428
  fs.statSync(sessionFile);
@@ -421718,7 +422154,7 @@ async function loadTranscriptFile2(filePath, opts) {
421718
422154
  };
421719
422155
  }
421720
422156
  async function loadSessionFile2(sessionId) {
421721
- const sessionFile = join159(getSessionProjectDir() ?? getProjectDir3(getOriginalCwd()), `${sessionId}.jsonl`);
422157
+ const sessionFile = join160(getSessionProjectDir() ?? getProjectDir3(getOriginalCwd()), `${sessionId}.jsonl`);
421722
422158
  return loadTranscriptFile2(sessionFile);
421723
422159
  }
421724
422160
  function clearSessionMessagesCache2() {
@@ -421782,7 +422218,7 @@ async function loadAllProjectsMessageLogsFull(limit) {
421782
422218
  } catch {
421783
422219
  return [];
421784
422220
  }
421785
- const projectDirs = dirents.filter((dirent) => dirent.isDirectory()).map((dirent) => join159(projectsDir, dirent.name));
422221
+ const projectDirs = dirents.filter((dirent) => dirent.isDirectory()).map((dirent) => join160(projectsDir, dirent.name));
421786
422222
  const logsPerProject = await Promise.all(projectDirs.map((projectDir) => getLogsWithoutIndex(projectDir, limit)));
421787
422223
  const allLogs = logsPerProject.flat();
421788
422224
  const deduped = new Map;
@@ -421807,7 +422243,7 @@ async function loadAllProjectsMessageLogsProgressive(limit, initialEnrichCount =
421807
422243
  } catch {
421808
422244
  return { logs: [], allStatLogs: [], nextIndex: 0 };
421809
422245
  }
421810
- const projectDirs = dirents.filter((dirent) => dirent.isDirectory()).map((dirent) => join159(projectsDir, dirent.name));
422246
+ const projectDirs = dirents.filter((dirent) => dirent.isDirectory()).map((dirent) => join160(projectsDir, dirent.name));
421811
422247
  const rawLogs = [];
421812
422248
  for (const projectDir of projectDirs) {
421813
422249
  rawLogs.push(...await getSessionFilesLite(projectDir, limit));
@@ -421883,7 +422319,7 @@ async function getStatOnlyLogsForWorktrees(worktreePaths, limit) {
421883
422319
  for (const { path: wtPath, prefix } of indexed) {
421884
422320
  if (dirName === prefix || dirName.startsWith(prefix + "-")) {
421885
422321
  seenDirs.add(dirName);
421886
- allLogs.push(...await getSessionFilesLite(join159(projectsDir, dirent.name), undefined, wtPath));
422322
+ allLogs.push(...await getSessionFilesLite(join160(projectsDir, dirent.name), undefined, wtPath));
421887
422323
  break;
421888
422324
  }
421889
422325
  }
@@ -421943,7 +422379,7 @@ async function loadSubagentTranscripts(agentIds) {
421943
422379
  return transcripts;
421944
422380
  }
421945
422381
  async function loadAllSubagentTranscriptsFromDisk() {
421946
- const subagentsDir = join159(getSessionProjectDir() ?? getProjectDir3(getOriginalCwd()), getSessionId(), "subagents");
422382
+ const subagentsDir = join160(getSessionProjectDir() ?? getProjectDir3(getOriginalCwd()), getSessionId(), "subagents");
421947
422383
  let entries;
421948
422384
  try {
421949
422385
  entries = await readdir33(subagentsDir, { withFileTypes: true });
@@ -422038,7 +422474,7 @@ async function getSessionFilesWithMtime(projectDir) {
422038
422474
  const sessionId = validateUuid2(basename48(dirent.name, ".jsonl"));
422039
422475
  if (!sessionId)
422040
422476
  continue;
422041
- candidates.push({ sessionId, filePath: join159(projectDir, dirent.name) });
422477
+ candidates.push({ sessionId, filePath: join160(projectDir, dirent.name) });
422042
422478
  }
422043
422479
  await Promise.all(candidates.map(async ({ sessionId, filePath }) => {
422044
422480
  try {
@@ -422460,7 +422896,7 @@ var init_sessionStorage = __esm(() => {
422460
422896
  MAX_TRANSCRIPT_READ_BYTES2 = 50 * 1024 * 1024;
422461
422897
  agentTranscriptSubdirs2 = new Map;
422462
422898
  getProjectDir3 = memoize_default((projectDir) => {
422463
- return join159(getProjectsDir3(), sanitizePath3(projectDir));
422899
+ return join160(getProjectsDir3(), sanitizePath3(projectDir));
422464
422900
  });
422465
422901
  METADATA_TYPE_MARKERS2 = [
422466
422902
  '"type":"summary"',
@@ -422479,7 +422915,7 @@ var init_sessionStorage = __esm(() => {
422479
422915
  // src/tui/utils/plans.ts
422480
422916
  import { randomUUID as randomUUID40 } from "crypto";
422481
422917
  import { copyFile as copyFile9, writeFile as writeFile47 } from "fs/promises";
422482
- import { join as join160, resolve as resolve53, sep as sep34 } from "path";
422918
+ import { join as join161, resolve as resolve54, sep as sep35 } from "path";
422483
422919
  function getPlanSlug2(sessionId) {
422484
422920
  const id = sessionId ?? getSessionId();
422485
422921
  const cache = getPlanSlugCache();
@@ -422488,7 +422924,7 @@ function getPlanSlug2(sessionId) {
422488
422924
  const plansDir = getPlansDirectory2();
422489
422925
  for (let i = 0;i < MAX_SLUG_RETRIES2; i++) {
422490
422926
  slug = generateWordSlug2();
422491
- const filePath = join160(plansDir, `${slug}.md`);
422927
+ const filePath = join161(plansDir, `${slug}.md`);
422492
422928
  if (!getFsImplementation2().existsSync(filePath)) {
422493
422929
  break;
422494
422930
  }
@@ -422506,9 +422942,9 @@ function clearAllPlanSlugs2() {
422506
422942
  function getPlanFilePath2(agentId) {
422507
422943
  const planSlug = getPlanSlug2(getSessionId());
422508
422944
  if (!agentId) {
422509
- return join160(getPlansDirectory2(), `${planSlug}.md`);
422945
+ return join161(getPlansDirectory2(), `${planSlug}.md`);
422510
422946
  }
422511
- return join160(getPlansDirectory2(), `${planSlug}-agent-${agentId}.md`);
422947
+ return join161(getPlansDirectory2(), `${planSlug}-agent-${agentId}.md`);
422512
422948
  }
422513
422949
  function getPlan2(agentId) {
422514
422950
  const filePath = getPlanFilePath2(agentId);
@@ -422531,7 +422967,7 @@ async function copyPlanForResume(log, targetSessionId) {
422531
422967
  }
422532
422968
  const sessionId = targetSessionId ?? getSessionId();
422533
422969
  setPlanSlug2(sessionId, slug);
422534
- const planPath = join160(getPlansDirectory2(), `${slug}.md`);
422970
+ const planPath = join161(getPlansDirectory2(), `${slug}.md`);
422535
422971
  try {
422536
422972
  await getFsImplementation2().readFile(planPath, { encoding: "utf-8" });
422537
422973
  return true;
@@ -422574,9 +423010,9 @@ async function copyPlanForFork(log, targetSessionId) {
422574
423010
  return false;
422575
423011
  }
422576
423012
  const plansDir = getPlansDirectory2();
422577
- const originalPlanPath = join160(plansDir, `${originalSlug}.md`);
423013
+ const originalPlanPath = join161(plansDir, `${originalSlug}.md`);
422578
423014
  const newSlug = getPlanSlug2(targetSessionId);
422579
- const newPlanPath = join160(plansDir, `${newSlug}.md`);
423015
+ const newPlanPath = join161(plansDir, `${newSlug}.md`);
422580
423016
  try {
422581
423017
  await copyFile9(originalPlanPath, newPlanPath);
422582
423018
  return true;
@@ -422689,15 +423125,15 @@ var init_plans = __esm(() => {
422689
423125
  let plansPath;
422690
423126
  if (settingsDir) {
422691
423127
  const cwd = getCwd();
422692
- const resolved = resolve53(cwd, settingsDir);
422693
- if (!resolved.startsWith(cwd + sep34) && resolved !== cwd) {
423128
+ const resolved = resolve54(cwd, settingsDir);
423129
+ if (!resolved.startsWith(cwd + sep35) && resolved !== cwd) {
422694
423130
  logError3(new Error(`plansDirectory must be within project root: ${settingsDir}`));
422695
- plansPath = join160(getAtlasConfigHomeDir3(), "plans");
423131
+ plansPath = join161(getAtlasConfigHomeDir3(), "plans");
422696
423132
  } else {
422697
423133
  plansPath = resolved;
422698
423134
  }
422699
423135
  } else {
422700
- plansPath = join160(getAtlasConfigHomeDir3(), "plans");
423136
+ plansPath = join161(getAtlasConfigHomeDir3(), "plans");
422701
423137
  }
422702
423138
  try {
422703
423139
  getFsImplementation2().mkdirSync(plansPath);
@@ -422711,7 +423147,7 @@ var init_plans = __esm(() => {
422711
423147
  // src/tui/utils/permissions/filesystem.ts
422712
423148
  import { randomBytes as randomBytes21 } from "crypto";
422713
423149
  import { homedir as homedir38, tmpdir as tmpdir11 } from "os";
422714
- import { join as join161, normalize as normalize15, posix as posix9, resolve as resolve54, sep as sep35 } from "path";
423150
+ import { join as join162, normalize as normalize15, posix as posix9, resolve as resolve55, sep as sep36 } from "path";
422715
423151
  function normalizeCaseForComparison2(path) {
422716
423152
  return path.toLowerCase();
422717
423153
  }
@@ -422721,21 +423157,21 @@ function getClaudeSkillScope(filePath) {
422721
423157
  const configDir = getConfigDirName2();
422722
423158
  const bases = [
422723
423159
  {
422724
- dir: expandPath2(join161(getOriginalCwd(), configDir, "skills")),
423160
+ dir: expandPath2(join162(getOriginalCwd(), configDir, "skills")),
422725
423161
  prefix: `/${configDir}/skills/`
422726
423162
  },
422727
423163
  {
422728
- dir: expandPath2(join161(homedir38(), configDir, "skills")),
423164
+ dir: expandPath2(join162(homedir38(), configDir, "skills")),
422729
423165
  prefix: `~/${configDir}/skills/`
422730
423166
  }
422731
423167
  ];
422732
423168
  for (const { dir, prefix } of bases) {
422733
423169
  const dirLower = normalizeCaseForComparison2(dir);
422734
- for (const s of [sep35, "/"]) {
423170
+ for (const s of [sep36, "/"]) {
422735
423171
  if (absolutePathLower.startsWith(dirLower + s.toLowerCase())) {
422736
423172
  const rest = absolutePath.slice(dir.length + s.length);
422737
423173
  const slash = rest.indexOf("/");
422738
- const bslash = sep35 === "\\" ? rest.indexOf("\\") : -1;
423174
+ const bslash = sep36 === "\\" ? rest.indexOf("\\") : -1;
422739
423175
  const cut = slash === -1 ? bslash : bslash === -1 ? slash : Math.min(slash, bslash);
422740
423176
  if (cut <= 0)
422741
423177
  return null;
@@ -422771,7 +423207,7 @@ function getSettingsPaths3() {
422771
423207
  function isAtlasSettingsPath2(filePath) {
422772
423208
  const expandedPath = expandPath2(filePath);
422773
423209
  const normalizedPath = normalizeCaseForComparison2(expandedPath);
422774
- if (normalizedPath.endsWith(`${sep35}getConfigDirName()${sep35}settings.json`) || normalizedPath.endsWith(`${sep35}getConfigDirName()${sep35}settings.local.json`)) {
423210
+ if (normalizedPath.endsWith(`${sep36}getConfigDirName()${sep36}settings.json`) || normalizedPath.endsWith(`${sep36}getConfigDirName()${sep36}settings.local.json`)) {
422775
423211
  return true;
422776
423212
  }
422777
423213
  return getSettingsPaths3().some((settingsPath) => normalizeCaseForComparison2(settingsPath) === normalizedPath);
@@ -422780,21 +423216,21 @@ function isClaudeConfigFilePath2(filePath) {
422780
423216
  if (isAtlasSettingsPath2(filePath)) {
422781
423217
  return true;
422782
423218
  }
422783
- const commandsDir = join161(getOriginalCwd(), getConfigDirName2(), "commands");
422784
- const agentsDir = join161(getOriginalCwd(), getConfigDirName2(), "agents");
422785
- const skillsDir = join161(getOriginalCwd(), getConfigDirName2(), "skills");
423219
+ const commandsDir = join162(getOriginalCwd(), getConfigDirName2(), "commands");
423220
+ const agentsDir = join162(getOriginalCwd(), getConfigDirName2(), "agents");
423221
+ const skillsDir = join162(getOriginalCwd(), getConfigDirName2(), "skills");
422786
423222
  return pathInWorkingPath2(filePath, commandsDir) || pathInWorkingPath2(filePath, agentsDir) || pathInWorkingPath2(filePath, skillsDir);
422787
423223
  }
422788
423224
  function isSessionPlanFile(absolutePath) {
422789
- const expectedPrefix = join161(getPlansDirectory2(), getPlanSlug2());
423225
+ const expectedPrefix = join162(getPlansDirectory2(), getPlanSlug2());
422790
423226
  const normalizedPath = normalize15(absolutePath);
422791
423227
  return normalizedPath.startsWith(expectedPrefix) && normalizedPath.endsWith(".md");
422792
423228
  }
422793
423229
  function getSessionMemoryDir() {
422794
- return join161(getProjectDir3(getCwd()), getSessionId(), "session-memory") + sep35;
423230
+ return join162(getProjectDir3(getCwd()), getSessionId(), "session-memory") + sep36;
422795
423231
  }
422796
423232
  function getSessionMemoryPath() {
422797
- return join161(getSessionMemoryDir(), "summary.md");
423233
+ return join162(getSessionMemoryDir(), "summary.md");
422798
423234
  }
422799
423235
  function isSessionMemoryPath(absolutePath) {
422800
423236
  const normalizedPath = normalize15(absolutePath);
@@ -422803,7 +423239,7 @@ function isSessionMemoryPath(absolutePath) {
422803
423239
  function isProjectDirPath(absolutePath) {
422804
423240
  const projectDir = getProjectDir3(getCwd());
422805
423241
  const normalizedPath = normalize15(absolutePath);
422806
- return normalizedPath === projectDir || normalizedPath.startsWith(projectDir + sep35);
423242
+ return normalizedPath === projectDir || normalizedPath.startsWith(projectDir + sep36);
422807
423243
  }
422808
423244
  function isScratchpadEnabled() {
422809
423245
  return checkStatsigFeatureGate_CACHED_MAY_BE_STALE("atlas_scratch");
@@ -422816,10 +423252,10 @@ function getAtlasTempDirName2() {
422816
423252
  return `${getConfigDirName2()}-${uid}`;
422817
423253
  }
422818
423254
  function getProjectTempDir2() {
422819
- return join161(getAtlasTempDir2(), sanitizePath3(getOriginalCwd())) + sep35;
423255
+ return join162(getAtlasTempDir2(), sanitizePath3(getOriginalCwd())) + sep36;
422820
423256
  }
422821
423257
  function getScratchpadDir() {
422822
- return join161(getProjectTempDir2(), getSessionId(), "scratchpad");
423258
+ return join162(getProjectTempDir2(), getSessionId(), "scratchpad");
422823
423259
  }
422824
423260
  async function ensureScratchpadDir() {
422825
423261
  if (!isScratchpadEnabled()) {
@@ -422836,11 +423272,11 @@ function isScratchpadPath(absolutePath) {
422836
423272
  }
422837
423273
  const scratchpadDir = getScratchpadDir();
422838
423274
  const normalizedPath = normalize15(absolutePath);
422839
- return normalizedPath === scratchpadDir || normalizedPath.startsWith(scratchpadDir + sep35);
423275
+ return normalizedPath === scratchpadDir || normalizedPath.startsWith(scratchpadDir + sep36);
422840
423276
  }
422841
423277
  function isDangerousFilePathToAutoEdit2(path) {
422842
423278
  const absolutePath = expandPath2(path);
422843
- const pathSegments = absolutePath.split(sep35);
423279
+ const pathSegments = absolutePath.split(sep36);
422844
423280
  const fileName = pathSegments.at(-1);
422845
423281
  if (path.startsWith("\\\\") || path.startsWith("//")) {
422846
423282
  return true;
@@ -422934,13 +423370,13 @@ function isActiveWorktreeCwd2(cwd) {
422934
423370
  }
422935
423371
  let active = false;
422936
423372
  try {
422937
- const content = getFsImplementation2().readFileSync(join161(cwd, ".git"), {
423373
+ const content = getFsImplementation2().readFileSync(join162(cwd, ".git"), {
422938
423374
  encoding: "utf8"
422939
423375
  });
422940
423376
  const gitdirMatch = content.match(/^gitdir:\s*(.+)$/m);
422941
423377
  if (gitdirMatch?.[1]) {
422942
- const gitdir = resolve54(cwd, gitdirMatch[1].trim());
422943
- active = gitdir.lastIndexOf(sep35 + ".git" + sep35 + "worktrees" + sep35) > 0;
423378
+ const gitdir = resolve55(cwd, gitdirMatch[1].trim());
423379
+ active = gitdir.lastIndexOf(sep36 + ".git" + sep36 + "worktrees" + sep36) > 0;
422944
423380
  }
422945
423381
  } catch {
422946
423382
  active = false;
@@ -423406,15 +423842,15 @@ function checkEditableInternalPath2(absolutePath, input) {
423406
423842
  if (feature("TEMPLATES")) {
423407
423843
  const jobDir = process.env.ATLAS_JOB_DIR;
423408
423844
  if (jobDir) {
423409
- const jobsRoot = join161(getAtlasConfigHomeDir3(), "jobs");
423845
+ const jobsRoot = join162(getAtlasConfigHomeDir3(), "jobs");
423410
423846
  const jobDirForms = getPathsForPermissionCheck2(jobDir).map(normalize15);
423411
423847
  const jobsRootForms = getPathsForPermissionCheck2(jobsRoot).map(normalize15);
423412
- const isUnderJobsRoot = jobDirForms.every((jd) => jobsRootForms.some((jr) => jd.startsWith(jr + sep35)));
423848
+ const isUnderJobsRoot = jobDirForms.every((jd) => jobsRootForms.some((jr) => jd.startsWith(jr + sep36)));
423413
423849
  if (isUnderJobsRoot) {
423414
423850
  const targetForms = getPathsForPermissionCheck2(absolutePath);
423415
423851
  const allInsideJobDir = targetForms.every((p) => {
423416
423852
  const np = normalize15(p);
423417
- return jobDirForms.some((jd) => np === jd || np.startsWith(jd + sep35));
423853
+ return jobDirForms.some((jd) => np === jd || np.startsWith(jd + sep36));
423418
423854
  });
423419
423855
  if (allInsideJobDir) {
423420
423856
  return {
@@ -423449,7 +423885,7 @@ function checkEditableInternalPath2(absolutePath, input) {
423449
423885
  }
423450
423886
  };
423451
423887
  }
423452
- if (normalizeCaseForComparison2(normalizedPath) === normalizeCaseForComparison2(join161(getOriginalCwd(), getConfigDirName2(), "launch.json"))) {
423888
+ if (normalizeCaseForComparison2(normalizedPath) === normalizeCaseForComparison2(join162(getOriginalCwd(), getConfigDirName2(), "launch.json"))) {
423453
423889
  return {
423454
423890
  behavior: "allow",
423455
423891
  updatedInput: input,
@@ -423494,7 +423930,7 @@ function checkReadableInternalPath2(absolutePath, input) {
423494
423930
  };
423495
423931
  }
423496
423932
  const toolResultsDir = getToolResultsDir3();
423497
- const toolResultsDirWithSep = toolResultsDir.endsWith(sep35) ? toolResultsDir : toolResultsDir + sep35;
423933
+ const toolResultsDirWithSep = toolResultsDir.endsWith(sep36) ? toolResultsDir : toolResultsDir + sep36;
423498
423934
  if (normalizedPath === toolResultsDir || normalizedPath.startsWith(toolResultsDirWithSep)) {
423499
423935
  return {
423500
423936
  behavior: "allow",
@@ -423546,7 +423982,7 @@ function checkReadableInternalPath2(absolutePath, input) {
423546
423982
  }
423547
423983
  };
423548
423984
  }
423549
- const tasksDir = join161(getAtlasConfigHomeDir3(), "tasks") + sep35;
423985
+ const tasksDir = join162(getAtlasConfigHomeDir3(), "tasks") + sep36;
423550
423986
  if (normalizedPath === tasksDir.slice(0, -1) || normalizedPath.startsWith(tasksDir)) {
423551
423987
  return {
423552
423988
  behavior: "allow",
@@ -423557,7 +423993,7 @@ function checkReadableInternalPath2(absolutePath, input) {
423557
423993
  }
423558
423994
  };
423559
423995
  }
423560
- const teamsReadDir = join161(getAtlasConfigHomeDir3(), "teams") + sep35;
423996
+ const teamsReadDir = join162(getAtlasConfigHomeDir3(), "teams") + sep36;
423561
423997
  if (normalizedPath === teamsReadDir.slice(0, -1) || normalizedPath.startsWith(teamsReadDir)) {
423562
423998
  return {
423563
423999
  behavior: "allow",
@@ -423568,7 +424004,7 @@ function checkReadableInternalPath2(absolutePath, input) {
423568
424004
  }
423569
424005
  };
423570
424006
  }
423571
- const bundledSkillsRoot = getBundledSkillsRoot2() + sep35;
424007
+ const bundledSkillsRoot = getBundledSkillsRoot2() + sep36;
423572
424008
  if (normalizedPath.startsWith(bundledSkillsRoot)) {
423573
424009
  return {
423574
424010
  behavior: "allow",
@@ -423634,11 +424070,11 @@ var init_filesystem2 = __esm(() => {
423634
424070
  try {
423635
424071
  resolvedBaseTmpDir = fs.realpathSync(baseTmpDir);
423636
424072
  } catch {}
423637
- return join161(resolvedBaseTmpDir, getAtlasTempDirName2()) + sep35;
424073
+ return join162(resolvedBaseTmpDir, getAtlasTempDirName2()) + sep36;
423638
424074
  });
423639
424075
  getBundledSkillsRoot2 = memoize_default(function getBundledSkillsRoot() {
423640
424076
  const nonce = randomBytes21(16).toString("hex");
423641
- return join161(getAtlasTempDir2(), "bundled-skills", MACRO.VERSION, nonce);
424077
+ return join162(getAtlasTempDir2(), "bundled-skills", MACRO.VERSION, nonce);
423642
424078
  });
423643
424079
  worktreeCwdProbeCache2 = new Map;
423644
424080
  getResolvedWorkingDirPaths2 = memoize_default(getPathsForPermissionCheck2);
@@ -423653,10 +424089,10 @@ import {
423653
424089
  symlink as symlink7,
423654
424090
  unlink as unlink25
423655
424091
  } from "fs/promises";
423656
- import { join as join162 } from "path";
424092
+ import { join as join163 } from "path";
423657
424093
  function getTaskOutputDir2() {
423658
424094
  if (_taskOutputDir2 === undefined) {
423659
- _taskOutputDir2 = join162(getProjectTempDir2(), getSessionId(), "tasks");
424095
+ _taskOutputDir2 = join163(getProjectTempDir2(), getSessionId(), "tasks");
423660
424096
  }
423661
424097
  return _taskOutputDir2;
423662
424098
  }
@@ -423664,7 +424100,7 @@ async function ensureOutputDir2() {
423664
424100
  await mkdir52(getTaskOutputDir2(), { recursive: true });
423665
424101
  }
423666
424102
  function getTaskOutputPath2(taskId) {
423667
- return join162(getTaskOutputDir2(), `${taskId}.output`);
424103
+ return join163(getTaskOutputDir2(), `${taskId}.output`);
423668
424104
  }
423669
424105
  function track2(p) {
423670
424106
  _pendingOps2.add(p);
@@ -430695,7 +431131,7 @@ var init_compact4 = __esm(() => {
430695
431131
 
430696
431132
  // src/tui/services/SessionMemory/prompts.ts
430697
431133
  import { readFile as readFile61 } from "fs/promises";
430698
- import { join as join163 } from "path";
431134
+ import { join as join164 } from "path";
430699
431135
  function getDefaultUpdatePrompt() {
430700
431136
  return `IMPORTANT: This message and these instructions are NOT part of the actual user conversation. Do NOT include any references to "note-taking", "session notes extraction", or these update instructions in the notes content.
430701
431137
 
@@ -430736,7 +431172,7 @@ You ONLY update the actual content that comes AFTER these two preserved lines. T
430736
431172
  REMEMBER: Use the Edit tool in parallel and stop. Do not continue after the edits. Only include insights from the actual user conversation, never from these note-taking instructions. Do not delete or change section headers or italic _section descriptions_.`;
430737
431173
  }
430738
431174
  async function loadSessionMemoryTemplate() {
430739
- const templatePath = join163(getAtlasConfigHomeDir3(), "session-memory", "config", "template.md");
431175
+ const templatePath = join164(getAtlasConfigHomeDir3(), "session-memory", "config", "template.md");
430740
431176
  try {
430741
431177
  return await readFile61(templatePath, { encoding: "utf-8" });
430742
431178
  } catch (e) {
@@ -430749,7 +431185,7 @@ async function loadSessionMemoryTemplate() {
430749
431185
  }
430750
431186
  }
430751
431187
  async function loadSessionMemoryPrompt() {
430752
- const promptPath = join163(getAtlasConfigHomeDir3(), "session-memory", "config", "prompt.md");
431188
+ const promptPath = join164(getAtlasConfigHomeDir3(), "session-memory", "config", "prompt.md");
430753
431189
  try {
430754
431190
  return await readFile61(promptPath, { encoding: "utf-8" });
430755
431191
  } catch (e) {
@@ -431355,7 +431791,7 @@ var init_contextHostWiring = __esm(() => {
431355
431791
 
431356
431792
  // src/tui/core/executor/AscendFreshnessPort.ts
431357
431793
  import { readFileSync as readFileSync22, existsSync as existsSync12 } from "fs";
431358
- import { join as join164, dirname as dirname77 } from "path";
431794
+ import { join as join165, dirname as dirname77 } from "path";
431359
431795
 
431360
431796
  class DefaultAscendFreshnessPort {
431361
431797
  injectedCache;
@@ -431369,8 +431805,8 @@ class DefaultAscendFreshnessPort {
431369
431805
  return env;
431370
431806
  let dir = dirname77(new URL(import.meta.url).pathname);
431371
431807
  for (let i = 0;i < MAX_WALK_UP; i++) {
431372
- if (existsSync12(join164(dir, "package.json")))
431373
- return join164(dir, ".freshness-cache.json");
431808
+ if (existsSync12(join165(dir, "package.json")))
431809
+ return join165(dir, ".freshness-cache.json");
431374
431810
  const parent = dirname77(dir);
431375
431811
  if (parent === dir)
431376
431812
  break;
@@ -431845,10 +432281,10 @@ import {
431845
432281
  dirname as dirname78,
431846
432282
  extname as extname17,
431847
432283
  isAbsolute as isAbsolute33,
431848
- join as join165,
432284
+ join as join166,
431849
432285
  parse as parse13,
431850
432286
  relative as relative29,
431851
- sep as sep36
432287
+ sep as sep37
431852
432288
  } from "path";
431853
432289
  function pathInOriginalCwd(path) {
431854
432290
  return pathInWorkingPath2(path, getOriginalCwd());
@@ -432085,7 +432521,7 @@ async function processMdRules({
432085
432521
  throw e;
432086
432522
  }
432087
432523
  for (const entry of entries) {
432088
- const entryPath = join165(rulesDir, entry.name);
432524
+ const entryPath = join166(rulesDir, entry.name);
432089
432525
  const { resolvedPath: resolvedEntryPath, isSymlink } = safeResolvePath3(fs, entryPath);
432090
432526
  const stats = isSymlink ? await fs.stat(resolvedEntryPath) : null;
432091
432527
  const isDirectory = stats ? stats.isDirectory() : entry.isDirectory();
@@ -432153,14 +432589,14 @@ async function getMemoryFilesForNestedDirectory(dir, targetPath, processedPaths)
432153
432589
  if (isSettingSourceEnabled2("projectSettings")) {
432154
432590
  const projectPath = findMemoryFile(dir);
432155
432591
  result.push(...await processMemoryFile(projectPath, "Project", processedPaths, false));
432156
- const dotClaudePath = findMemoryFile(join165(dir, getConfigDirName2()));
432592
+ const dotClaudePath = findMemoryFile(join166(dir, getConfigDirName2()));
432157
432593
  result.push(...await processMemoryFile(dotClaudePath, "Project", processedPaths, false));
432158
432594
  }
432159
432595
  if (isSettingSourceEnabled2("localSettings")) {
432160
- const localPath = join165(dir, "CLAUDE.local.md");
432596
+ const localPath = join166(dir, "CLAUDE.local.md");
432161
432597
  result.push(...await processMemoryFile(localPath, "Local", processedPaths, false));
432162
432598
  }
432163
- const rulesDir = join165(dir, getConfigDirName2(), "rules");
432599
+ const rulesDir = join166(dir, getConfigDirName2(), "rules");
432164
432600
  const unconditionalProcessedPaths = new Set(processedPaths);
432165
432601
  result.push(...await processMdRules({
432166
432602
  rulesDir,
@@ -432176,7 +432612,7 @@ async function getMemoryFilesForNestedDirectory(dir, targetPath, processedPaths)
432176
432612
  return result;
432177
432613
  }
432178
432614
  async function getConditionalRulesForCwdLevelDirectory(dir, targetPath, processedPaths) {
432179
- const rulesDir = join165(dir, getConfigDirName2(), "rules");
432615
+ const rulesDir = join166(dir, getConfigDirName2(), "rules");
432180
432616
  return processConditionedMdRules(targetPath, rulesDir, "Project", processedPaths, false);
432181
432617
  }
432182
432618
  async function processConditionedMdRules(targetPath, rulesDir, type, processedPaths, includeExternal) {
@@ -432432,9 +432868,9 @@ var init_memoryFiles = __esm(() => {
432432
432868
  if (isSettingSourceEnabled2("projectSettings") && !skipProject) {
432433
432869
  const projectPath = findMemoryFile(dir);
432434
432870
  result.push(...await processMemoryFile(projectPath, "Project", processedPaths, includeExternal));
432435
- const dotClaudePath = findMemoryFile(join165(dir, getConfigDirName2()));
432871
+ const dotClaudePath = findMemoryFile(join166(dir, getConfigDirName2()));
432436
432872
  result.push(...await processMemoryFile(dotClaudePath, "Project", processedPaths, includeExternal));
432437
- const rulesDir = join165(dir, getConfigDirName2(), "rules");
432873
+ const rulesDir = join166(dir, getConfigDirName2(), "rules");
432438
432874
  result.push(...await processMdRules({
432439
432875
  rulesDir,
432440
432876
  type: "Project",
@@ -432444,7 +432880,7 @@ var init_memoryFiles = __esm(() => {
432444
432880
  }));
432445
432881
  }
432446
432882
  if (isSettingSourceEnabled2("localSettings")) {
432447
- const localPath = join165(dir, "CLAUDE.local.md");
432883
+ const localPath = join166(dir, "CLAUDE.local.md");
432448
432884
  result.push(...await processMemoryFile(localPath, "Local", processedPaths, includeExternal));
432449
432885
  }
432450
432886
  }
@@ -432453,9 +432889,9 @@ var init_memoryFiles = __esm(() => {
432453
432889
  for (const dir of additionalDirs) {
432454
432890
  const projectPath = findMemoryFile(dir);
432455
432891
  result.push(...await processMemoryFile(projectPath, "Project", processedPaths, includeExternal));
432456
- const dotClaudePath = findMemoryFile(join165(dir, getConfigDirName2()));
432892
+ const dotClaudePath = findMemoryFile(join166(dir, getConfigDirName2()));
432457
432893
  result.push(...await processMemoryFile(dotClaudePath, "Project", processedPaths, includeExternal));
432458
- const rulesDir = join165(dir, getConfigDirName2(), "rules");
432894
+ const rulesDir = join166(dir, getConfigDirName2(), "rules");
432459
432895
  result.push(...await processMdRules({
432460
432896
  rulesDir,
432461
432897
  type: "Project",
@@ -440980,20 +441416,20 @@ var init_AutoModeConfirm = __esm(() => {
440980
441416
 
440981
441417
  // src/tui/components/permissions/FilePermissionDialog/permissionOptions.tsx
440982
441418
  import { homedir as homedir39 } from "os";
440983
- import { basename as basename54, join as join166, sep as sep37 } from "path";
441419
+ import { basename as basename54, join as join167, sep as sep38 } from "path";
440984
441420
  function isInClaudeFolder(filePath) {
440985
441421
  const absolutePath = expandPath2(filePath);
440986
441422
  const claudeFolderPath = expandPath2(`${getOriginalCwd()}/${getConfigDirName2()}`);
440987
441423
  const normalizedAbsolutePath = normalizeCaseForComparison2(absolutePath);
440988
441424
  const normalizedClaudeFolderPath = normalizeCaseForComparison2(claudeFolderPath);
440989
- return normalizedAbsolutePath.startsWith(normalizedClaudeFolderPath + sep37.toLowerCase()) || normalizedAbsolutePath.startsWith(normalizedClaudeFolderPath + "/");
441425
+ return normalizedAbsolutePath.startsWith(normalizedClaudeFolderPath + sep38.toLowerCase()) || normalizedAbsolutePath.startsWith(normalizedClaudeFolderPath + "/");
440990
441426
  }
440991
441427
  function isInGlobalClaudeFolder(filePath) {
440992
441428
  const absolutePath = expandPath2(filePath);
440993
- const globalClaudeFolderPath = join166(homedir39(), getConfigDirName2());
441429
+ const globalClaudeFolderPath = join167(homedir39(), getConfigDirName2());
440994
441430
  const normalizedAbsolutePath = normalizeCaseForComparison2(absolutePath);
440995
441431
  const normalizedGlobalClaudeFolderPath = normalizeCaseForComparison2(globalClaudeFolderPath);
440996
- return normalizedAbsolutePath.startsWith(normalizedGlobalClaudeFolderPath + sep37.toLowerCase()) || normalizedAbsolutePath.startsWith(normalizedGlobalClaudeFolderPath + "/");
441432
+ return normalizedAbsolutePath.startsWith(normalizedGlobalClaudeFolderPath + sep38.toLowerCase()) || normalizedAbsolutePath.startsWith(normalizedGlobalClaudeFolderPath + "/");
440997
441433
  }
440998
441434
  function getFilePermissionOptions({
440999
441435
  filePath,
@@ -441974,7 +442410,7 @@ var init_useShellPermissionFeedback = __esm(() => {
441974
442410
  });
441975
442411
 
441976
442412
  // src/tui/components/permissions/shellPermissionHelpers.tsx
441977
- import { basename as basename56, sep as sep38 } from "path";
442413
+ import { basename as basename56, sep as sep39 } from "path";
441978
442414
  function commandListDisplay(commands) {
441979
442415
  switch (commands.length) {
441980
442416
  case 0:
@@ -442033,7 +442469,7 @@ function formatPathList(paths) {
442033
442469
  bold: true,
442034
442470
  children: names[0]
442035
442471
  }, undefined, false, undefined, this),
442036
- sep38
442472
+ sep39
442037
442473
  ]
442038
442474
  }, undefined, true, undefined, this);
442039
442475
  }
@@ -442044,13 +442480,13 @@ function formatPathList(paths) {
442044
442480
  bold: true,
442045
442481
  children: names[0]
442046
442482
  }, undefined, false, undefined, this),
442047
- sep38,
442483
+ sep39,
442048
442484
  " and ",
442049
442485
  /* @__PURE__ */ jsx_dev_runtime337.jsxDEV(ThemedText, {
442050
442486
  bold: true,
442051
442487
  children: names[1]
442052
442488
  }, undefined, false, undefined, this),
442053
- sep38
442489
+ sep39
442054
442490
  ]
442055
442491
  }, undefined, true, undefined, this);
442056
442492
  }
@@ -442060,13 +442496,13 @@ function formatPathList(paths) {
442060
442496
  bold: true,
442061
442497
  children: names[0]
442062
442498
  }, undefined, false, undefined, this),
442063
- sep38,
442499
+ sep39,
442064
442500
  ", ",
442065
442501
  /* @__PURE__ */ jsx_dev_runtime337.jsxDEV(ThemedText, {
442066
442502
  bold: true,
442067
442503
  children: names[1]
442068
442504
  }, undefined, false, undefined, this),
442069
- sep38,
442505
+ sep39,
442070
442506
  " and ",
442071
442507
  paths.length - 2,
442072
442508
  " more"
@@ -442099,7 +442535,7 @@ function generateShellSuggestionsLabel(suggestions, shellToolName, commandTransf
442099
442535
  bold: true,
442100
442536
  children: dirName
442101
442537
  }, undefined, false, undefined, this),
442102
- sep38,
442538
+ sep39,
442103
442539
  " from this project"
442104
442540
  ]
442105
442541
  }, undefined, true, undefined, this);
@@ -442123,7 +442559,7 @@ function generateShellSuggestionsLabel(suggestions, shellToolName, commandTransf
442123
442559
  bold: true,
442124
442560
  children: dirName
442125
442561
  }, undefined, false, undefined, this),
442126
- sep38,
442562
+ sep39,
442127
442563
  " from this project"
442128
442564
  ]
442129
442565
  }, undefined, true, undefined, this);
@@ -458718,10 +459154,10 @@ var init_segments = __esm(() => {
458718
459154
 
458719
459155
  // src/tui/components/StatusLine/segments/statusLineConfig.ts
458720
459156
  import { readFileSync as readFileSync23, existsSync as existsSync13, writeFileSync as writeFileSync9, renameSync as renameSync3, mkdirSync as mkdirSync9 } from "fs";
458721
- import { join as join167 } from "path";
459157
+ import { join as join168 } from "path";
458722
459158
  import { homedir as homedir41 } from "os";
458723
459159
  function getStatusLineJsonPath() {
458724
- return join167(homedir41(), getConfigDirName2(), "statusline.json");
459160
+ return join168(homedir41(), getConfigDirName2(), "statusline.json");
458725
459161
  }
458726
459162
  function getDefaultConfig() {
458727
459163
  return {
@@ -464146,7 +464582,7 @@ var init_autoDream = __esm(() => {
464146
464582
  });
464147
464583
 
464148
464584
  // src/tui/utils/cleanup.ts
464149
- import { join as join168 } from "path";
464585
+ import { join as join169 } from "path";
464150
464586
  function getCutoffDate() {
464151
464587
  const settings = getSettings_DEPRECATED() || {};
464152
464588
  const cleanupPeriodDays = settings.cleanupPeriodDays ?? DEFAULT_CLEANUP_PERIOD_DAYS;
@@ -464171,7 +464607,7 @@ async function cleanupOldFilesInDirectory(dirPath, cutoffDate, isMessagePath) {
464171
464607
  try {
464172
464608
  const timestamp = convertFileNameToDate(file.name);
464173
464609
  if (timestamp < cutoffDate) {
464174
- await getFsImplementation2().unlink(join168(dirPath, file.name));
464610
+ await getFsImplementation2().unlink(join169(dirPath, file.name));
464175
464611
  if (isMessagePath) {
464176
464612
  result.messages++;
464177
464613
  } else {
@@ -464202,7 +464638,7 @@ async function cleanupOldMessageFiles() {
464202
464638
  } catch {
464203
464639
  return result;
464204
464640
  }
464205
- const mcpLogDirs = dirents.filter((dirent) => dirent.isDirectory() && dirent.name.startsWith("mcp-logs-")).map((dirent) => join168(baseCachePath, dirent.name));
464641
+ const mcpLogDirs = dirents.filter((dirent) => dirent.isDirectory() && dirent.name.startsWith("mcp-logs-")).map((dirent) => join169(baseCachePath, dirent.name));
464206
464642
  for (const mcpLogDir of mcpLogDirs) {
464207
464643
  result = addCleanupResults(result, await cleanupOldFilesInDirectory(mcpLogDir, cutoffDate, true));
464208
464644
  await tryRmdir(mcpLogDir, fsImpl);
@@ -464241,7 +464677,7 @@ async function cleanupOldSessionFiles() {
464241
464677
  for (const projectDirent of projectDirents) {
464242
464678
  if (!projectDirent.isDirectory())
464243
464679
  continue;
464244
- const projectDir = join168(projectsDir, projectDirent.name);
464680
+ const projectDir = join169(projectsDir, projectDirent.name);
464245
464681
  let entries;
464246
464682
  try {
464247
464683
  entries = await fsImpl.readdir(projectDir);
@@ -464255,15 +464691,15 @@ async function cleanupOldSessionFiles() {
464255
464691
  continue;
464256
464692
  }
464257
464693
  try {
464258
- if (await unlinkIfOld(join168(projectDir, entry.name), cutoffDate, fsImpl)) {
464694
+ if (await unlinkIfOld(join169(projectDir, entry.name), cutoffDate, fsImpl)) {
464259
464695
  result.messages++;
464260
464696
  }
464261
464697
  } catch {
464262
464698
  result.errors++;
464263
464699
  }
464264
464700
  } else if (entry.isDirectory()) {
464265
- const sessionDir = join168(projectDir, entry.name);
464266
- const toolResultsDir = join168(sessionDir, TOOL_RESULTS_SUBDIR3);
464701
+ const sessionDir = join169(projectDir, entry.name);
464702
+ const toolResultsDir = join169(sessionDir, TOOL_RESULTS_SUBDIR3);
464267
464703
  let toolDirs;
464268
464704
  try {
464269
464705
  toolDirs = await fsImpl.readdir(toolResultsDir);
@@ -464274,14 +464710,14 @@ async function cleanupOldSessionFiles() {
464274
464710
  for (const toolEntry of toolDirs) {
464275
464711
  if (toolEntry.isFile()) {
464276
464712
  try {
464277
- if (await unlinkIfOld(join168(toolResultsDir, toolEntry.name), cutoffDate, fsImpl)) {
464713
+ if (await unlinkIfOld(join169(toolResultsDir, toolEntry.name), cutoffDate, fsImpl)) {
464278
464714
  result.messages++;
464279
464715
  }
464280
464716
  } catch {
464281
464717
  result.errors++;
464282
464718
  }
464283
464719
  } else if (toolEntry.isDirectory()) {
464284
- const toolDirPath = join168(toolResultsDir, toolEntry.name);
464720
+ const toolDirPath = join169(toolResultsDir, toolEntry.name);
464285
464721
  let toolFiles;
464286
464722
  try {
464287
464723
  toolFiles = await fsImpl.readdir(toolDirPath);
@@ -464292,7 +464728,7 @@ async function cleanupOldSessionFiles() {
464292
464728
  if (!tf.isFile())
464293
464729
  continue;
464294
464730
  try {
464295
- if (await unlinkIfOld(join168(toolDirPath, tf.name), cutoffDate, fsImpl)) {
464731
+ if (await unlinkIfOld(join169(toolDirPath, tf.name), cutoffDate, fsImpl)) {
464296
464732
  result.messages++;
464297
464733
  }
464298
464734
  } catch {
@@ -464324,7 +464760,7 @@ async function cleanupSingleDirectory(dirPath, extension, removeEmptyDir = true)
464324
464760
  if (!dirent.isFile() || !dirent.name.endsWith(extension))
464325
464761
  continue;
464326
464762
  try {
464327
- if (await unlinkIfOld(join168(dirPath, dirent.name), cutoffDate, fsImpl)) {
464763
+ if (await unlinkIfOld(join169(dirPath, dirent.name), cutoffDate, fsImpl)) {
464328
464764
  result.messages++;
464329
464765
  }
464330
464766
  } catch {
@@ -464337,7 +464773,7 @@ async function cleanupSingleDirectory(dirPath, extension, removeEmptyDir = true)
464337
464773
  return result;
464338
464774
  }
464339
464775
  function cleanupOldPlanFiles() {
464340
- const plansDir = join168(getAtlasConfigHomeDir3(), "plans");
464776
+ const plansDir = join169(getAtlasConfigHomeDir3(), "plans");
464341
464777
  return cleanupSingleDirectory(plansDir, ".md");
464342
464778
  }
464343
464779
  async function cleanupOldFileHistoryBackups() {
@@ -464346,14 +464782,14 @@ async function cleanupOldFileHistoryBackups() {
464346
464782
  const fsImpl = getFsImplementation2();
464347
464783
  try {
464348
464784
  const configDir = getAtlasConfigHomeDir3();
464349
- const fileHistoryStorageDir = join168(configDir, "file-history");
464785
+ const fileHistoryStorageDir = join169(configDir, "file-history");
464350
464786
  let dirents;
464351
464787
  try {
464352
464788
  dirents = await fsImpl.readdir(fileHistoryStorageDir);
464353
464789
  } catch {
464354
464790
  return result;
464355
464791
  }
464356
- const fileHistorySessionsDirs = dirents.filter((dirent) => dirent.isDirectory()).map((dirent) => join168(fileHistoryStorageDir, dirent.name));
464792
+ const fileHistorySessionsDirs = dirents.filter((dirent) => dirent.isDirectory()).map((dirent) => join169(fileHistoryStorageDir, dirent.name));
464357
464793
  await Promise.all(fileHistorySessionsDirs.map(async (fileHistorySessionDir) => {
464358
464794
  try {
464359
464795
  const stats = await fsImpl.stat(fileHistorySessionDir);
@@ -464380,14 +464816,14 @@ async function cleanupOldSessionEnvDirs() {
464380
464816
  const fsImpl = getFsImplementation2();
464381
464817
  try {
464382
464818
  const configDir = getAtlasConfigHomeDir3();
464383
- const sessionEnvBaseDir = join168(configDir, "session-env");
464819
+ const sessionEnvBaseDir = join169(configDir, "session-env");
464384
464820
  let dirents;
464385
464821
  try {
464386
464822
  dirents = await fsImpl.readdir(sessionEnvBaseDir);
464387
464823
  } catch {
464388
464824
  return result;
464389
464825
  }
464390
- const sessionEnvDirs = dirents.filter((dirent) => dirent.isDirectory()).map((dirent) => join168(sessionEnvBaseDir, dirent.name));
464826
+ const sessionEnvDirs = dirents.filter((dirent) => dirent.isDirectory()).map((dirent) => join169(sessionEnvBaseDir, dirent.name));
464391
464827
  for (const sessionEnvDir of sessionEnvDirs) {
464392
464828
  try {
464393
464829
  const stats = await fsImpl.stat(sessionEnvDir);
@@ -464409,7 +464845,7 @@ async function cleanupOldDebugLogs() {
464409
464845
  const cutoffDate = getCutoffDate();
464410
464846
  const result = { messages: 0, errors: 0 };
464411
464847
  const fsImpl = getFsImplementation2();
464412
- const debugDir = join168(getAtlasConfigHomeDir3(), "debug");
464848
+ const debugDir = join169(getAtlasConfigHomeDir3(), "debug");
464413
464849
  let dirents;
464414
464850
  try {
464415
464851
  dirents = await fsImpl.readdir(debugDir);
@@ -464421,7 +464857,7 @@ async function cleanupOldDebugLogs() {
464421
464857
  continue;
464422
464858
  }
464423
464859
  try {
464424
- if (await unlinkIfOld(join168(debugDir, dirent.name), cutoffDate, fsImpl)) {
464860
+ if (await unlinkIfOld(join169(debugDir, dirent.name), cutoffDate, fsImpl)) {
464425
464861
  result.messages++;
464426
464862
  }
464427
464863
  } catch {
@@ -465867,9 +466303,9 @@ var init_coordinatorHandler = __esm(() => {
465867
466303
 
465868
466304
  // src/tui/utils/permissions/sessionPermissionRules.ts
465869
466305
  import { mkdir as mkdir53, readFile as readFile62, rename as rename11, writeFile as writeFile48 } from "fs/promises";
465870
- import { dirname as dirname80, join as join170 } from "path";
466306
+ import { dirname as dirname80, join as join171 } from "path";
465871
466307
  function sessionRulesPath(sessionId, projectDir) {
465872
- return join170(projectDir, `${sessionId}${SESSION_RULES_FILE_SUFFIX}`);
466308
+ return join171(projectDir, `${sessionId}${SESSION_RULES_FILE_SUFFIX}`);
465873
466309
  }
465874
466310
  function parseSessionRulesJson(json) {
465875
466311
  if (json.length > MAX_SESSION_RULES_BYTES)
@@ -467957,171 +468393,6 @@ var init_useMergedCommands = __esm(() => {
467957
468393
  import_react250 = __toESM(require_react(), 1);
467958
468394
  });
467959
468395
 
467960
- // src/tui/utils/skills/skillChangeDetector.ts
467961
- import * as platformPath2 from "path";
467962
- async function initialize2() {
467963
- if (initialized5 || disposed3)
467964
- return;
467965
- initialized5 = true;
467966
- if (!dynamicSkillsCallbackRegistered) {
467967
- dynamicSkillsCallbackRegistered = true;
467968
- onDynamicSkillsLoaded2(() => {
467969
- clearCommandMemoizationCaches2();
467970
- skillsChanged.emit();
467971
- });
467972
- }
467973
- const paths = await getWatchablePaths();
467974
- if (paths.length === 0)
467975
- return;
467976
- logForDebugging3(`Watching for changes in skill/command directories: ${paths.join(", ")}...`);
467977
- watcher4 = chokidar_default.watch(paths, {
467978
- persistent: true,
467979
- ignoreInitial: true,
467980
- depth: 2,
467981
- awaitWriteFinish: {
467982
- stabilityThreshold: testOverrides2?.stabilityThreshold ?? FILE_STABILITY_THRESHOLD_MS3,
467983
- pollInterval: testOverrides2?.pollInterval ?? FILE_STABILITY_POLL_INTERVAL_MS3
467984
- },
467985
- ignored: (path, stats) => {
467986
- if (stats && !stats.isFile() && !stats.isDirectory())
467987
- return true;
467988
- return path.split(platformPath2.sep).some((dir) => dir === ".git");
467989
- },
467990
- ignorePermissionErrors: true,
467991
- usePolling: USE_POLLING,
467992
- interval: testOverrides2?.chokidarInterval ?? POLLING_INTERVAL_MS,
467993
- atomic: true
467994
- });
467995
- watcher4.on("add", handleChange3);
467996
- watcher4.on("change", handleChange3);
467997
- watcher4.on("unlink", handleChange3);
467998
- unregisterCleanup3 = registerCleanup3(async () => {
467999
- await dispose3();
468000
- });
468001
- }
468002
- function dispose3() {
468003
- disposed3 = true;
468004
- if (unregisterCleanup3) {
468005
- unregisterCleanup3();
468006
- unregisterCleanup3 = null;
468007
- }
468008
- let closePromise = Promise.resolve();
468009
- if (watcher4) {
468010
- closePromise = watcher4.close();
468011
- watcher4 = null;
468012
- }
468013
- if (reloadTimer) {
468014
- clearTimeout(reloadTimer);
468015
- reloadTimer = null;
468016
- }
468017
- pendingChangedPaths.clear();
468018
- skillsChanged.clear();
468019
- return closePromise;
468020
- }
468021
- async function getWatchablePaths() {
468022
- const fs = getFsImplementation2();
468023
- const paths = [];
468024
- const userSkillsPath = getSkillsPath2("userSettings", "skills");
468025
- if (userSkillsPath) {
468026
- try {
468027
- await fs.stat(userSkillsPath);
468028
- paths.push(userSkillsPath);
468029
- } catch {}
468030
- }
468031
- const userCommandsPath = getSkillsPath2("userSettings", "commands");
468032
- if (userCommandsPath) {
468033
- try {
468034
- await fs.stat(userCommandsPath);
468035
- paths.push(userCommandsPath);
468036
- } catch {}
468037
- }
468038
- const projectSkillsPath = getSkillsPath2("projectSettings", "skills");
468039
- if (projectSkillsPath) {
468040
- try {
468041
- const absolutePath = platformPath2.resolve(projectSkillsPath);
468042
- await fs.stat(absolutePath);
468043
- paths.push(absolutePath);
468044
- } catch {}
468045
- }
468046
- const projectCommandsPath = getSkillsPath2("projectSettings", "commands");
468047
- if (projectCommandsPath) {
468048
- try {
468049
- const absolutePath = platformPath2.resolve(projectCommandsPath);
468050
- await fs.stat(absolutePath);
468051
- paths.push(absolutePath);
468052
- } catch {}
468053
- }
468054
- for (const dir of getAdditionalDirectoriesForClaudeMd()) {
468055
- const additionalSkillsPath = platformPath2.join(dir, getConfigDirName2(), "skills");
468056
- try {
468057
- await fs.stat(additionalSkillsPath);
468058
- paths.push(additionalSkillsPath);
468059
- } catch {}
468060
- }
468061
- return paths;
468062
- }
468063
- function handleChange3(path) {
468064
- logForDebugging3(`Detected skill change: ${path}`);
468065
- scheduleReload(path);
468066
- }
468067
- function scheduleReload(changedPath) {
468068
- pendingChangedPaths.add(changedPath);
468069
- if (reloadTimer)
468070
- clearTimeout(reloadTimer);
468071
- reloadTimer = setTimeout(async () => {
468072
- reloadTimer = null;
468073
- const paths = [...pendingChangedPaths];
468074
- pendingChangedPaths.clear();
468075
- const results = await executeConfigChangeHooks("skills", paths[0]);
468076
- if (hasBlockingResult(results)) {
468077
- logForDebugging3(`ConfigChange hook blocked skill reload (${paths.length} paths)`);
468078
- return;
468079
- }
468080
- clearSkillCaches2();
468081
- clearCommandsCache2();
468082
- resetSentSkillNames();
468083
- skillsChanged.emit();
468084
- }, testOverrides2?.reloadDebounce ?? RELOAD_DEBOUNCE_MS);
468085
- }
468086
- async function resetForTesting2(overrides) {
468087
- if (watcher4) {
468088
- await watcher4.close();
468089
- watcher4 = null;
468090
- }
468091
- if (reloadTimer) {
468092
- clearTimeout(reloadTimer);
468093
- reloadTimer = null;
468094
- }
468095
- pendingChangedPaths.clear();
468096
- skillsChanged.clear();
468097
- initialized5 = false;
468098
- disposed3 = false;
468099
- testOverrides2 = overrides ?? null;
468100
- }
468101
- var FILE_STABILITY_THRESHOLD_MS3 = 1000, FILE_STABILITY_POLL_INTERVAL_MS3 = 500, RELOAD_DEBOUNCE_MS = 300, POLLING_INTERVAL_MS = 2000, USE_POLLING, watcher4 = null, reloadTimer = null, pendingChangedPaths, initialized5 = false, disposed3 = false, dynamicSkillsCallbackRegistered = false, unregisterCleanup3 = null, skillsChanged, testOverrides2 = null, subscribe3, skillChangeDetector;
468102
- var init_skillChangeDetector = __esm(() => {
468103
- init_chokidar();
468104
- init_configDir();
468105
- init_bootstrapState();
468106
- init_commands5();
468107
- init_loadSkillsDir2();
468108
- init_attachments();
468109
- init_cleanupRegistry3();
468110
- init_debug();
468111
- init_fsOperations();
468112
- init_hooks7();
468113
- USE_POLLING = typeof Bun !== "undefined";
468114
- pendingChangedPaths = new Set;
468115
- skillsChanged = createSignal3();
468116
- subscribe3 = skillsChanged.subscribe;
468117
- skillChangeDetector = {
468118
- initialize: initialize2,
468119
- dispose: dispose3,
468120
- subscribe: subscribe3,
468121
- resetForTesting: resetForTesting2
468122
- };
468123
- });
468124
-
468125
468396
  // src/tui/hooks/useSkillsChange.ts
468126
468397
  function useSkillsChange(cwd, onCommandsChange) {
468127
468398
  const handleChange = import_react251.useCallback(async () => {
@@ -489998,24 +490269,25 @@ function autoModeConfigHandler2() {
489998
490269
  const defaults = getDefaultExternalAutoModeRules2();
489999
490270
  writeRules2({
490000
490271
  allow: config?.allow?.length ? config.allow : defaults.allow,
490272
+ hard_deny: config?.hard_deny?.length ? config.hard_deny : defaults.hard_deny,
490001
490273
  soft_deny: config?.soft_deny?.length ? config.soft_deny : defaults.soft_deny,
490002
490274
  environment: config?.environment?.length ? config.environment : defaults.environment
490003
490275
  });
490004
490276
  }
490005
490277
  async function autoModeCritiqueHandler2(options) {
490006
490278
  const config = getAutoModeConfig2();
490007
- const hasCustomRules = (config?.allow?.length ?? 0) > 0 || (config?.soft_deny?.length ?? 0) > 0 || (config?.environment?.length ?? 0) > 0;
490279
+ const hasCustomRules = (config?.allow?.length ?? 0) > 0 || (config?.hard_deny?.length ?? 0) > 0 || (config?.soft_deny?.length ?? 0) > 0 || (config?.environment?.length ?? 0) > 0;
490008
490280
  if (!hasCustomRules) {
490009
490281
  process.stdout.write(`No custom auto mode rules found.
490010
490282
 
490011
- ` + `Add rules to your settings file under autoMode.{allow, soft_deny, environment}.
490283
+ ` + `Add rules to your settings file under autoMode.{allow, hard_deny, soft_deny, environment}.
490012
490284
  ` + "Run `claude auto-mode defaults` to see the default rules for reference.\n");
490013
490285
  return;
490014
490286
  }
490015
490287
  const model = options.model ? parseUserSpecifiedModel2(options.model) : getMainLoopModel();
490016
490288
  const defaults = getDefaultExternalAutoModeRules2();
490017
490289
  const classifierPrompt = buildDefaultExternalSystemPrompt2();
490018
- const userRulesSummary = formatRulesForCritique2("allow", config?.allow ?? [], defaults.allow) + formatRulesForCritique2("soft_deny", config?.soft_deny ?? [], defaults.soft_deny) + formatRulesForCritique2("environment", config?.environment ?? [], defaults.environment);
490290
+ const userRulesSummary = formatRulesForCritique2("allow", config?.allow ?? [], defaults.allow) + formatRulesForCritique2("hard_deny", config?.hard_deny ?? [], defaults.hard_deny) + formatRulesForCritique2("soft_deny", config?.soft_deny ?? [], defaults.soft_deny) + formatRulesForCritique2("environment", config?.environment ?? [], defaults.environment);
490019
490291
  process.stdout.write(`Analyzing your auto mode rules…
490020
490292
 
490021
490293
  `);
@@ -490084,9 +490356,10 @@ var init_autoMode3 = __esm(() => {
490084
490356
  init_slowOperations();
490085
490357
  CRITIQUE_SYSTEM_PROMPT2 = `You are an expert reviewer of auto mode classifier rules for Atlas.
490086
490358
  ` + `
490087
- ` + 'Atlas has an "auto mode" that uses an AI classifier to decide whether ' + "tool calls should be auto-approved or require user confirmation. Users can " + `write custom rules in three categories:
490359
+ ` + 'Atlas has an "auto mode" that uses an AI classifier to decide whether ' + "tool calls should be auto-approved or require user confirmation. Users can " + `write custom rules in four categories:
490088
490360
  ` + `
490089
490361
  ` + `- **allow**: Actions the classifier should auto-approve
490362
+ ` + `- **hard_deny**: Actions that are blocked unconditionally (user intent does not clear these)
490090
490363
  ` + `- **soft_deny**: Actions the classifier should block (require user confirmation)
490091
490364
  ` + `- **environment**: Context about the user's setup that helps the classifier make decisions
490092
490365
  ` + `
@@ -490941,7 +491214,7 @@ async function run() {
490941
491214
  throw new Error("--task-budget must be a positive integer");
490942
491215
  }
490943
491216
  return tokens;
490944
- }).hideHelp()).option("--replay-user-messages", "Re-emit user messages from stdin back on stdout for acknowledgment (only works with --input-format=stream-json and --output-format=stream-json)", () => true).addOption(new Option("--enable-auth-status", "Enable auth status messages in SDK mode").default(false).hideHelp()).option("--allowedTools, --allowed-tools <tools...>", 'Comma or space-separated list of tool names to allow (e.g. "Bash(git:*) Edit")').option("--tools <tools...>", 'Specify the list of available tools from the built-in set. Use "" to disable all tools, "default" to use all tools, or specify tool names (e.g. "Bash,Edit,Read").').option("--disallowedTools, --disallowed-tools <tools...>", 'Comma or space-separated list of tool names to deny (e.g. "Bash(git:*) Edit")').option("--mcp-config <configs...>", "Load MCP servers from JSON files or strings (space-separated)").addOption(new Option("--permission-prompt-tool <tool>", "MCP tool to use for permission prompts (only works with --print)").argParser(String).hideHelp()).addOption(new Option("--system-prompt <prompt>", "System prompt to use for the session").argParser(String)).addOption(new Option("--system-prompt-file <file>", "Read system prompt from a file").argParser(String).hideHelp()).addOption(new Option("--append-system-prompt <prompt>", "Append a system prompt to the default system prompt").argParser(String)).addOption(new Option("--append-system-prompt-file <file>", "Read system prompt from a file and append to the default system prompt").argParser(String).hideHelp()).addOption(new Option("--permission-mode <mode>", "Permission mode to use for the session").argParser(String).choices(PERMISSION_MODES2)).option("-c, --continue", "Continue the most recent conversation in the current directory", () => true).option("-r, --resume [value]", "Resume a conversation by session ID, or open interactive picker with optional search term", (value) => value || true).option("--fork-session", "When resuming, create a new session ID instead of reusing the original (use with --resume or --continue)", () => true).addOption(new Option("--prefill <text>", "Pre-fill the prompt input with text without submitting it").hideHelp()).addOption(new Option("--deep-link-origin", "Signal that this session was launched from a deep link").hideHelp()).addOption(new Option("--deep-link-repo <slug>", "Repo slug the deep link ?repo= parameter resolved to the current cwd").hideHelp()).addOption(new Option("--deep-link-last-fetch <ms>", "FETCH_HEAD mtime in epoch ms, precomputed by the deep link trampoline").argParser((v) => {
491217
+ }).hideHelp()).option("--replay-user-messages", "Re-emit user messages from stdin back on stdout for acknowledgment (only works with --input-format=stream-json and --output-format=stream-json)", () => true).addOption(new Option("--enable-auth-status", "Enable auth status messages in SDK mode").default(false).hideHelp()).option("--allowedTools, --allowed-tools <tools...>", 'Comma or space-separated list of tool names to allow (e.g. "Bash(git:*) Edit")').option("--tools <tools...>", 'Specify the list of available tools from the built-in set. Use "" to disable all tools, "default" to use all tools, or specify tool names (e.g. "Bash,Edit,Read").').option("--disallowedTools, --disallowed-tools <tools...>", 'Comma or space-separated list of tool names to deny (e.g. "Bash(git:*) Edit")').option("--mcp-config <configs...>", "Load MCP servers from JSON files or strings (space-separated)").addOption(new Option("--permission-prompt-tool <tool>", "MCP tool to use for permission prompts (only works with --print)").argParser(String).hideHelp()).addOption(new Option("--system-prompt <prompt>", "System prompt to use for the session").argParser(String)).addOption(new Option("--system-prompt-file <file>", "Read system prompt from a file").argParser(String).hideHelp()).addOption(new Option("--append-system-prompt <prompt>", "Append a system prompt to the default system prompt").argParser(String)).addOption(new Option("--append-system-prompt-file <file>", "Read system prompt from a file and append to the default system prompt").argParser(String).hideHelp()).addOption(new Option("--permission-mode <mode>", "Permission mode to use for the session").argParser(String).choices(PERMISSION_MODES2)).addOption(new Option("--permission-prompts <mode>", "Permission prompt policy; 'none' auto-denies prompts that would otherwise ask").argParser(String).choices(["none"])).option("-c, --continue", "Continue the most recent conversation in the current directory", () => true).option("-r, --resume [value]", "Resume a conversation by session ID, or open interactive picker with optional search term", (value) => value || true).option("--fork-session", "When resuming, create a new session ID instead of reusing the original (use with --resume or --continue)", () => true).addOption(new Option("--prefill <text>", "Pre-fill the prompt input with text without submitting it").hideHelp()).addOption(new Option("--deep-link-origin", "Signal that this session was launched from a deep link").hideHelp()).addOption(new Option("--deep-link-repo <slug>", "Repo slug the deep link ?repo= parameter resolved to the current cwd").hideHelp()).addOption(new Option("--deep-link-last-fetch <ms>", "FETCH_HEAD mtime in epoch ms, precomputed by the deep link trampoline").argParser((v) => {
490945
491218
  const n = Number(v);
490946
491219
  return Number.isFinite(n) ? n : undefined;
490947
491220
  }).hideHelp()).option("--from-pr [value]", "Resume a session linked to a PR by PR number/URL, or open interactive picker with optional search term", (value) => value || true).option("--no-session-persistence", "Disable session persistence - sessions will not be saved to disk and cannot be resumed (only works with --print)").addOption(new Option("--resume-session-at <message id>", "When resuming, only messages up to and including the assistant message with <message.id> (use with --resume in print mode)").argParser(String).hideHelp()).addOption(new Option("--rewind-files <user-message-id>", "Restore files to state at the specified user message and exit (requires --resume)").hideHelp()).option("--model <model>", `Model for the current session. Provide a role alias (e.g. 'small' or 'premium') or a provider/model reference (e.g. 'bailian/qwen38-27b').`).addOption(new Option("--effort <level>", `Effort level for the current session (low, medium, high, xhigh, max)`).argParser((rawValue) => {
@@ -490970,7 +491243,8 @@ async function run() {
490970
491243
  allowedTools = [],
490971
491244
  disallowedTools = [],
490972
491245
  mcpConfig = [],
490973
- permissionMode: permissionModeCli,
491246
+ permissionMode: permissionModeCliRaw,
491247
+ permissionPrompts,
490974
491248
  addDir = [],
490975
491249
  fallbackModel,
490976
491250
  betas = [],
@@ -490979,6 +491253,7 @@ async function run() {
490979
491253
  includeHookEvents,
490980
491254
  includePartialMessages
490981
491255
  } = options;
491256
+ const permissionModeCli = permissionModeCliRaw ?? (permissionPrompts === "none" ? "dontAsk" : undefined);
490982
491257
  if (options.prefill) {
490983
491258
  seedEarlyInput(options.prefill);
490984
491259
  }