@bastani/atomic 0.9.29 → 0.9.30-alpha.2

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 (112) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/dist/builtin/intercom/package.json +1 -1
  3. package/dist/builtin/mcp/package.json +1 -1
  4. package/dist/builtin/subagents/package.json +1 -1
  5. package/dist/builtin/web-access/package.json +1 -1
  6. package/dist/builtin/workflows/package.json +1 -1
  7. package/dist/core/anthropic-thinking-guard.js.map +1 -1
  8. package/dist/core/extensions/loader-virtual-modules.d.ts.map +1 -1
  9. package/dist/core/extensions/loader-virtual-modules.js +6 -0
  10. package/dist/core/extensions/loader-virtual-modules.js.map +1 -1
  11. package/dist/core/http-dispatcher.d.ts +1 -1
  12. package/dist/core/http-dispatcher.d.ts.map +1 -1
  13. package/dist/core/http-dispatcher.js +2 -1
  14. package/dist/core/http-dispatcher.js.map +1 -1
  15. package/dist/core/key-id-schema.d.ts +6 -0
  16. package/dist/core/key-id-schema.d.ts.map +1 -0
  17. package/dist/core/key-id-schema.js +16 -0
  18. package/dist/core/key-id-schema.js.map +1 -0
  19. package/dist/core/keybindings-schema.d.ts +4 -0
  20. package/dist/core/keybindings-schema.d.ts.map +1 -0
  21. package/dist/core/keybindings-schema.js +20 -0
  22. package/dist/core/keybindings-schema.js.map +1 -0
  23. package/dist/core/keybindings.d.ts +226 -79
  24. package/dist/core/keybindings.d.ts.map +1 -1
  25. package/dist/core/keybindings.js +25 -20
  26. package/dist/core/keybindings.js.map +1 -1
  27. package/dist/core/model-config.d.ts +685 -164
  28. package/dist/core/model-config.d.ts.map +1 -1
  29. package/dist/core/model-config.js +22 -176
  30. package/dist/core/model-config.js.map +1 -1
  31. package/dist/core/project-trust.d.ts.map +1 -1
  32. package/dist/core/project-trust.js +2 -1
  33. package/dist/core/project-trust.js.map +1 -1
  34. package/dist/core/resource-loader-context-files.d.ts.map +1 -1
  35. package/dist/core/resource-loader-context-files.js +10 -6
  36. package/dist/core/resource-loader-context-files.js.map +1 -1
  37. package/dist/core/settings-defaults.d.ts +80 -0
  38. package/dist/core/settings-defaults.d.ts.map +1 -0
  39. package/dist/core/settings-defaults.js +81 -0
  40. package/dist/core/settings-defaults.js.map +1 -0
  41. package/dist/core/settings-manager-basic-accessors.d.ts.map +1 -1
  42. package/dist/core/settings-manager-basic-accessors.js +34 -29
  43. package/dist/core/settings-manager-basic-accessors.js.map +1 -1
  44. package/dist/core/settings-manager-resource-accessors.d.ts.map +1 -1
  45. package/dist/core/settings-manager-resource-accessors.js +10 -9
  46. package/dist/core/settings-manager-resource-accessors.js.map +1 -1
  47. package/dist/core/settings-manager-ui-accessors.d.ts.map +1 -1
  48. package/dist/core/settings-manager-ui-accessors.js +26 -18
  49. package/dist/core/settings-manager-ui-accessors.js.map +1 -1
  50. package/dist/core/settings-schema.d.ts +292 -0
  51. package/dist/core/settings-schema.d.ts.map +1 -0
  52. package/dist/core/settings-schema.js +403 -0
  53. package/dist/core/settings-schema.js.map +1 -0
  54. package/dist/core/settings-types.d.ts +2 -181
  55. package/dist/core/settings-types.d.ts.map +1 -1
  56. package/dist/core/settings-types.js.map +1 -1
  57. package/dist/extensions/codemode/index.d.ts.map +1 -1
  58. package/dist/extensions/codemode/index.js +2 -1
  59. package/dist/extensions/codemode/index.js.map +1 -1
  60. package/dist/extensions/codemode/tool.d.ts +1 -1
  61. package/dist/extensions/codemode/tool.d.ts.map +1 -1
  62. package/dist/extensions/codemode/tool.js +2 -1
  63. package/dist/extensions/codemode/tool.js.map +1 -1
  64. package/dist/extensions/herdr/index.d.ts.map +1 -1
  65. package/dist/extensions/herdr/index.js +4 -1
  66. package/dist/extensions/herdr/index.js.map +1 -1
  67. package/dist/modes/interactive/components/settings-selector-items.d.ts.map +1 -1
  68. package/dist/modes/interactive/components/settings-selector-items.js +2 -4
  69. package/dist/modes/interactive/components/settings-selector-items.js.map +1 -1
  70. package/dist/modes/interactive/components/settings-selector-submenus.d.ts.map +1 -1
  71. package/dist/modes/interactive/components/settings-selector-submenus.js +2 -1
  72. package/dist/modes/interactive/components/settings-selector-submenus.js.map +1 -1
  73. package/dist/modes/interactive/theme/catppuccin-frappe.json +1 -1
  74. package/dist/modes/interactive/theme/catppuccin-latte.json +1 -1
  75. package/dist/modes/interactive/theme/catppuccin-macchiato.json +1 -1
  76. package/dist/modes/interactive/theme/catppuccin-mocha.json +1 -1
  77. package/dist/modes/interactive/theme/dark.json +1 -1
  78. package/dist/modes/interactive/theme/light.json +1 -1
  79. package/dist/modes/interactive/theme/theme-class.d.ts +3 -12
  80. package/dist/modes/interactive/theme/theme-class.d.ts.map +1 -1
  81. package/dist/modes/interactive/theme/theme-class.js +2 -9
  82. package/dist/modes/interactive/theme/theme-class.js.map +1 -1
  83. package/dist/modes/interactive/theme/theme-loading.d.ts.map +1 -1
  84. package/dist/modes/interactive/theme/theme-loading.js +3 -21
  85. package/dist/modes/interactive/theme/theme-loading.js.map +1 -1
  86. package/dist/modes/interactive/theme/theme-parse.d.ts.map +1 -1
  87. package/dist/modes/interactive/theme/theme-parse.js +3 -0
  88. package/dist/modes/interactive/theme/theme-parse.js.map +1 -1
  89. package/dist/modes/interactive/theme/theme-schema.d.ts +5 -224
  90. package/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -1
  91. package/dist/modes/interactive/theme/theme-schema.js +47 -72
  92. package/dist/modes/interactive/theme/theme-schema.js.map +1 -1
  93. package/dist/modes/interactive/theme/theme-tokens.d.ts +262 -0
  94. package/dist/modes/interactive/theme/theme-tokens.d.ts.map +1 -0
  95. package/dist/modes/interactive/theme/theme-tokens.js +126 -0
  96. package/dist/modes/interactive/theme/theme-tokens.js.map +1 -0
  97. package/docs/compaction/reference.md +1 -1
  98. package/docs/compaction.md +2 -2
  99. package/docs/keybindings.md +2 -0
  100. package/docs/models.md +2 -0
  101. package/docs/providers.md +1 -1
  102. package/docs/settings.md +2 -0
  103. package/docs/themes/reference.md +2 -2
  104. package/docs/themes.md +3 -1
  105. package/examples/extensions/dynamic-resources/dynamic.json +1 -1
  106. package/npm-shrinkwrap.json +36 -36
  107. package/package.json +5 -3
  108. package/schemas/keybindings.schema.json +413 -0
  109. package/schemas/models.schema.json +1178 -0
  110. package/schemas/settings.schema.json +940 -0
  111. package/schemas/theme.schema.json +369 -0
  112. package/dist/modes/interactive/theme/theme-schema.json +0 -361
@@ -0,0 +1,262 @@
1
+ export interface ThemeTokenDescriptor {
2
+ slot: "foreground" | "background";
3
+ description: string;
4
+ /** Token in the same slot that supplies this token's color when a theme omits it. */
5
+ fallback?: string;
6
+ }
7
+ export type ThemeTokenDescriptors = Readonly<Record<string, ThemeTokenDescriptor>>;
8
+ /**
9
+ * Theme token metadata in the same order used by theme files and the published JSON Schema.
10
+ * A token with a `fallback` is optional: a theme written before the token existed keeps validating and
11
+ * keeps rendering with the fallback token's color.
12
+ */
13
+ export declare const THEME_TOKENS: {
14
+ readonly accent: {
15
+ readonly slot: "foreground";
16
+ readonly description: "Primary accent color (logo, selected items, cursor)";
17
+ };
18
+ readonly border: {
19
+ readonly slot: "foreground";
20
+ readonly description: "Normal borders";
21
+ };
22
+ readonly borderAccent: {
23
+ readonly slot: "foreground";
24
+ readonly description: "Highlighted borders";
25
+ };
26
+ readonly borderMuted: {
27
+ readonly slot: "foreground";
28
+ readonly description: "Subtle borders";
29
+ };
30
+ readonly success: {
31
+ readonly slot: "foreground";
32
+ readonly description: "Success states";
33
+ };
34
+ readonly error: {
35
+ readonly slot: "foreground";
36
+ readonly description: "Error states";
37
+ };
38
+ readonly warning: {
39
+ readonly slot: "foreground";
40
+ readonly description: "Warning states";
41
+ };
42
+ readonly muted: {
43
+ readonly slot: "foreground";
44
+ readonly description: "Secondary/dimmed text";
45
+ };
46
+ readonly dim: {
47
+ readonly slot: "foreground";
48
+ readonly description: "Very dimmed text (more subtle than muted)";
49
+ };
50
+ readonly text: {
51
+ readonly slot: "foreground";
52
+ readonly description: "Default text color (usually empty string)";
53
+ };
54
+ readonly thinkingText: {
55
+ readonly slot: "foreground";
56
+ readonly description: "Thinking block text color";
57
+ };
58
+ readonly selectedBg: {
59
+ readonly slot: "background";
60
+ readonly description: "Selected item background";
61
+ };
62
+ readonly scrollbarThumb: {
63
+ readonly slot: "background";
64
+ readonly description: "Fullscreen scrollbar thumb background (falls back to selectedBg when omitted)";
65
+ readonly fallback: "selectedBg";
66
+ };
67
+ readonly searchMatchBg: {
68
+ readonly slot: "background";
69
+ readonly description: "Transcript search match background and current-match text (falls back to selectedBg when omitted)";
70
+ readonly fallback: "selectedBg";
71
+ };
72
+ readonly searchMatchText: {
73
+ readonly slot: "foreground";
74
+ readonly description: "Transcript search match text and current-match background (falls back to text when omitted)";
75
+ readonly fallback: "text";
76
+ };
77
+ readonly userMessageBg: {
78
+ readonly slot: "background";
79
+ readonly description: "User message background";
80
+ };
81
+ readonly userMessageText: {
82
+ readonly slot: "foreground";
83
+ readonly description: "User message text color";
84
+ };
85
+ readonly customMessageBg: {
86
+ readonly slot: "background";
87
+ readonly description: "Custom message background (hook-injected messages)";
88
+ };
89
+ readonly customMessageText: {
90
+ readonly slot: "foreground";
91
+ readonly description: "Custom message text color";
92
+ };
93
+ readonly customMessageLabel: {
94
+ readonly slot: "foreground";
95
+ readonly description: "Custom message type label color";
96
+ };
97
+ readonly toolPendingBg: {
98
+ readonly slot: "background";
99
+ readonly description: "Tool execution box (pending state)";
100
+ };
101
+ readonly toolSuccessBg: {
102
+ readonly slot: "background";
103
+ readonly description: "Tool execution box (success state)";
104
+ };
105
+ readonly toolErrorBg: {
106
+ readonly slot: "background";
107
+ readonly description: "Tool execution box (error state)";
108
+ };
109
+ readonly toolTitle: {
110
+ readonly slot: "foreground";
111
+ readonly description: "Tool execution box title color";
112
+ };
113
+ readonly toolOutput: {
114
+ readonly slot: "foreground";
115
+ readonly description: "Tool execution box output text color";
116
+ };
117
+ readonly mdHeading: {
118
+ readonly slot: "foreground";
119
+ readonly description: "Markdown heading text";
120
+ };
121
+ readonly mdLink: {
122
+ readonly slot: "foreground";
123
+ readonly description: "Markdown link text";
124
+ };
125
+ readonly mdLinkUrl: {
126
+ readonly slot: "foreground";
127
+ readonly description: "Markdown link URL";
128
+ };
129
+ readonly mdCode: {
130
+ readonly slot: "foreground";
131
+ readonly description: "Markdown inline code";
132
+ };
133
+ readonly mdCodeBlock: {
134
+ readonly slot: "foreground";
135
+ readonly description: "Markdown code block content";
136
+ };
137
+ readonly mdCodeBlockBorder: {
138
+ readonly slot: "foreground";
139
+ readonly description: "Markdown code block fences";
140
+ };
141
+ readonly mdQuote: {
142
+ readonly slot: "foreground";
143
+ readonly description: "Markdown blockquote text";
144
+ };
145
+ readonly mdQuoteBorder: {
146
+ readonly slot: "foreground";
147
+ readonly description: "Markdown blockquote border";
148
+ };
149
+ readonly mdHr: {
150
+ readonly slot: "foreground";
151
+ readonly description: "Markdown horizontal rule";
152
+ };
153
+ readonly mdListBullet: {
154
+ readonly slot: "foreground";
155
+ readonly description: "Markdown list bullets/numbers";
156
+ };
157
+ readonly toolDiffAdded: {
158
+ readonly slot: "foreground";
159
+ readonly description: "Added lines in tool diffs";
160
+ };
161
+ readonly toolDiffRemoved: {
162
+ readonly slot: "foreground";
163
+ readonly description: "Removed lines in tool diffs";
164
+ };
165
+ readonly toolDiffContext: {
166
+ readonly slot: "foreground";
167
+ readonly description: "Context lines in tool diffs";
168
+ };
169
+ readonly syntaxComment: {
170
+ readonly slot: "foreground";
171
+ readonly description: "Syntax highlighting: comments";
172
+ };
173
+ readonly syntaxKeyword: {
174
+ readonly slot: "foreground";
175
+ readonly description: "Syntax highlighting: keywords";
176
+ };
177
+ readonly syntaxFunction: {
178
+ readonly slot: "foreground";
179
+ readonly description: "Syntax highlighting: function names";
180
+ };
181
+ readonly syntaxVariable: {
182
+ readonly slot: "foreground";
183
+ readonly description: "Syntax highlighting: variable names";
184
+ };
185
+ readonly syntaxString: {
186
+ readonly slot: "foreground";
187
+ readonly description: "Syntax highlighting: string literals";
188
+ };
189
+ readonly syntaxNumber: {
190
+ readonly slot: "foreground";
191
+ readonly description: "Syntax highlighting: number literals";
192
+ };
193
+ readonly syntaxType: {
194
+ readonly slot: "foreground";
195
+ readonly description: "Syntax highlighting: type names";
196
+ };
197
+ readonly syntaxOperator: {
198
+ readonly slot: "foreground";
199
+ readonly description: "Syntax highlighting: operators";
200
+ };
201
+ readonly syntaxPunctuation: {
202
+ readonly slot: "foreground";
203
+ readonly description: "Syntax highlighting: punctuation";
204
+ };
205
+ readonly thinkingOff: {
206
+ readonly slot: "foreground";
207
+ readonly description: "Thinking level border: off";
208
+ };
209
+ readonly thinkingMinimal: {
210
+ readonly slot: "foreground";
211
+ readonly description: "Thinking level border: minimal";
212
+ };
213
+ readonly thinkingLow: {
214
+ readonly slot: "foreground";
215
+ readonly description: "Thinking level border: low";
216
+ };
217
+ readonly thinkingMedium: {
218
+ readonly slot: "foreground";
219
+ readonly description: "Thinking level border: medium";
220
+ };
221
+ readonly thinkingHigh: {
222
+ readonly slot: "foreground";
223
+ readonly description: "Thinking level border: high";
224
+ };
225
+ readonly thinkingXhigh: {
226
+ readonly slot: "foreground";
227
+ readonly description: "Thinking level border: xhigh (OpenAI codex-max only)";
228
+ };
229
+ readonly bashMode: {
230
+ readonly slot: "foreground";
231
+ readonly description: "Editor border color in bash mode";
232
+ };
233
+ };
234
+ export type ThemeToken = keyof typeof THEME_TOKENS;
235
+ export type ThemeColor = {
236
+ [K in ThemeToken]: (typeof THEME_TOKENS)[K]["slot"] extends "foreground" ? K : never;
237
+ }[ThemeToken];
238
+ export type ThemeBg = Exclude<ThemeToken, ThemeColor>;
239
+ type OptionalToken = {
240
+ [K in ThemeToken]: (typeof THEME_TOKENS)[K] extends {
241
+ fallback: string;
242
+ } ? K : never;
243
+ }[ThemeToken];
244
+ type RequiredToken = Exclude<ThemeToken, OptionalToken>;
245
+ export type ThemeColorValues<Value> = {
246
+ [K in RequiredToken]: Value;
247
+ } & {
248
+ [K in OptionalToken]?: Value;
249
+ };
250
+ export type ResolvedThemeColorValues<Value> = Record<ThemeToken, Value>;
251
+ /** Fill omitted optional tokens from their fallback tokens. */
252
+ export declare function withThemeTokenFallbacks<Value>(values: ThemeColorValues<Value>): ResolvedThemeColorValues<Value>;
253
+ /**
254
+ * Split resolved token values into the foreground and background slots. Generated system themes also carry
255
+ * palette entries that theme files cannot set; those are not tokens and are left out.
256
+ */
257
+ export declare function splitThemeColors(colors: ResolvedThemeColorValues<string | number>): {
258
+ fgColors: Record<ThemeColor, string | number>;
259
+ bgColors: Record<ThemeBg, string | number>;
260
+ };
261
+ export {};
262
+ //# sourceMappingURL=theme-tokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-tokens.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/theme/theme-tokens.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,oBAAoB;IACpC,IAAI,EAAE,YAAY,GAAG,YAAY,CAAC;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,qFAAqF;IACrF,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC,CAAC;AAgBnF;;;;GAIG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmEvB,CAAC;AAEH,MAAM,MAAM,UAAU,GAAG,MAAM,OAAO,YAAY,CAAC;AACnD,MAAM,MAAM,UAAU,GAAG;KACvB,CAAC,IAAI,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,YAAY,GAAG,CAAC,GAAG,KAAK;CACpF,CAAC,UAAU,CAAC,CAAC;AACd,MAAM,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;AAEtD,KAAK,aAAa,GAAG;KACnB,CAAC,IAAI,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,CAAC,GAAG,KAAK;CACpF,CAAC,UAAU,CAAC,CAAC;AAEd,KAAK,aAAa,GAAG,OAAO,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAExD,MAAM,MAAM,gBAAgB,CAAC,KAAK,IAAI;KACpC,CAAC,IAAI,aAAa,GAAG,KAAK;CAC3B,GAAG;KACF,CAAC,IAAI,aAAa,CAAC,CAAC,EAAE,KAAK;CAC5B,CAAC;AAEF,MAAM,MAAM,wBAAwB,CAAC,KAAK,IAAI,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;AAExE,+DAA+D;AAC/D,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,gBAAgB,CAAC,KAAK,CAAC,GAAG,wBAAwB,CAAC,KAAK,CAAC,CAc/G;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,wBAAwB,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG;IACpF,QAAQ,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;IAC9C,QAAQ,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;CAC3C,CAaA"}
@@ -0,0 +1,126 @@
1
+ function defineThemeTokens(tokens) {
2
+ for (const [name, descriptor] of Object.entries(tokens)) {
3
+ if (descriptor.fallback === undefined)
4
+ continue;
5
+ const fallback = tokens[descriptor.fallback];
6
+ if (fallback === undefined) {
7
+ throw new Error(`Theme token ${name} has unknown fallback ${descriptor.fallback}`);
8
+ }
9
+ if (fallback.slot !== descriptor.slot) {
10
+ throw new Error(`Theme token ${name} has fallback ${descriptor.fallback} in a different color slot`);
11
+ }
12
+ }
13
+ return tokens;
14
+ }
15
+ /**
16
+ * Theme token metadata in the same order used by theme files and the published JSON Schema.
17
+ * A token with a `fallback` is optional: a theme written before the token existed keeps validating and
18
+ * keeps rendering with the fallback token's color.
19
+ */
20
+ export const THEME_TOKENS = defineThemeTokens({
21
+ accent: { slot: "foreground", description: "Primary accent color (logo, selected items, cursor)" },
22
+ border: { slot: "foreground", description: "Normal borders" },
23
+ borderAccent: { slot: "foreground", description: "Highlighted borders" },
24
+ borderMuted: { slot: "foreground", description: "Subtle borders" },
25
+ success: { slot: "foreground", description: "Success states" },
26
+ error: { slot: "foreground", description: "Error states" },
27
+ warning: { slot: "foreground", description: "Warning states" },
28
+ muted: { slot: "foreground", description: "Secondary/dimmed text" },
29
+ dim: { slot: "foreground", description: "Very dimmed text (more subtle than muted)" },
30
+ text: { slot: "foreground", description: "Default text color (usually empty string)" },
31
+ thinkingText: { slot: "foreground", description: "Thinking block text color" },
32
+ selectedBg: { slot: "background", description: "Selected item background" },
33
+ scrollbarThumb: {
34
+ slot: "background",
35
+ description: "Fullscreen scrollbar thumb background (falls back to selectedBg when omitted)",
36
+ fallback: "selectedBg",
37
+ },
38
+ searchMatchBg: {
39
+ slot: "background",
40
+ description: "Transcript search match background and current-match text (falls back to selectedBg when omitted)",
41
+ fallback: "selectedBg",
42
+ },
43
+ searchMatchText: {
44
+ slot: "foreground",
45
+ description: "Transcript search match text and current-match background (falls back to text when omitted)",
46
+ fallback: "text",
47
+ },
48
+ userMessageBg: { slot: "background", description: "User message background" },
49
+ userMessageText: { slot: "foreground", description: "User message text color" },
50
+ customMessageBg: { slot: "background", description: "Custom message background (hook-injected messages)" },
51
+ customMessageText: { slot: "foreground", description: "Custom message text color" },
52
+ customMessageLabel: { slot: "foreground", description: "Custom message type label color" },
53
+ toolPendingBg: { slot: "background", description: "Tool execution box (pending state)" },
54
+ toolSuccessBg: { slot: "background", description: "Tool execution box (success state)" },
55
+ toolErrorBg: { slot: "background", description: "Tool execution box (error state)" },
56
+ toolTitle: { slot: "foreground", description: "Tool execution box title color" },
57
+ toolOutput: { slot: "foreground", description: "Tool execution box output text color" },
58
+ mdHeading: { slot: "foreground", description: "Markdown heading text" },
59
+ mdLink: { slot: "foreground", description: "Markdown link text" },
60
+ mdLinkUrl: { slot: "foreground", description: "Markdown link URL" },
61
+ mdCode: { slot: "foreground", description: "Markdown inline code" },
62
+ mdCodeBlock: { slot: "foreground", description: "Markdown code block content" },
63
+ mdCodeBlockBorder: { slot: "foreground", description: "Markdown code block fences" },
64
+ mdQuote: { slot: "foreground", description: "Markdown blockquote text" },
65
+ mdQuoteBorder: { slot: "foreground", description: "Markdown blockquote border" },
66
+ mdHr: { slot: "foreground", description: "Markdown horizontal rule" },
67
+ mdListBullet: { slot: "foreground", description: "Markdown list bullets/numbers" },
68
+ toolDiffAdded: { slot: "foreground", description: "Added lines in tool diffs" },
69
+ toolDiffRemoved: { slot: "foreground", description: "Removed lines in tool diffs" },
70
+ toolDiffContext: { slot: "foreground", description: "Context lines in tool diffs" },
71
+ syntaxComment: { slot: "foreground", description: "Syntax highlighting: comments" },
72
+ syntaxKeyword: { slot: "foreground", description: "Syntax highlighting: keywords" },
73
+ syntaxFunction: { slot: "foreground", description: "Syntax highlighting: function names" },
74
+ syntaxVariable: { slot: "foreground", description: "Syntax highlighting: variable names" },
75
+ syntaxString: { slot: "foreground", description: "Syntax highlighting: string literals" },
76
+ syntaxNumber: { slot: "foreground", description: "Syntax highlighting: number literals" },
77
+ syntaxType: { slot: "foreground", description: "Syntax highlighting: type names" },
78
+ syntaxOperator: { slot: "foreground", description: "Syntax highlighting: operators" },
79
+ syntaxPunctuation: { slot: "foreground", description: "Syntax highlighting: punctuation" },
80
+ thinkingOff: { slot: "foreground", description: "Thinking level border: off" },
81
+ thinkingMinimal: { slot: "foreground", description: "Thinking level border: minimal" },
82
+ thinkingLow: { slot: "foreground", description: "Thinking level border: low" },
83
+ thinkingMedium: { slot: "foreground", description: "Thinking level border: medium" },
84
+ thinkingHigh: { slot: "foreground", description: "Thinking level border: high" },
85
+ thinkingXhigh: { slot: "foreground", description: "Thinking level border: xhigh (OpenAI codex-max only)" },
86
+ bashMode: { slot: "foreground", description: "Editor border color in bash mode" },
87
+ });
88
+ /** Fill omitted optional tokens from their fallback tokens. */
89
+ export function withThemeTokenFallbacks(values) {
90
+ const resolved = { ...values };
91
+ for (const [rawName, descriptor] of Object.entries(THEME_TOKENS)) {
92
+ if (!("fallback" in descriptor))
93
+ continue;
94
+ const name = rawName;
95
+ if (resolved[name] !== undefined)
96
+ continue;
97
+ const fallback = descriptor.fallback;
98
+ const fallbackValue = resolved[fallback];
99
+ if (fallbackValue === undefined) {
100
+ throw new Error(`Theme token ${rawName} has unresolved fallback ${descriptor.fallback}`);
101
+ }
102
+ resolved[name] = fallbackValue;
103
+ }
104
+ return resolved;
105
+ }
106
+ /**
107
+ * Split resolved token values into the foreground and background slots. Generated system themes also carry
108
+ * palette entries that theme files cannot set; those are not tokens and are left out.
109
+ */
110
+ export function splitThemeColors(colors) {
111
+ const fgColors = {};
112
+ const bgColors = {};
113
+ for (const [key, value] of Object.entries(colors)) {
114
+ const token = THEME_TOKENS[key];
115
+ if (token === undefined)
116
+ continue;
117
+ if (token.slot === "background") {
118
+ bgColors[key] = value;
119
+ }
120
+ else {
121
+ fgColors[key] = value;
122
+ }
123
+ }
124
+ return { fgColors, bgColors };
125
+ }
126
+ //# sourceMappingURL=theme-tokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-tokens.js","sourceRoot":"","sources":["../../../../src/modes/interactive/theme/theme-tokens.ts"],"names":[],"mappings":"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","sourcesContent":["export interface ThemeTokenDescriptor {\n\tslot: \"foreground\" | \"background\";\n\tdescription: string;\n\t/** Token in the same slot that supplies this token's color when a theme omits it. */\n\tfallback?: string;\n}\n\nexport type ThemeTokenDescriptors = Readonly<Record<string, ThemeTokenDescriptor>>;\n\nfunction defineThemeTokens<const T extends ThemeTokenDescriptors>(tokens: T): T {\n\tfor (const [name, descriptor] of Object.entries(tokens)) {\n\t\tif (descriptor.fallback === undefined) continue;\n\t\tconst fallback = tokens[descriptor.fallback];\n\t\tif (fallback === undefined) {\n\t\t\tthrow new Error(`Theme token ${name} has unknown fallback ${descriptor.fallback}`);\n\t\t}\n\t\tif (fallback.slot !== descriptor.slot) {\n\t\t\tthrow new Error(`Theme token ${name} has fallback ${descriptor.fallback} in a different color slot`);\n\t\t}\n\t}\n\treturn tokens;\n}\n\n/**\n * Theme token metadata in the same order used by theme files and the published JSON Schema.\n * A token with a `fallback` is optional: a theme written before the token existed keeps validating and\n * keeps rendering with the fallback token's color.\n */\nexport const THEME_TOKENS = defineThemeTokens({\n\taccent: { slot: \"foreground\", description: \"Primary accent color (logo, selected items, cursor)\" },\n\tborder: { slot: \"foreground\", description: \"Normal borders\" },\n\tborderAccent: { slot: \"foreground\", description: \"Highlighted borders\" },\n\tborderMuted: { slot: \"foreground\", description: \"Subtle borders\" },\n\tsuccess: { slot: \"foreground\", description: \"Success states\" },\n\terror: { slot: \"foreground\", description: \"Error states\" },\n\twarning: { slot: \"foreground\", description: \"Warning states\" },\n\tmuted: { slot: \"foreground\", description: \"Secondary/dimmed text\" },\n\tdim: { slot: \"foreground\", description: \"Very dimmed text (more subtle than muted)\" },\n\ttext: { slot: \"foreground\", description: \"Default text color (usually empty string)\" },\n\tthinkingText: { slot: \"foreground\", description: \"Thinking block text color\" },\n\tselectedBg: { slot: \"background\", description: \"Selected item background\" },\n\tscrollbarThumb: {\n\t\tslot: \"background\",\n\t\tdescription: \"Fullscreen scrollbar thumb background (falls back to selectedBg when omitted)\",\n\t\tfallback: \"selectedBg\",\n\t},\n\tsearchMatchBg: {\n\t\tslot: \"background\",\n\t\tdescription: \"Transcript search match background and current-match text (falls back to selectedBg when omitted)\",\n\t\tfallback: \"selectedBg\",\n\t},\n\tsearchMatchText: {\n\t\tslot: \"foreground\",\n\t\tdescription: \"Transcript search match text and current-match background (falls back to text when omitted)\",\n\t\tfallback: \"text\",\n\t},\n\tuserMessageBg: { slot: \"background\", description: \"User message background\" },\n\tuserMessageText: { slot: \"foreground\", description: \"User message text color\" },\n\tcustomMessageBg: { slot: \"background\", description: \"Custom message background (hook-injected messages)\" },\n\tcustomMessageText: { slot: \"foreground\", description: \"Custom message text color\" },\n\tcustomMessageLabel: { slot: \"foreground\", description: \"Custom message type label color\" },\n\ttoolPendingBg: { slot: \"background\", description: \"Tool execution box (pending state)\" },\n\ttoolSuccessBg: { slot: \"background\", description: \"Tool execution box (success state)\" },\n\ttoolErrorBg: { slot: \"background\", description: \"Tool execution box (error state)\" },\n\ttoolTitle: { slot: \"foreground\", description: \"Tool execution box title color\" },\n\ttoolOutput: { slot: \"foreground\", description: \"Tool execution box output text color\" },\n\tmdHeading: { slot: \"foreground\", description: \"Markdown heading text\" },\n\tmdLink: { slot: \"foreground\", description: \"Markdown link text\" },\n\tmdLinkUrl: { slot: \"foreground\", description: \"Markdown link URL\" },\n\tmdCode: { slot: \"foreground\", description: \"Markdown inline code\" },\n\tmdCodeBlock: { slot: \"foreground\", description: \"Markdown code block content\" },\n\tmdCodeBlockBorder: { slot: \"foreground\", description: \"Markdown code block fences\" },\n\tmdQuote: { slot: \"foreground\", description: \"Markdown blockquote text\" },\n\tmdQuoteBorder: { slot: \"foreground\", description: \"Markdown blockquote border\" },\n\tmdHr: { slot: \"foreground\", description: \"Markdown horizontal rule\" },\n\tmdListBullet: { slot: \"foreground\", description: \"Markdown list bullets/numbers\" },\n\ttoolDiffAdded: { slot: \"foreground\", description: \"Added lines in tool diffs\" },\n\ttoolDiffRemoved: { slot: \"foreground\", description: \"Removed lines in tool diffs\" },\n\ttoolDiffContext: { slot: \"foreground\", description: \"Context lines in tool diffs\" },\n\tsyntaxComment: { slot: \"foreground\", description: \"Syntax highlighting: comments\" },\n\tsyntaxKeyword: { slot: \"foreground\", description: \"Syntax highlighting: keywords\" },\n\tsyntaxFunction: { slot: \"foreground\", description: \"Syntax highlighting: function names\" },\n\tsyntaxVariable: { slot: \"foreground\", description: \"Syntax highlighting: variable names\" },\n\tsyntaxString: { slot: \"foreground\", description: \"Syntax highlighting: string literals\" },\n\tsyntaxNumber: { slot: \"foreground\", description: \"Syntax highlighting: number literals\" },\n\tsyntaxType: { slot: \"foreground\", description: \"Syntax highlighting: type names\" },\n\tsyntaxOperator: { slot: \"foreground\", description: \"Syntax highlighting: operators\" },\n\tsyntaxPunctuation: { slot: \"foreground\", description: \"Syntax highlighting: punctuation\" },\n\tthinkingOff: { slot: \"foreground\", description: \"Thinking level border: off\" },\n\tthinkingMinimal: { slot: \"foreground\", description: \"Thinking level border: minimal\" },\n\tthinkingLow: { slot: \"foreground\", description: \"Thinking level border: low\" },\n\tthinkingMedium: { slot: \"foreground\", description: \"Thinking level border: medium\" },\n\tthinkingHigh: { slot: \"foreground\", description: \"Thinking level border: high\" },\n\tthinkingXhigh: { slot: \"foreground\", description: \"Thinking level border: xhigh (OpenAI codex-max only)\" },\n\tbashMode: { slot: \"foreground\", description: \"Editor border color in bash mode\" },\n});\n\nexport type ThemeToken = keyof typeof THEME_TOKENS;\nexport type ThemeColor = {\n\t[K in ThemeToken]: (typeof THEME_TOKENS)[K][\"slot\"] extends \"foreground\" ? K : never;\n}[ThemeToken];\nexport type ThemeBg = Exclude<ThemeToken, ThemeColor>;\n\ntype OptionalToken = {\n\t[K in ThemeToken]: (typeof THEME_TOKENS)[K] extends { fallback: string } ? K : never;\n}[ThemeToken];\n\ntype RequiredToken = Exclude<ThemeToken, OptionalToken>;\n\nexport type ThemeColorValues<Value> = {\n\t[K in RequiredToken]: Value;\n} & {\n\t[K in OptionalToken]?: Value;\n};\n\nexport type ResolvedThemeColorValues<Value> = Record<ThemeToken, Value>;\n\n/** Fill omitted optional tokens from their fallback tokens. */\nexport function withThemeTokenFallbacks<Value>(values: ThemeColorValues<Value>): ResolvedThemeColorValues<Value> {\n\tconst resolved = { ...values } as Partial<ResolvedThemeColorValues<Value>>;\n\tfor (const [rawName, descriptor] of Object.entries(THEME_TOKENS)) {\n\t\tif (!(\"fallback\" in descriptor)) continue;\n\t\tconst name = rawName as ThemeToken;\n\t\tif (resolved[name] !== undefined) continue;\n\t\tconst fallback = descriptor.fallback as ThemeToken;\n\t\tconst fallbackValue = resolved[fallback];\n\t\tif (fallbackValue === undefined) {\n\t\t\tthrow new Error(`Theme token ${rawName} has unresolved fallback ${descriptor.fallback}`);\n\t\t}\n\t\tresolved[name] = fallbackValue;\n\t}\n\treturn resolved as ResolvedThemeColorValues<Value>;\n}\n\n/**\n * Split resolved token values into the foreground and background slots. Generated system themes also carry\n * palette entries that theme files cannot set; those are not tokens and are left out.\n */\nexport function splitThemeColors(colors: ResolvedThemeColorValues<string | number>): {\n\tfgColors: Record<ThemeColor, string | number>;\n\tbgColors: Record<ThemeBg, string | number>;\n} {\n\tconst fgColors = {} as Record<ThemeColor, string | number>;\n\tconst bgColors = {} as Record<ThemeBg, string | number>;\n\tfor (const [key, value] of Object.entries(colors)) {\n\t\tconst token: ThemeTokenDescriptor | undefined = THEME_TOKENS[key as ThemeToken];\n\t\tif (token === undefined) continue;\n\t\tif (token.slot === \"background\") {\n\t\t\tbgColors[key as ThemeBg] = value;\n\t\t} else {\n\t\t\tfgColors[key as ThemeColor] = value;\n\t\t}\n\t}\n\treturn { fgColors, bgColors };\n}\n"]}
@@ -259,7 +259,7 @@ Configure compaction in `~/.atomic/agent/settings.json` or `<project-dir>/.atomi
259
259
  | `enabled` | `true` | Enable automatic Verbatim Compaction. |
260
260
  | `reserveTokens` | `16384` | Tokens to reserve for the next LLM response; threshold auto-compaction starts when completed-response usage or a prospective post-tool context exceeds the model's effective input budget minus this reserve. It is an **input-side** reserve only and never caps planner output. |
261
261
 
262
- The top-level `compactionModel` setting defaults to `"auto"`, using the session model. An exact registered chat-model, classifier, or compactor ID selects a separate compactor. Project settings may not select `morph/*`. See [Compaction model](/compaction#compaction-model).
262
+ The top-level `compactionModel` setting defaults to `"auto"`, using the session model. An exact registered chat-model, classifier, or compactor ID selects a separate compactor. See [Compaction model](/compaction#compaction-model).
263
263
 
264
264
  Fallback borrowing reuses `settings.fallbackModels`, the same ordered `provider/model[:thinkingLevel]` list used for chat fallback. It skips entries equal to the selected compaction model. A policy refusal from any chat compaction model, including `auto`, explicit chat-model IDs, and borrowed fallback entries, first tries pi's summary compaction on the same model. Classifier and Morph refusals skip summary fallback and advance directly to the next configured model. Other failures and failed summaries also advance to the next configured model. Only load-bearing recovery may clear older context after all attempts fail.
265
265
 
@@ -100,13 +100,13 @@ You can also set `compactionModel` in `~/.atomic/agent/settings.json` or a trust
100
100
  }
101
101
  ```
102
102
 
103
- The default, `auto`, or an empty value uses the current session model, including Anthropic models. An exact registered chat-model ID selects that model just for compaction. Registered classifiers and Morph compactors are also selectable. Project settings cannot select `morph/*`; choose Morph globally instead.
103
+ The default, `auto`, or an empty value uses the current session model, including Anthropic models. An exact registered chat-model ID selects that model just for compaction. Registered classifiers and Morph compactors are also selectable, in global or trusted project settings.
104
104
 
105
105
  An explicit compaction model can send the compactable transcript to a different provider, using that provider's credentials. Choose only providers permitted to receive your conversation. Changing `compactionModel` does not affect branch summaries. SDK and extension code can pick a model for a single run with `session.compact({ compactionModel })` or `ctx.compact({ compactionModel })`, which leaves the setting unchanged.
106
106
 
107
107
  For classifier compaction, log in with `/login typesafe`, then set `"compactionModel": "typesafe/jev-latest"`. The classifier scores groups of transcript lines; Atomic removes lower-scored groups without rewriting the rest. Protected lines and the recent tail are not sent for scoring. If scoring fails, Atomic tries your fallback models. Group boundaries can make the retained fraction differ from the requested compression ratio.
108
108
 
109
- For Morph compaction, use `/login morph` or set `MORPH_API_KEY`, then choose `morph/morph-compactor` in the global selector or settings file. Without a credential, the selector marks Morph as `requires /login morph`. Morph receives the compactable transcript, including serialized thinking, but not the recent tail. Atomic reconstructs surviving lines from the originals and preserves `<keepContext>` spans. Morph is not a chat-model choice.
109
+ For Morph compaction, use `/login morph` or set `MORPH_API_KEY`, then choose `morph/morph-compactor` in the selector or a settings file. Without a credential, the selector marks Morph as `requires /login morph`. Morph receives the compactable transcript, including serialized thinking, but not the recent tail. Atomic reconstructs surviving lines from the originals and preserves `<keepContext>` spans. Morph is not a chat-model choice.
110
110
 
111
111
  The compaction card shows the backend and model that produced the result, such as `classifier · typesafe/jev-latest` or `morph · morph/morph-compactor`. A policy-refusal summary appears as `summary (pi fallback)`.
112
112
 
@@ -8,6 +8,8 @@ Older configs using pre-namespaced ids such as `cursorUp` or `expandTools` are m
8
8
 
9
9
  After editing `keybindings.json`, run `/reload` in Atomic to apply the changes without restarting the session.
10
10
 
11
+ For editor completion of every action id and validation of key syntax, add `"$schema": "https://raw.githubusercontent.com/bastani-inc/atomic/main/packages/coding-agent/schemas/keybindings.schema.json"` to `keybindings.json`. Atomic ignores `$schema` when it loads your bindings.
12
+
11
13
  ## Workflow widget scrolling
12
14
 
13
15
  `app.workflows.scrollUp` defaults to `["alt+k", "alt+pageUp"]`; `app.workflows.scrollDown` defaults to `["alt+j", "alt+pageDown"]`. These scroll the main-chat workflow list without leaving the editor. Any other configured editor binding takes precedence, including the Vim Alt+J/K cursor bindings. Alt+Up remains available for queued messages.
package/docs/models.md CHANGED
@@ -15,6 +15,8 @@ If refresh times out or fails, the selector reports that it is using cached mode
15
15
 
16
16
  A complete `defaultProvider`/`defaultModel` pair in `settings.json` is resolved after built-in, configured, and extension providers register. If the provider remains unsupported, interactive mode reports a generic saved-configuration warning and leaves model selection open instead of routing the session to a different provider. Print and JSON modes write that diagnostic to stderr and exit nonzero before prompting, keeping JSON stdout JSONL-clean. RPC rejects `prompt` with the same correlated diagnostic until an explicit successful `set_model` selects an available model or an explicit model cycle returns a different available model. A null or unchanged cycle result does not clear the condition. If the provider is supported but the model is unknown or lacks authentication, normal automatic selection of an available authenticated model continues. Valid custom- and extension-provider defaults resolve once their provider registration is available. See [Settings](/settings#model-&-thinking).
17
17
 
18
+ For editor completion and validation of providers, models, and `compat` fields, add `"$schema": "https://raw.githubusercontent.com/bastani-inc/atomic/main/packages/coding-agent/schemas/models.schema.json"` to `models.json`.
19
+
18
20
  ## Where to go next
19
21
 
20
22
  This page shows minimal and full `models.json` examples you can copy. Every field, override, derived variant, and API compatibility contract lives in the [Model configuration reference](/models/reference).
package/docs/providers.md CHANGED
@@ -626,7 +626,7 @@ Use `/login morph` to save a Morph API key under `morph` in `~/.atomic/agent/aut
626
626
 
627
627
  Then choose `morph/morph-compactor` through `/settings` → **Compaction model**, or set `"compactionModel": "morph/morph-compactor"` in global settings. Without credentials, the selector marks it as `requires /login morph`. Morph receives the compactable transcript, including serialized thinking; the preserved recent tail is not sent. Atomic retains the original surviving lines and enforces `<keepContext>` protection. Choose Morph only if it is permitted to receive your transcript.
628
628
 
629
- Morph is a compactor, not a chat model. It does not appear in `/model` or automatic model routing. Project settings cannot select `morph/*`. Missing credentials, HTTP errors, policy refusals, or unusable results advance directly to your configured fallback models without a Morph summary request. `/logout morph` removes the saved credential; an environment key remains active until you unset it. See [Compaction model](/compaction#compaction-model).
629
+ Morph is a compactor, not a chat model. It does not appear in `/model` or automatic model routing. Missing credentials, HTTP errors, policy refusals, or unusable results advance directly to your configured fallback models without a Morph summary request. `/logout morph` removes the saved credential; an environment key remains active until you unset it. See [Compaction model](/compaction#compaction-model).
630
630
 
631
631
  ## Custom Providers
632
632
 
package/docs/settings.md CHANGED
@@ -9,6 +9,8 @@ Atomic uses JSON settings files with project settings overriding global settings
9
9
 
10
10
  Edit directly or use `/settings` for common options. Choosing a model or thinking level with `/model`, `/thinking`, or their cycling shortcuts automatically saves it as the startup default. Thinking choices also update the active model's saved thinking level. `/scoped-models` saves cycle-list changes automatically. SDK calls, session restoration, and automatic fallbacks do not overwrite these defaults unless persistence is explicitly requested. Atomic also reads legacy `~/.pi/agent/settings.json` and `.pi/settings.json` as compatibility fallbacks, with `.atomic` paths taking precedence.
11
11
 
12
+ For editor completion and validation, add `"$schema": "https://raw.githubusercontent.com/bastani-inc/atomic/main/packages/coding-agent/schemas/settings.schema.json"` to `settings.json`. Atomic preserves `$schema` and settings it does not recognize, such as extension settings, when it saves.
13
+
12
14
  Saving an Atomic setting applies only the changed fields to the corresponding `.atomic` file; it does not copy untouched fallback fields out of `.pi`. To intentionally override an inherited array such as `packages`, set it in `.atomic`, including an explicit empty array (`"packages": []`) when the inherited list should be disabled.
13
15
 
14
16
  ## On this page and its guide
@@ -9,7 +9,7 @@ description: Theme file format, every color token, and accepted color values.
9
9
 
10
10
  ```json
11
11
  {
12
- "$schema": "https://raw.githubusercontent.com/bastani-inc/atomic/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
12
+ "$schema": "https://raw.githubusercontent.com/bastani-inc/atomic/main/packages/coding-agent/schemas/theme.schema.json",
13
13
  "name": "my-theme",
14
14
  "vars": {
15
15
  "blue": "#0066cc",
@@ -40,7 +40,7 @@ description: Theme file format, every color token, and accepted color values.
40
40
  - When an index from 0 through 15 seeds an omitted tone, Atomic mixes from its built-in approximation of the common ANSI RGB value. The terminal still controls the explicit index's actual appearance.
41
41
  - Both explicit and derived tones update on theme hot reload.
42
42
 
43
- The `$schema` field enables editor auto-completion and validation.
43
+ The `$schema` field enables editor auto-completion and validation against the [theme JSON schema](https://github.com/bastani-inc/atomic/blob/main/packages/coding-agent/schemas/theme.schema.json). Atomic itself rejects theme files with unknown top-level fields or unknown properties under `colors`, `workingIndicator`, or `export`; define reusable custom colors under `vars` instead.
44
44
 
45
45
  ## Color Tokens
46
46
 
package/docs/themes.md CHANGED
@@ -80,7 +80,7 @@ vim ~/.atomic/agent/themes/my-theme.json
80
80
 
81
81
  ```json
82
82
  {
83
- "$schema": "https://raw.githubusercontent.com/bastani-inc/atomic/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
83
+ "$schema": "https://raw.githubusercontent.com/bastani-inc/atomic/main/packages/coding-agent/schemas/theme.schema.json",
84
84
  "name": "my-theme",
85
85
  "vars": {
86
86
  "primary": "#00aaff",
@@ -147,6 +147,8 @@ vim ~/.atomic/agent/themes/my-theme.json
147
147
 
148
148
  Atomic automatically reloads the active custom theme when you edit its file, so you can see changes immediately.
149
149
 
150
+ Theme files are strict. Atomic accepts only the documented top-level fields and color tokens; custom keys under `colors`, `workingIndicator`, or `export` and extra top-level metadata make the theme invalid. Define reusable custom colors under `vars`. The [theme JSON schema](https://github.com/bastani-inc/atomic/blob/main/packages/coding-agent/schemas/theme.schema.json) lists every accepted property, the required colors, and the accepted value types. Atomic reports invalid theme files during startup and `/reload`.
151
+
150
152
  ## Theme Format
151
153
 
152
154
  Moved to [Theme reference](/themes/reference#theme-format).
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
2
+ "$schema": "https://raw.githubusercontent.com/bastani-inc/atomic/main/packages/coding-agent/schemas/theme.schema.json",
3
3
  "name": "dynamic-resources",
4
4
  "vars": {
5
5
  "cyan": "#00d7ff",