@bastani/atomic 0.8.31-alpha.1 → 0.8.31-alpha.3

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 (148) hide show
  1. package/CHANGELOG.md +17 -5
  2. package/README.md +12 -10
  3. package/dist/builtin/cursor/CHANGELOG.md +1 -1
  4. package/dist/builtin/cursor/package.json +2 -2
  5. package/dist/builtin/intercom/CHANGELOG.md +1 -1
  6. package/dist/builtin/intercom/package.json +2 -2
  7. package/dist/builtin/mcp/CHANGELOG.md +1 -1
  8. package/dist/builtin/mcp/package.json +3 -3
  9. package/dist/builtin/subagents/CHANGELOG.md +10 -1
  10. package/dist/builtin/subagents/agents/codebase-online-researcher.md +8 -8
  11. package/dist/builtin/subagents/agents/debugger.md +6 -6
  12. package/dist/builtin/subagents/package.json +4 -4
  13. package/dist/builtin/subagents/skills/effective-liteparse/SKILL.md +118 -0
  14. package/dist/builtin/subagents/skills/effective-liteparse/scripts/search.py +128 -0
  15. package/dist/builtin/subagents/skills/playwright-cli/SKILL.md +404 -0
  16. package/dist/builtin/subagents/skills/playwright-cli/references/element-attributes.md +23 -0
  17. package/dist/builtin/subagents/skills/playwright-cli/references/playwright-tests.md +39 -0
  18. package/dist/builtin/subagents/skills/playwright-cli/references/request-mocking.md +87 -0
  19. package/dist/builtin/subagents/skills/playwright-cli/references/running-code.md +241 -0
  20. package/dist/builtin/subagents/skills/playwright-cli/references/session-management.md +225 -0
  21. package/dist/builtin/subagents/skills/playwright-cli/references/spec-driven-testing.md +305 -0
  22. package/dist/builtin/subagents/skills/playwright-cli/references/storage-state.md +275 -0
  23. package/dist/builtin/subagents/skills/playwright-cli/references/test-generation.md +134 -0
  24. package/dist/builtin/subagents/skills/playwright-cli/references/tracing.md +139 -0
  25. package/dist/builtin/subagents/skills/playwright-cli/references/video-recording.md +143 -0
  26. package/dist/builtin/web-access/CHANGELOG.md +1 -1
  27. package/dist/builtin/web-access/package.json +2 -2
  28. package/dist/builtin/workflows/CHANGELOG.md +7 -1
  29. package/dist/builtin/workflows/README.md +4 -4
  30. package/dist/builtin/workflows/builtin/open-claude-design.ts +59 -56
  31. package/dist/builtin/workflows/builtin/ralph.ts +56 -3
  32. package/dist/builtin/workflows/builtin/shared-prompts.ts +1 -1
  33. package/dist/builtin/workflows/package.json +2 -2
  34. package/dist/builtin/workflows/skills/research-codebase/SKILL.md +1 -1
  35. package/dist/cli/args.d.ts.map +1 -1
  36. package/dist/cli/args.js +1 -1
  37. package/dist/cli/args.js.map +1 -1
  38. package/dist/core/agent-session.d.ts +1 -0
  39. package/dist/core/agent-session.d.ts.map +1 -1
  40. package/dist/core/agent-session.js +49 -21
  41. package/dist/core/agent-session.js.map +1 -1
  42. package/dist/core/context-window.d.ts +26 -1
  43. package/dist/core/context-window.d.ts.map +1 -1
  44. package/dist/core/context-window.js +30 -6
  45. package/dist/core/context-window.js.map +1 -1
  46. package/dist/core/copilot-model-catalog.d.ts +39 -21
  47. package/dist/core/copilot-model-catalog.d.ts.map +1 -1
  48. package/dist/core/copilot-model-catalog.js +44 -16
  49. package/dist/core/copilot-model-catalog.js.map +1 -1
  50. package/dist/core/model-registry.d.ts.map +1 -1
  51. package/dist/core/model-registry.js +6 -4
  52. package/dist/core/model-registry.js.map +1 -1
  53. package/dist/core/project-trust.d.ts.map +1 -1
  54. package/dist/core/project-trust.js +2 -1
  55. package/dist/core/project-trust.js.map +1 -1
  56. package/dist/core/sdk.d.ts.map +1 -1
  57. package/dist/core/sdk.js +18 -7
  58. package/dist/core/sdk.js.map +1 -1
  59. package/dist/core/settings-manager.d.ts +11 -2
  60. package/dist/core/settings-manager.d.ts.map +1 -1
  61. package/dist/core/settings-manager.js +62 -8
  62. package/dist/core/settings-manager.js.map +1 -1
  63. package/dist/core/system-prompt.d.ts.map +1 -1
  64. package/dist/core/system-prompt.js +1 -0
  65. package/dist/core/system-prompt.js.map +1 -1
  66. package/dist/core/tools/edit-diff.d.ts +1 -2
  67. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  68. package/dist/core/tools/edit-diff.js +1 -2
  69. package/dist/core/tools/edit-diff.js.map +1 -1
  70. package/dist/index.d.ts +2 -1
  71. package/dist/index.d.ts.map +1 -1
  72. package/dist/index.js +2 -1
  73. package/dist/index.js.map +1 -1
  74. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  75. package/dist/modes/interactive/components/config-selector.js +5 -7
  76. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  77. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  78. package/dist/modes/interactive/components/model-selector.js +2 -1
  79. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  80. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  81. package/dist/modes/interactive/components/scoped-models-selector.js +4 -1
  82. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  83. package/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  84. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  85. package/dist/modes/interactive/components/settings-selector.js +165 -15
  86. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  87. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  88. package/dist/modes/interactive/components/tree-selector.js +44 -4
  89. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  90. package/dist/modes/interactive/interactive-mode.d.ts +1 -1
  91. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  92. package/dist/modes/interactive/interactive-mode.js +24 -54
  93. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  94. package/dist/modes/interactive/model-search.d.ts +7 -0
  95. package/dist/modes/interactive/model-search.d.ts.map +1 -0
  96. package/dist/modes/interactive/model-search.js +6 -0
  97. package/dist/modes/interactive/model-search.js.map +1 -0
  98. package/dist/modes/interactive/theme/theme-controller.d.ts +30 -0
  99. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -0
  100. package/dist/modes/interactive/theme/theme-controller.js +108 -0
  101. package/dist/modes/interactive/theme/theme-controller.js.map +1 -0
  102. package/dist/modes/interactive/theme/theme-schema.json +2 -1
  103. package/dist/modes/interactive/theme/theme.d.ts +5 -0
  104. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  105. package/dist/modes/interactive/theme/theme.js +70 -29
  106. package/dist/modes/interactive/theme/theme.js.map +1 -1
  107. package/dist/modes/rpc/rpc-client.d.ts +1 -1
  108. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  109. package/dist/modes/rpc/rpc-client.js +1 -1
  110. package/dist/modes/rpc/rpc-client.js.map +1 -1
  111. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  112. package/dist/modes/rpc/rpc-mode.js +1 -1
  113. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  114. package/dist/package-manager-cli.d.ts.map +1 -1
  115. package/dist/package-manager-cli.js +39 -9
  116. package/dist/package-manager-cli.js.map +1 -1
  117. package/docs/extensions.md +21 -0
  118. package/docs/models.md +3 -3
  119. package/docs/packages.md +13 -9
  120. package/docs/providers.md +3 -3
  121. package/docs/quickstart.md +14 -0
  122. package/docs/rpc.md +3 -3
  123. package/docs/sdk.md +15 -11
  124. package/docs/session-format.md +1 -1
  125. package/docs/settings.md +8 -3
  126. package/docs/themes.md +3 -1
  127. package/docs/tui.md +1 -1
  128. package/docs/usage.md +12 -9
  129. package/docs/workflows.md +9 -7
  130. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  131. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  132. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  133. package/examples/extensions/gondolin/package-lock.json +2 -2
  134. package/examples/extensions/gondolin/package.json +1 -1
  135. package/examples/extensions/preset.ts +10 -4
  136. package/examples/extensions/provider-payload.ts +5 -5
  137. package/examples/extensions/sandbox/index.ts +2 -2
  138. package/examples/extensions/sandbox/package-lock.json +3 -3
  139. package/examples/extensions/sandbox/package.json +2 -2
  140. package/examples/extensions/subagent/agents.ts +2 -2
  141. package/examples/extensions/subagent/index.ts +4 -2
  142. package/examples/extensions/with-deps/package-lock.json +2 -2
  143. package/examples/extensions/with-deps/package.json +1 -1
  144. package/package.json +5 -5
  145. package/dist/builtin/subagents/skills/browser/EXAMPLES.md +0 -151
  146. package/dist/builtin/subagents/skills/browser/LICENSE.txt +0 -21
  147. package/dist/builtin/subagents/skills/browser/REFERENCE.md +0 -451
  148. package/dist/builtin/subagents/skills/browser/SKILL.md +0 -170
package/docs/rpc.md CHANGED
@@ -323,7 +323,7 @@ Response:
323
323
  {"type": "response", "command": "set_context_window", "success": true}
324
324
  ```
325
325
 
326
- This command calls `AgentSession.setContextWindow(...)` without `{ persistDefault: true }`: it updates the active model, appends a `context_window_change` session entry and emits `context_window_changed` when the budget changes, but it does **not** write `defaultContextWindow` to settings. Use startup `--context-window` or an interactive settings selection when you intentionally want the existing persisted-default behavior.
326
+ This command calls `AgentSession.setContextWindow(...)` without `{ persistDefault: true }`: it updates the active model, appends a `context_window_change` session entry and emits `context_window_changed` when the budget changes, but it does **not** write context-window defaults to settings. Use startup `--context-window` or an interactive context-window selection when you intentionally want the effective selection persisted under `defaultContextWindows["provider/modelId"]`.
327
327
 
328
328
  Unsupported or malformed selections return the standard RPC error response:
329
329
  ```json
@@ -975,7 +975,7 @@ Emitted whenever the pending steering or follow-up queue changes.
975
975
 
976
976
  ### context_window_changed
977
977
 
978
- Emitted when the active context-window token budget changes through RPC `set_context_window`, `AgentSession.setContextWindow()` in an SDK-backed runtime, or because in-place tree navigation replayed a branch-scoped `context_window_change` entry. Navigation replay updates the active model for accurate budgeting and compaction but does not append another session entry or write `defaultContextWindow` to settings.
978
+ Emitted when the active context-window token budget changes through RPC `set_context_window`, `AgentSession.setContextWindow()` in an SDK-backed runtime, or because in-place tree navigation replayed a branch-scoped `context_window_change` entry. Navigation replay updates the active model for accurate budgeting and compaction but does not append another session entry or write context-window defaults to settings.
979
979
 
980
980
  ```json
981
981
  {
@@ -1321,7 +1321,7 @@ Source files and installed definitions:
1321
1321
  }
1322
1322
  ```
1323
1323
 
1324
- `contextWindow` is the active/effective token budget used by Atomic's local budgeting, footer/stats, and compaction logic. `defaultContextWindow` is the model's scalar default before a session/runtime override, and `contextWindowOptions` lists selectable token budgets when the model supports more than one size. RPC clients can read/select the active runtime budget with `get_available_context_windows` and `set_context_window`; the runtime command does not persist `defaultContextWindow` to settings.
1324
+ `contextWindow` is the active/effective token budget used by Atomic's local budgeting, footer/stats, and compaction logic. `defaultContextWindow` is the model's scalar default before a session/runtime override, and `contextWindowOptions` lists selectable token budgets when the model supports more than one size. RPC clients can read/select the active runtime budget with `get_available_context_windows` and `set_context_window`; the runtime command does not persist context-window defaults to settings.
1325
1325
 
1326
1326
  ### UserMessage
1327
1327
 
package/docs/sdk.md CHANGED
@@ -437,11 +437,11 @@ If no model is provided:
437
437
  2. Uses default from settings
438
438
  3. Falls back to first available model
439
439
 
440
- Context-window selection is independent from `thinkingLevel`. `contextWindow` accepts a raw token count such as `400_000` or `1_000_000`; the value must be present in the model's supported context windows (`model.contextWindowOptions` plus the scalar default). When a saved or settings default context window is unsupported for the selected model, `createAgentSession()` keeps the model default and returns `contextWindowWarning`. When you pass `contextWindowStrict: true`, an unsupported explicit selection is reported as `contextWindowError` so callers can fail before prompting. A successful explicit `contextWindow` startup option is journaled as a `context_window_change` entry even when it equals the scalar model default, so the user's explicit budget choice survives future settings changes and resume.
440
+ Context-window selection is independent from `thinkingLevel`. `contextWindow` accepts a raw token count such as `400_000` or `1_000_000`; for most providers the value must be present in the model's supported context windows (`model.contextWindowOptions` plus the scalar default). GitHub Copilot is the only provider with rounded long-context budget handling: when a tiered Copilot model advertises a long tier below the branded request (for example `936_000` for a `1_000_000` request), Atomic selects the largest advertised Copilot long tier at or below the request instead of falling back to the short tier. Settings lookup first checks the selected model's `defaultContextWindows["provider/modelId"]` entry, then the optional global `defaultContextWindow` fallback; unsupported model-specific settings keep the model default and return `contextWindowWarning`, while unsupported global fallback values are ignored silently as not applicable to the active model. When you pass `contextWindowStrict: true`, an unsupported explicit selection is reported as `contextWindowError` so callers can fail before prompting. A successful explicit `contextWindow` startup option is journaled as a `context_window_change` entry even when it equals the scalar model default, so the user's explicit budget choice survives future settings changes and resume.
441
441
 
442
- At runtime, use `session.getAvailableContextWindows()` to inspect supported values, `session.supportsContextWindowSelection()` to check whether more than one value is selectable, and `session.setContextWindow(tokens, { persistDefault })` to change the active model budget. `setContextWindow()` journals a `context_window_change` entry only when the active value changes. Passing `{ persistDefault: true }` also writes `defaultContextWindow` to settings. Tree navigation replays the target branch's `context_window_change` state into the active model without adding another journal entry or changing settings. Larger provider context windows may consume more credits/cost, so opt into larger values deliberately. For allowlisted GitHub Copilot long-context models (including `github-copilot/gpt-5.5` and `github-copilot/gemini-3.1-pro-preview`), selecting `1m` raises Atomic's local budget and sends `X-GitHub-Api-Version: 2026-06-01`; GitHub applies the long-context tier server-side by prompt token count, consumes more Copilot AI credits, and requires long-context/usage-based billing entitlement.
442
+ At runtime, use `session.getAvailableContextWindows()` to inspect supported values, `session.supportsContextWindowSelection()` to check whether more than one value is selectable, and `session.setContextWindow(tokens, { persistDefault })` to change the active model budget. `setContextWindow()` journals a `context_window_change` entry only when the active value changes. Passing `{ persistDefault: true }` also writes the effective selected budget to `defaultContextWindows["provider/modelId"]` in settings instead of the global fallback, so a Copilot prompt cap such as `936k` does not leak into Anthropic, Cursor, or other providers. Tree navigation replays the target branch's `context_window_change` state into the active model without adding another journal entry or changing settings. Larger provider context windows may consume more credits/cost, so opt into larger values deliberately. For allowlisted GitHub Copilot long-context models (including `github-copilot/gpt-5.5` and `github-copilot/gemini-3.1-pro-preview`), selecting `1m` raises Atomic's local budget to the model's advertised `922k`/`936k` tier and sends `X-GitHub-Api-Version: 2026-06-01`; GitHub applies the long-context tier server-side by prompt token count, consumes more Copilot AI credits, and requires long-context/usage-based billing entitlement.
443
443
 
444
- The package root exports the same context-window helpers and types used by the runtime: `parseContextWindowValue()`, `formatContextWindow()`, `validateContextWindowValue()`, `normalizeContextWindowOptions()`, `getModelDefaultContextWindow()`, `getSupportedContextWindows()`, `withContextWindowOptions()`, `selectContextWindow()`, `ContextWindowParseResult`, `ContextWindowSelection`, and `ContextWindowSelectionError`. Importing from `@bastani/atomic` also includes the `@earendil-works/pi-ai` `Model<Api>` augmentation for `contextWindowOptions` and `defaultContextWindow`, so SDK consumers can use the helper types without importing internal source paths.
444
+ The package root exports the same context-window helpers and types used by the runtime: `parseContextWindowValue()`, `formatContextWindow()`, `validateContextWindowValue()`, `normalizeContextWindowOptions()`, `getModelDefaultContextWindow()`, `getSupportedContextWindows()`, `withContextWindowOptions()`, `selectContextWindow()`, `ContextWindowParseResult`, `ContextWindowSelection`, `ContextWindowSelectionError`, and `ContextWindowSelectionOptions`. Importing from `@bastani/atomic` also includes the `@earendil-works/pi-ai` `Model<Api>` augmentation for `contextWindowOptions` and `defaultContextWindow`, so SDK consumers can use the helper types without importing internal source paths.
445
445
 
446
446
  > See [examples/sdk/02-custom-model.ts](https://github.com/bastani-inc/atomic/blob/main/packages/coding-agent/examples/sdk/02-custom-model.ts)
447
447
 
@@ -546,11 +546,11 @@ const { session } = await createAgentSession({
546
546
  ```typescript
547
547
  import { createAgentSession, type BashCommandPolicy } from "@bastani/atomic";
548
548
 
549
- const browseOnly: BashCommandPolicy = {
549
+ const playwrightCliOnly: BashCommandPolicy = {
550
550
  default: "deny",
551
551
  allow: [
552
- "which browse",
553
- { prefix: "browse " },
552
+ "which playwright-cli",
553
+ { prefix: "playwright-cli " },
554
554
  { prefix: "grep " },
555
555
  { glob: "bun test test/unit/*.test.ts" },
556
556
  { regex: "^rg\\b" },
@@ -561,19 +561,19 @@ const browseOnly: BashCommandPolicy = {
561
561
 
562
562
  const { session } = await createAgentSession({
563
563
  tools: ["read", "bash"],
564
- bashPolicy: browseOnly,
564
+ bashPolicy: playwrightCliOnly,
565
565
  });
566
566
  ```
567
567
 
568
568
  Rules match exact command strings, prefixes, command-string globs, or JavaScript regular expressions. `default` defaults to `"allow"` for backward compatibility; set `default: "deny"` for an allowlist-only shell. Omitting `bashPolicy`, passing `{}`, or passing a default-allow policy with no `allow`/`deny` rules is a compatibility no-op and does not parse the command. Empty `allow`/`deny` arrays and match-only default-allow policies are treated the same; malformed policy objects still fail closed.
569
569
 
570
- Glob rules match command target strings, not filesystem path segments. `*` and `?` can match `/`, so `{ glob: "browse *" }` matches `browse http://localhost:3000`, `browse docs/index.html`, and `browse ./preview/output.html`, while still matching the whole target so `echo browse docs/index.html` does not match unless the pattern includes leading wildcards. Backslash escapes the next glob character when you need a literal `*`, `?`, or bracket; inside bracket classes, escaped metacharacters such as `\-`, `\^`, `\]`, `\[`, and `\\` stay literal instead of becoming regex ranges, negation markers, class delimiters, or backslash escapes. Malformed glob bracket classes or ranges, such as `{ glob: "echo [z-a]" }`, fail closed as `invalid-policy` rather than surfacing raw regular-expression errors.
570
+ Glob rules match command target strings, not filesystem path segments. `*` and `?` can match `/`, so `{ glob: "playwright-cli *" }` matches `playwright-cli http://localhost:3000`, `playwright-cli docs/index.html`, and `playwright-cli ./preview/output.html`, while still matching the whole target so `echo playwright-cli docs/index.html` does not match unless the pattern includes leading wildcards. Backslash escapes the next glob character when you need a literal `*`, `?`, or bracket; inside bracket classes, escaped metacharacters such as `\-`, `\^`, `\]`, `\[`, and `\\` stay literal instead of becoming regex ranges, negation markers, class delimiters, or backslash escapes. Malformed glob bracket classes or ranges, such as `{ glob: "echo [z-a]" }`, fail closed as `invalid-policy` rather than surfacing raw regular-expression errors.
571
571
 
572
572
  Runtime policy validation is part of enforcement for JavaScript/JSON callers: a provided policy must be a non-null object with only the top-level keys `default`, `allow`, `deny`, and `match`; typoed or extra keys such as `denny` or `extra` are rejected as `invalid-policy` even when the policy otherwise looks like default-allow. `allow`/`deny` must be arrays when present, rules must be non-empty strings or one-variant objects with string values, regex flags must be strings, and invalid regexes, invalid globs, or stateful `g`/`y` flags are rejected as `invalid-policy` before shell execution.
573
573
 
574
- By default, `match: "segments"` parses shell separators and substitutions and requires every executable segment to pass. Separators include pipes, `&&`, `||`, `;`, background `&`, and unquoted line terminators: LF, CRLF, and bare CR are command separators rather than ordinary whitespace. Bash noclobber redirection `>|` is treated as redirection syntax rather than a pipeline separator after a command head, so `echo ok >|/tmp/out` remains one `echo` segment. For example, `browse snapshot | grep title` must satisfy both the `browse` rule and the `grep` rule, and `browse snapshot; rm -rf /` or `browse snapshot\nrm -rf /` is blocked when `rm` is denied or when `default: "deny"` has no matching allow rule. Segment mode also checks command substitutions (`$(...)`, backticks) and process substitutions (`<(...)`, `>(...)`). Syntax Atomic cannot safely segment is rejected before a shell process starts.
574
+ By default, `match: "segments"` parses shell separators and substitutions and requires every executable segment to pass. Separators include pipes, `&&`, `||`, `;`, background `&`, and unquoted line terminators: LF, CRLF, and bare CR are command separators rather than ordinary whitespace. Bash noclobber redirection `>|` is treated as redirection syntax rather than a pipeline separator after a command head, so `echo ok >|/tmp/out` remains one `echo` segment. For example, `playwright-cli snapshot | grep title` must satisfy both the `playwright-cli` rule and the `grep` rule, and `playwright-cli snapshot; rm -rf /` or `playwright-cli snapshot\nrm -rf /` is blocked when `rm` is denied or when `default: "deny"` has no matching allow rule. Segment mode also checks command substitutions (`$(...)`, backticks) and process substitutions (`<(...)`, `>(...)`). Syntax Atomic cannot safely segment is rejected before a shell process starts.
575
575
 
576
- Segment mode requires each command head to be a statically identifiable literal word. Literal names such as `grep`, `./script`, `/usr/bin/env`, `bun`, `browse`, and names containing hyphens, underscores, dots, or slashes are accepted when they contain no shell expansion syntax. Atomic conservatively rejects Bash reserved words and compound introducers (`coproc`, `if`, `for`, `while`, `case`, `{`, `}`, `!`), leading redirection syntax (`>file cmd`, `2>file cmd`, `<file cmd`, `&>file cmd`, `>|file cmd`, `<&0 cmd`, `>&2 cmd`), redirection operators attached to the command-head word (`cmd>file`, `cmd>>file`, `cmd>|file`, `cmd2>file`, `cmd>&2`, `cmd</tmp/in`), leading environment assignment words (`PATH=/tmp:$PATH browse snapshot`, `LD_PRELOAD=/tmp/x browse snapshot`, `FOO=bar`), variable or parameter-expanded heads (`$cmd`, `${cmd}`), quote- or escape-constructed heads (`r''m`, `"rm"`, `r\m`), tilde/glob/brace-expanded heads (`~/bin/rm`, `r*m`, `{rm,echo}`), and command/process substitutions or backticks embedded in the head. Substitutions in argument positions are still parsed so nested commands must also pass the policy.
576
+ Segment mode requires each command head to be a statically identifiable literal word. Literal names such as `grep`, `./script`, `/usr/bin/env`, `bun`, `playwright-cli`, and names containing hyphens, underscores, dots, or slashes are accepted when they contain no shell expansion syntax. Atomic conservatively rejects Bash reserved words and compound introducers (`coproc`, `if`, `for`, `while`, `case`, `{`, `}`, `!`), leading redirection syntax (`>file cmd`, `2>file cmd`, `<file cmd`, `&>file cmd`, `>|file cmd`, `<&0 cmd`, `>&2 cmd`), redirection operators attached to the command-head word (`cmd>file`, `cmd>>file`, `cmd>|file`, `cmd2>file`, `cmd>&2`, `cmd</tmp/in`), leading environment assignment words (`PATH=/tmp:$PATH playwright-cli snapshot`, `LD_PRELOAD=/tmp/x playwright-cli snapshot`, `FOO=bar`), variable or parameter-expanded heads (`$cmd`, `${cmd}`), quote- or escape-constructed heads (`r''m`, `"rm"`, `r\m`), tilde/glob/brace-expanded heads (`~/bin/rm`, `r*m`, `{rm,echo}`), and command/process substitutions or backticks embedded in the head. Substitutions in argument positions are still parsed so nested commands must also pass the policy.
577
577
 
578
578
  Use `match: "whole"` only when you intentionally want rules to match the raw command string as-is. Whole-command prefix rules can allow shell operators inside the same raw string.
579
579
 
@@ -1256,7 +1256,8 @@ DefaultResourceLoader
1256
1256
  type ResourceLoader
1257
1257
  createEventBus
1258
1258
 
1259
- // Helpers
1259
+ // Constants and helpers
1260
+ CONFIG_DIR_NAME
1260
1261
  defineTool
1261
1262
  STRUCTURED_OUTPUT_TOOL_NAME
1262
1263
  createStructuredOutputTool
@@ -1266,6 +1267,9 @@ getPackageDir
1266
1267
  getReadmePath
1267
1268
  getDocsPath
1268
1269
  getExamplesPath
1270
+ generateDiffString
1271
+ generateUnifiedPatch
1272
+ type EditDiffResult
1269
1273
 
1270
1274
  // Session management
1271
1275
  SessionManager
@@ -224,7 +224,7 @@ Emitted when the user selects a supported context-window size for the active mod
224
224
  {"type":"context_window_change","id":"f6g7h8i9","parentId":"e5f6g7h8","timestamp":"2024-12-03T14:07:00.000Z","contextWindow":1000000}
225
225
  ```
226
226
 
227
- `buildSessionContext()` replays the latest `context_window_change` on the active branch. In-place tree navigation also applies the branch's replayed context window to the active model without appending another `context_window_change` entry or writing `defaultContextWindow` to settings. If a historical value is no longer supported by the current model, session creation/navigation falls back to the model default the same way other context-window restore paths do.
227
+ `buildSessionContext()` replays the latest `context_window_change` on the active branch. In-place tree navigation also applies the branch's replayed context window to the active model without appending another `context_window_change` entry or writing context-window defaults to settings. If a historical value is no longer supported by the current model, session creation/navigation falls back to the model default the same way other context-window restore paths do.
228
228
 
229
229
  ### CompactionEntry
230
230
 
package/docs/settings.md CHANGED
@@ -232,16 +232,21 @@ When multiple sources specify a session directory, precedence is `--session-dir`
232
232
  | Setting | Type | Default | Description |
233
233
  |---------|------|---------|-------------|
234
234
  | `enabledModels` | string[] | - | Model patterns for CTRL+P cycling (same format as `--models` CLI flag) |
235
- | `defaultContextWindow` | number \| string | model default | Preferred context window for models that expose selectable context windows. Accepts raw token counts or compact labels such as `400k` and `1m`. Unsupported values are ignored with a warning for the active model. |
235
+ | `defaultContextWindow` | number \| string | model default | Optional global fallback context window for models that expose selectable context windows. Accepts raw token counts or compact labels such as `400k` and `1m`. Unsupported values are ignored for models that do not support them. |
236
+ | `defaultContextWindows` | object | `{}` | Per-model preferred context windows keyed as `provider/modelId`. The interactive `/model` context picker writes this setting so a Copilot-specific prompt cap such as `936k` does not leak into Anthropic, Cursor, or other providers. |
236
237
 
237
238
  ```json
238
239
  {
239
240
  "enabledModels": ["claude-*", "gpt-4o", "gemini-2*"],
240
- "defaultContextWindow": "1m"
241
+ "defaultContextWindow": "1m",
242
+ "defaultContextWindows": {
243
+ "github-copilot/claude-opus-4.8": "936k",
244
+ "github-copilot/gpt-5.5": "922k"
245
+ }
241
246
  }
242
247
  ```
243
248
 
244
- `defaultContextWindow` is independent of `defaultThinkingLevel`: selecting a larger context window does not change reasoning effort. Interactive users can also change the active model's budget through the `/model` selection flow, which prompts for a context window whenever the chosen model supports more than one window. Larger provider context windows can carry higher usage cost. For GitHub Copilot allowlisted long-context models (including `github-copilot/gpt-5.5` and `github-copilot/gemini-3.1-pro-preview`), selecting `1m` raises Atomic's local budget and sends `X-GitHub-Api-Version: 2026-06-01`; GitHub then applies the long-context tier server-side by prompt token count. That tier consumes more Copilot AI credits and requires Copilot long-context/usage-based billing entitlement, otherwise requests over the server cap are rejected with a friendly hint. Custom providers and explicit model overrides can still declare their own selectable `contextWindowOptions`.
249
+ Context-window settings are independent of `defaultThinkingLevel`: selecting a larger context window does not change reasoning effort. Interactive users can change the active model's budget through the `/model` selection flow, which prompts for a context window whenever the chosen model supports more than one window and persists the effective selection under `defaultContextWindows["provider/modelId"]`. Atomic treats `defaultContextWindow` as a broad fallback only: if the active model does not support that value, the model's own default is used without a startup warning; targeted `defaultContextWindows` entries still warn when they become unsupported for their exact model. Larger provider context windows can carry higher usage cost. For GitHub Copilot allowlisted long-context models (including `github-copilot/gpt-5.5` and `github-copilot/gemini-3.1-pro-preview`), selecting `1m` raises Atomic's local prompt budget to the largest advertised long-context tier at or below that rounded request (for example `922k` or `936k`) and sends `X-GitHub-Api-Version: 2026-06-01`; GitHub then applies the long-context tier server-side by prompt token count. That tier consumes more Copilot AI credits and requires Copilot long-context/usage-based billing entitlement, otherwise requests over the server cap are rejected with a friendly hint. Custom providers and explicit model overrides can still declare their own selectable `contextWindowOptions`.
245
250
 
246
251
  ### Markdown
247
252
 
package/docs/themes.md CHANGED
@@ -37,6 +37,8 @@ Select a theme via `/settings` or in `settings.json`:
37
37
  }
38
38
  ```
39
39
 
40
+ Use `"theme": "light-theme/dark-theme"` for automatic mode. Atomic chooses the first theme when the terminal reports a light color scheme and the second theme for dark terminals, and it follows terminal color-scheme changes when supported.
41
+
40
42
  On first run, Atomic detects your terminal background and defaults to `dark` or `light`.
41
43
 
42
44
  ## Creating a Custom Theme
@@ -137,7 +139,7 @@ vim ~/.atomic/agent/themes/my-theme.json
137
139
  }
138
140
  ```
139
141
 
140
- - `name` is required and must be unique.
142
+ - `name` is required, must be unique, and must not contain `/`.
141
143
  - `vars` is optional. Define reusable colors here, then reference them in `colors`.
142
144
  - `colors` must define all 51 required tokens.
143
145
 
package/docs/tui.md CHANGED
@@ -250,7 +250,7 @@ md.setText("Updated markdown");
250
250
 
251
251
  ### Image
252
252
 
253
- Renders images in supported terminals (Kitty, iTerm2, Ghostty, WezTerm).
253
+ Renders images in supported terminals (Kitty, iTerm2, Ghostty, WezTerm, Warp).
254
254
 
255
255
  ```typescript
256
256
  const image = new Image(
package/docs/usage.md CHANGED
@@ -131,17 +131,20 @@ atomic [options] [@files...] [messages...]
131
131
  ### Package Commands
132
132
 
133
133
  ```bash
134
- atomic install <source> [-l] # Install package, -l for project-local
135
- atomic remove <source> [-l] # Remove package
136
- atomic uninstall <source> [-l] # Alias for remove
137
- atomic update [source|self|atomic] # Update Atomic and packages; skips pinned packages
138
- atomic update --extensions # Update packages only
139
- atomic update --self # Update Atomic only
140
- atomic update --extension <src> # Update one package
141
- atomic list # List installed packages
142
- atomic config # Enable/disable package resources
134
+ atomic install <source> [-l] # Install package, -l for project-local
135
+ atomic remove <source> [-l] # Remove package
136
+ atomic uninstall <source> [-l] # Alias for remove
137
+ atomic update [source|self|atomic] # Update Atomic only, or one package source
138
+ atomic update --all # Update Atomic and packages; reconcile pinned git refs
139
+ atomic update --extensions # Update packages only; reconcile pinned git refs
140
+ atomic update --self # Update Atomic only
141
+ atomic update --extension <src> # Update one package
142
+ atomic list # List installed packages
143
+ atomic config # Enable/disable package resources
143
144
  ```
144
145
 
146
+ These commands manage Atomic packages and `atomic update` can update the Atomic CLI installation. To uninstall Atomic itself, see [Quickstart](/quickstart#uninstall). `atomic config` and project package commands accept `--approve`/`--no-approve` to trust or ignore project-local settings for one command. `atomic update` never prompts for project trust.
147
+
145
148
  See [Atomic Packages](/packages) for package sources and security notes.
146
149
 
147
150
  ### Modes
package/docs/workflows.md CHANGED
@@ -224,7 +224,7 @@ Run examples:
224
224
 
225
225
  Write the `objective` like a compact acceptance spec. Say what should exist when the run is done, how you want testing handled, which command(s) or manual checks matter, and what outcome proves completion. The workflow is intentionally lean: it does not first generate an RFC or migration plan, so the developer-supplied objective is where scope, validation, and completion criteria belong.
226
226
 
227
- The worker may claim readiness, but it cannot finalize completion. Workers and reviewers are prompted to verify user-visible behavior end-to-end when practical, using browser-skilled subagents for web/frontend flows that may depend on backend/API behavior and tmux-skilled subagents for TUI or terminal-app scenarios. Three reviewers independently inspect the ledger, worker receipt, repository state, and diff against `base_branch`; each returns structured JSON with findings, evidence, verification still remaining, and an optional blocker. A TypeScript reducer marks the goal complete only when reviewer quorum approves, marks blocked only when the same dependency/tool blocker repeats for the blocker threshold, continues when evidence is missing, and returns `needs_human` when `max_turns` is exhausted or worker execution fails.
227
+ The worker may claim readiness, but it cannot finalize completion. Workers and reviewers are prompted to verify user-visible behavior end-to-end when practical, using `playwright-cli`-skilled subagents for web/frontend flows that may depend on backend/API behavior and tmux-skilled subagents for TUI or terminal-app scenarios. Three reviewers independently inspect the ledger, worker receipt, repository state, and diff against `base_branch`; each returns structured JSON with findings, evidence, verification still remaining, and an optional blocker. A TypeScript reducer marks the goal complete only when reviewer quorum approves, marks blocked only when the same dependency/tool blocker repeats for the blocker threshold, continues when evidence is missing, and returns `needs_human` when `max_turns` is exhausted or worker execution fails.
228
228
 
229
229
  Result fields:
230
230
 
@@ -262,7 +262,7 @@ Run examples:
262
262
  /workflow ralph prompt="Safely implement the API refactor" git_worktree_dir=../atomic-ralph-api-wt base_branch=main
263
263
  ```
264
264
 
265
- Each `ralph` iteration starts by prompt-engineering the user prompt with `/skill:prompt-engineer Transform the following user prompt to a codebase and online research question which can be thoroughly explored: ...`, then researches that transformed question with `/skill:research-codebase ...` and writes the findings under `research/`. The orchestrator treats that research artifact as its primary implementation context, initializes/updates an OS-temp implementation notes file while generating verifiable evidence for any claims it records in the notes and reviewer artifacts, delegates implementation through sub-agents, and asks three independent reviewers to inspect the patch directly against `base_branch`. The reviewer fan-out runs each reviewer on a different primary model family (with shared fallbacks) so the adversarial review gets cross-model coverage instead of three passes from one model. Ralph's orchestrator and reviewers are prompted to verify user-visible behavior end-to-end when practical, using browser-skilled subagents for web/frontend flows that may depend on backend/API behavior and tmux-skilled subagents for TUI or terminal-app scenarios. If reviewers find issues, the next prompt-engineering and research stages receive the review artifact path so follow-up research can address unresolved findings, and research stages fork from prior research session data when available. The loop stops only when all three reviewers independently approve (each finds no issues) or `max_loops` is reached, so a P0–P3 finding from any single reviewer keeps Ralph iterating instead of being out-voted by a majority quorum. By default Ralph does not start the final `pull-request` stage, and `pr_report` is omitted. Prompt text alone does not opt in. Pass `create_pr=true` only when you explicitly want the final `pull-request` stage to inspect provider credentials and attempt provider-appropriate PR/MR/review creation, such as GitHub `gh`, Azure Repos `az repos pr create`, or Sapling/Phabricator tooling; Ralph's own PR-creation instructions live in that final stage.
265
+ Each `ralph` iteration starts by prompt-engineering the user prompt with `/skill:prompt-engineer Transform the following user prompt to a codebase and online research question which can be thoroughly explored: ...`, then researches that transformed question with `/skill:research-codebase ...` and writes the findings under `research/`. The orchestrator treats that research artifact as its primary implementation context, initializes/updates an OS-temp implementation notes file while generating verifiable evidence for any claims it records in the notes and reviewer artifacts, delegates implementation through sub-agents, and asks three independent reviewers to inspect the patch directly against `base_branch`. The reviewer fan-out runs each reviewer on a different primary model family (with shared fallbacks) so the adversarial review gets cross-model coverage instead of three passes from one model. Ralph's orchestrator and reviewers are prompted to verify user-visible behavior end-to-end when practical, using `playwright-cli`-skilled subagents for web/frontend flows that may depend on backend/API behavior and tmux-skilled subagents for TUI or terminal-app scenarios. For UI-applicable or full-stack changes, the orchestrator runs a `playwright-cli` end-to-end QA pass and records a reviewable proof video (referenced in the implementation notes and surfaced as `qa_video_path`); when `create_pr=true`, the final `pull-request` stage attaches or links that video to the created PR/MR/review. If reviewers find issues, the next prompt-engineering and research stages receive the review artifact path so follow-up research can address unresolved findings, and research stages fork from prior research session data when available. The loop stops only when all three reviewers independently approve (each finds no issues) or `max_loops` is reached, so a P0–P3 finding from any single reviewer keeps Ralph iterating instead of being out-voted by a majority quorum. By default Ralph does not start the final `pull-request` stage, and `pr_report` is omitted. Prompt text alone does not opt in. Pass `create_pr=true` only when you explicitly want the final `pull-request` stage to inspect provider credentials and attempt provider-appropriate PR/MR/review creation, such as GitHub `gh`, Azure Repos `az repos pr create`, or Sapling/Phabricator tooling; Ralph's own PR-creation instructions live in that final stage.
266
266
 
267
267
  Set `git_worktree_dir` when you want Ralph's worker stages isolated in a reusable Git worktree. Relative paths resolve from the invoking repository root, existing same-repository worktree roots are reused, and missing paths are created from `base_branch`. Ralph preserves the invoking repo-relative cwd inside the worktree, so launching from `repo/packages/api` with `git_worktree_dir=../repo-wt` runs stages from `../repo-wt/packages/api`.
268
268
 
@@ -276,6 +276,7 @@ Result fields:
276
276
  | `research` | Latest research report text or artifact reference. |
277
277
  | `research_path` | Path to the latest generated research artifact under `research/`. |
278
278
  | `implementation_notes_path` | OS-temp notes file containing decisions, deviations, blockers, and validation notes. |
279
+ | `qa_video_path` | Absolute path to the reviewable QA end-to-end proof video recorded with `playwright-cli` for UI-applicable changes, when one was produced. |
279
280
  | `pr_report` | Pull-request report emitted only when `create_pr=true` and the final `pull-request` stage runs. |
280
281
  | `approved` | Whether the reviewer loop approved before completion or optional final handoff. |
281
282
  | `iterations_completed` | Number of research/orchestrate/review loops completed. |
@@ -313,6 +314,7 @@ Result fields:
313
314
  | `preview_file_url` | `file://` URL for the generated `preview.html` file. |
314
315
  | `spec_path` | Absolute path to the generated `spec.html` file. |
315
316
  | `spec_file_url` | `file://` URL for the generated `spec.html` file. |
317
+ | `playwright_cli_status` | Outcome of the initial deterministic step that ensures the `playwright-cli` skill's `playwright-cli` command is installed. |
316
318
 
317
319
  `open-claude-design` has no `result` output; it exposes only the declared fields listed above. Use the declared `artifact` and `handoff` fields for generated content.
318
320
 
@@ -1496,18 +1498,18 @@ await ctx.task("browser-preview", {
1496
1498
  bashPolicy: {
1497
1499
  default: "deny",
1498
1500
  allow: [
1499
- "which browse",
1500
- { prefix: "browse open " },
1501
- { prefix: "browse snapshot" },
1501
+ "which playwright-cli",
1502
+ { prefix: "playwright-cli open " },
1503
+ { prefix: "playwright-cli snapshot" },
1502
1504
  { prefix: "grep " },
1503
1505
  ],
1504
1506
  deny: [{ regex: "\\brm\\b" }],
1505
1507
  },
1506
- prompt: "Open the preview with browse, then summarize the visible state.",
1508
+ prompt: "Open the preview with playwright-cli, then summarize the visible state.",
1507
1509
  });
1508
1510
  ```
1509
1511
 
1510
- A command such as `browse snapshot | grep title` passes only when both segments are allowed, and `browse snapshot\nrm -rf /tmp/proof` cannot be hidden behind a `{ prefix: "browse " }` rule because the newline starts a new segment. Glob rules match command strings rather than filesystem path segments: `*` and `?` may span `/`, so `{ glob: "browse *" }` matches URLs and slash-bearing paths such as `browse http://localhost:3000`, `browse docs/index.html`, and `browse ./preview/output.html` while still matching the whole target rather than `echo browse ...`; escaped bracket-class metacharacters such as `\-`, `\^`, `\]`, `\[`, and `\\` stay literal, while malformed glob ranges such as `{ glob: "echo [z-a]" }` become `invalid-policy` denials. Segment mode accepts literal heads such as `grep`, `./script`, `/usr/bin/env`, `bun`, and `browse`, and treats non-leading `>|` as redirection syntax so `echo ok >|/tmp/out` stays one segment, but conservatively rejects reserved or compound heads (`coproc`, `if`, `for`, `while`, `case`, `{`, `}`, `!`), leading redirections (`>file cmd`, `2>file cmd`, `<file cmd`, `&>file cmd`, `&>>file cmd`, `>|file cmd`, `<&0 cmd`, `>&2 cmd`), redirections attached to the command-head word (`cmd>file`, `cmd>>file`, `cmd>|file`, `cmd2>file`, `cmd>&2`, `cmd</tmp/in`), leading environment assignments (`PATH=/tmp:$PATH browse snapshot`, `LD_PRELOAD=/tmp/x browse snapshot`, `FOO=bar`), dynamic heads such as `$cmd`, `${cmd}`, `r''m`, `r\m`, `~/bin/rm`, `r*m`, `{rm,echo}`, `r$(printf m)`, or backtick-built command names. A single denied, redirection-prefixed, attached-redirection, assignment-prefixed, dynamic, or unrecognized segment blocks the whole command with a model-readable tool error and no UI prompt, so the behavior works in headless workflow runs. Use `match: "whole"` only when raw-command matching is intentional.
1512
+ A command such as `playwright-cli snapshot | grep title` passes only when both segments are allowed, and `playwright-cli snapshot\nrm -rf /tmp/proof` cannot be hidden behind a `{ prefix: "playwright-cli " }` rule because the newline starts a new segment. Glob rules match command strings rather than filesystem path segments: `*` and `?` may span `/`, so `{ glob: "playwright-cli *" }` matches URLs and slash-bearing paths such as `playwright-cli http://localhost:3000`, `playwright-cli docs/index.html`, and `playwright-cli ./preview/output.html` while still matching the whole target rather than `echo playwright-cli ...`; escaped bracket-class metacharacters such as `\-`, `\^`, `\]`, `\[`, and `\\` stay literal, while malformed glob ranges such as `{ glob: "echo [z-a]" }` become `invalid-policy` denials. Segment mode accepts literal heads such as `grep`, `./script`, `/usr/bin/env`, `bun`, and `playwright-cli`, and treats non-leading `>|` as redirection syntax so `echo ok >|/tmp/out` stays one segment, but conservatively rejects reserved or compound heads (`coproc`, `if`, `for`, `while`, `case`, `{`, `}`, `!`), leading redirections (`>file cmd`, `2>file cmd`, `<file cmd`, `&>file cmd`, `&>>file cmd`, `>|file cmd`, `<&0 cmd`, `>&2 cmd`), redirections attached to the command-head word (`cmd>file`, `cmd>>file`, `cmd>|file`, `cmd2>file`, `cmd>&2`, `cmd</tmp/in`), leading environment assignments (`PATH=/tmp:$PATH playwright-cli snapshot`, `LD_PRELOAD=/tmp/x playwright-cli snapshot`, `FOO=bar`), dynamic heads such as `$cmd`, `${cmd}`, `r''m`, `r\m`, `~/bin/rm`, `r*m`, `{rm,echo}`, `r$(printf m)`, or backtick-built command names. A single denied, redirection-prefixed, attached-redirection, assignment-prefixed, dynamic, or unrecognized segment blocks the whole command with a model-readable tool error and no UI prompt, so the behavior works in headless workflow runs. Use `match: "whole"` only when raw-command matching is intentional.
1511
1513
 
1512
1514
  `gitWorktreeDir` selects a reusable Git worktree root for `ctx.stage`, `ctx.task`, `ctx.chain`, and `ctx.parallel`. If the path is missing, Atomic creates it with `git worktree add --detach <path> <baseBranch>`; if it exists, it must be a same-repository worktree root. The default stage cwd becomes the matching cwd inside the worktree and preserves the invoking repo-relative subdirectory. Explicit `cwd` still wins; relative `cwd` values resolve from the worktree cwd, while absolute `cwd` values are used as provided. `gitWorktreeDir` is mutually exclusive with `worktree: true`: use `gitWorktreeDir` for named/reusable worktrees and `worktree: true` for temporary direct-mode worktrees that are cleaned up after the run.
1513
1515
 
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "atomic-extension-custom-provider-anthropic",
3
- "version": "0.79.4",
3
+ "version": "0.79.7",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "atomic-extension-custom-provider-anthropic",
9
- "version": "0.79.4",
9
+ "version": "0.79.7",
10
10
  "dependencies": {
11
11
  "@anthropic-ai/sdk": "^0.52.0"
12
12
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "atomic-extension-custom-provider-anthropic",
3
3
  "private": true,
4
- "version": "0.79.4",
4
+ "version": "0.79.7",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "atomic-extension-custom-provider-gitlab-duo",
3
3
  "private": true,
4
- "version": "0.79.4",
4
+ "version": "0.79.7",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "atomic-extension-gondolin",
3
- "version": "0.79.4",
3
+ "version": "0.79.7",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "atomic-extension-gondolin",
9
- "version": "0.79.4",
9
+ "version": "0.79.7",
10
10
  "dependencies": {
11
11
  "@earendil-works/gondolin": "0.12.0"
12
12
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "atomic-extension-gondolin",
3
3
  "private": true,
4
- "version": "0.79.4",
4
+ "version": "0.79.7",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -42,7 +42,7 @@ import { existsSync, readFileSync } from "node:fs";
42
42
  import { join } from "node:path";
43
43
  import type { Api, Model } from "@earendil-works/pi-ai";
44
44
  import type { ExtensionAPI, ExtensionContext } from "@bastani/atomic";
45
- import { DynamicBorder, getAgentDir } from "@bastani/atomic";
45
+ import { CONFIG_DIR_NAME, DynamicBorder, getAgentDir } from "@bastani/atomic";
46
46
  import { Container, Key, type SelectItem, SelectList, Text } from "@earendil-works/pi-tui";
47
47
 
48
48
  // Preset configuration
@@ -69,7 +69,7 @@ interface PresetsConfig {
69
69
  */
70
70
  function loadPresets(cwd: string, includeProjectPresets: boolean): PresetsConfig {
71
71
  const globalPath = join(getAgentDir(), "presets.json");
72
- const projectPath = join(cwd, ".atomic", "presets.json");
72
+ const projectPath = join(cwd, CONFIG_DIR_NAME, "presets.json");
73
73
  const legacyProjectPath = join(cwd, ".pi", "presets.json");
74
74
 
75
75
  let globalPresets: PresetsConfig = {};
@@ -202,7 +202,10 @@ export default function presetExtension(pi: ExtensionAPI) {
202
202
  const presetNames = Object.keys(presets);
203
203
 
204
204
  if (presetNames.length === 0) {
205
- ctx.ui.notify("No presets defined. Add presets to ~/.atomic/agent/presets.json or .atomic/presets.json (legacy .pi/presets.json also works)", "warning");
205
+ ctx.ui.notify(
206
+ `No presets defined. Add presets to ${join(getAgentDir(), "presets.json")} or ${join(ctx.cwd, CONFIG_DIR_NAME, "presets.json")} (legacy ${join(ctx.cwd, ".pi", "presets.json")} also works)`,
207
+ "warning",
208
+ );
206
209
  return;
207
210
  }
208
211
 
@@ -310,7 +313,10 @@ export default function presetExtension(pi: ExtensionAPI) {
310
313
  async function cyclePreset(ctx: ExtensionContext): Promise<void> {
311
314
  const presetNames = getPresetOrder();
312
315
  if (presetNames.length === 0) {
313
- ctx.ui.notify("No presets defined. Add presets to ~/.atomic/agent/presets.json or .atomic/presets.json (legacy .pi/presets.json also works)", "warning");
316
+ ctx.ui.notify(
317
+ `No presets defined. Add presets to ${join(getAgentDir(), "presets.json")} or ${join(ctx.cwd, CONFIG_DIR_NAME, "presets.json")} (legacy ${join(ctx.cwd, ".pi", "presets.json")} also works)`,
318
+ "warning",
319
+ );
314
320
  return;
315
321
  }
316
322
 
@@ -1,18 +1,18 @@
1
1
  import { appendFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
- import type { ExtensionAPI } from "@bastani/atomic";
3
+ import { CONFIG_DIR_NAME, type ExtensionAPI } from "@bastani/atomic";
4
4
 
5
5
  export default function (pi: ExtensionAPI) {
6
- const logFile = join(process.cwd(), ".pi", "provider-payload.log");
7
-
8
- pi.on("before_provider_request", (event) => {
6
+ pi.on("before_provider_request", (event, ctx) => {
7
+ const logFile = join(ctx.cwd, CONFIG_DIR_NAME, "provider-payload.log");
9
8
  appendFileSync(logFile, `${JSON.stringify(event.payload, null, 2)}\n\n`, "utf8");
10
9
 
11
10
  // Optional: replace the payload instead of only logging it.
12
11
  // return { ...event.payload, temperature: 0 };
13
12
  });
14
13
 
15
- pi.on("after_provider_response", (event) => {
14
+ pi.on("after_provider_response", (event, ctx) => {
15
+ const logFile = join(ctx.cwd, CONFIG_DIR_NAME, "provider-payload.log");
16
16
  appendFileSync(logFile, `[${event.status}] ${JSON.stringify(event.headers)}\n\n`, "utf8");
17
17
  });
18
18
  }
@@ -46,7 +46,7 @@ import { existsSync, readFileSync } from "node:fs";
46
46
  import { join } from "node:path";
47
47
  import { SandboxManager, type SandboxRuntimeConfig } from "@anthropic-ai/sandbox-runtime";
48
48
  import type { ExtensionAPI } from "@bastani/atomic";
49
- import { type BashOperations, createBashTool, getAgentDir } from "@bastani/atomic";
49
+ import { type BashOperations, CONFIG_DIR_NAME, createBashTool, getAgentDir } from "@bastani/atomic";
50
50
 
51
51
  interface SandboxConfig extends SandboxRuntimeConfig {
52
52
  enabled?: boolean;
@@ -77,7 +77,7 @@ const DEFAULT_CONFIG: SandboxConfig = {
77
77
  };
78
78
 
79
79
  function loadConfig(cwd: string, includeProjectConfig: boolean): SandboxConfig {
80
- const projectConfigPath = join(cwd, ".atomic", "sandbox.json");
80
+ const projectConfigPath = join(cwd, CONFIG_DIR_NAME, "sandbox.json");
81
81
  const legacyProjectConfigPath = join(cwd, ".pi", "sandbox.json");
82
82
  const globalConfigPath = join(getAgentDir(), "extensions", "sandbox.json");
83
83
 
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "atomic-extension-sandbox",
3
- "version": "1.9.4",
3
+ "version": "1.9.7",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "atomic-extension-sandbox",
9
- "version": "1.9.4",
9
+ "version": "1.9.7",
10
10
  "dependencies": {
11
- "@anthropic-ai/sandbox-runtime": "^0.0.26"
11
+ "@anthropic-ai/sandbox-runtime": "0.0.26"
12
12
  }
13
13
  },
14
14
  "node_modules/@anthropic-ai/sandbox-runtime": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "atomic-extension-sandbox",
3
3
  "private": true,
4
- "version": "1.9.4",
4
+ "version": "1.9.7",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -9,7 +9,7 @@
9
9
  "check": "echo 'nothing to check'"
10
10
  },
11
11
  "dependencies": {
12
- "@anthropic-ai/sandbox-runtime": "^0.0.26"
12
+ "@anthropic-ai/sandbox-runtime": "0.0.26"
13
13
  },
14
14
  "atomic": {
15
15
  "extensions": [
@@ -4,7 +4,7 @@
4
4
 
5
5
  import * as fs from "node:fs";
6
6
  import * as path from "node:path";
7
- import { getAgentDir, parseFrontmatter } from "@bastani/atomic";
7
+ import { CONFIG_DIR_NAME, getAgentDir, parseFrontmatter } from "@bastani/atomic";
8
8
 
9
9
  export type AgentScope = "user" | "project" | "both";
10
10
 
@@ -85,7 +85,7 @@ function isDirectory(p: string): boolean {
85
85
  function findNearestProjectAgentsDir(cwd: string): string | null {
86
86
  let currentDir = cwd;
87
87
  while (true) {
88
- const atomicCandidate = path.join(currentDir, ".atomic", "agents");
88
+ const atomicCandidate = path.join(currentDir, CONFIG_DIR_NAME, "agents");
89
89
  if (isDirectory(atomicCandidate)) return atomicCandidate;
90
90
  const legacyCandidate = path.join(currentDir, ".pi", "agents");
91
91
  if (isDirectory(legacyCandidate)) return legacyCandidate;
@@ -21,7 +21,9 @@ import type { Message } from "@earendil-works/pi-ai";
21
21
  import { StringEnum } from "@earendil-works/pi-ai";
22
22
  import {
23
23
  APP_NAME,
24
+ CONFIG_DIR_NAME,
24
25
  type ExtensionAPI,
26
+ getAgentDir,
25
27
  getMarkdownTheme,
26
28
  withFileMutationQueue,
27
29
  } from "@bastani/atomic";
@@ -518,8 +520,8 @@ export default function (pi: ExtensionAPI) {
518
520
  description: [
519
521
  "Delegate tasks to specialized subagents with isolated context.",
520
522
  "Modes: single (agent + task), parallel (tasks array), chain (sequential with {previous} placeholder).",
521
- 'Default agent scope is "user" (from ~/.atomic/agent/agents).',
522
- 'To enable project-local agents in .atomic/agents (legacy .pi/agents also works), set agentScope: "both" (or "project").',
523
+ `Default agent scope is "user" (from ${path.join(getAgentDir(), "agents")}).`,
524
+ `To enable project-local agents in ${CONFIG_DIR_NAME}/agents (legacy .pi/agents also works), set agentScope: "both" (or "project").`,
523
525
  ].join(" "),
524
526
  parameters: SubagentParams,
525
527
 
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "atomic-extension-with-deps",
3
- "version": "0.79.4",
3
+ "version": "0.79.7",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "atomic-extension-with-deps",
9
- "version": "0.79.4",
9
+ "version": "0.79.7",
10
10
  "dependencies": {
11
11
  "ms": "^2.1.3"
12
12
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "atomic-extension-with-deps",
3
3
  "private": true,
4
- "version": "0.79.4",
4
+ "version": "0.79.7",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/atomic",
3
- "version": "0.8.31-alpha.1",
3
+ "version": "0.8.31-alpha.3",
4
4
  "description": "Atomic coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "atomicConfig": {
@@ -68,11 +68,11 @@
68
68
  "prepublishOnly": "bun run clean && bun run build"
69
69
  },
70
70
  "dependencies": {
71
- "@bastani/atomic-natives": "0.8.31-alpha.1",
71
+ "@bastani/atomic-natives": "0.8.31-alpha.3",
72
72
  "@bufbuild/protobuf": "^2.0.0",
73
- "@earendil-works/pi-agent-core": "^0.79.6",
74
- "@earendil-works/pi-ai": "^0.79.6",
75
- "@earendil-works/pi-tui": "^0.79.6",
73
+ "@earendil-works/pi-agent-core": "^0.79.7",
74
+ "@earendil-works/pi-ai": "^0.79.7",
75
+ "@earendil-works/pi-tui": "^0.79.7",
76
76
  "@modelcontextprotocol/ext-apps": "^1.7.2",
77
77
  "@modelcontextprotocol/sdk": "^1.25.1",
78
78
  "@mozilla/readability": "^0.6.0",