claude-code-extensions 0.1.0 → 0.1.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 (115) hide show
  1. package/dist/ast.d.ts +43 -0
  2. package/dist/ast.js +308 -0
  3. package/dist/ast.js.map +1 -0
  4. package/dist/cli-list.d.ts +5 -0
  5. package/dist/cli-list.js +33 -0
  6. package/dist/cli-list.js.map +1 -0
  7. package/dist/cli-reload.d.ts +7 -0
  8. package/dist/cli-reload.js +24 -0
  9. package/dist/cli-reload.js.map +1 -0
  10. package/dist/cli-setup.d.ts +14 -0
  11. package/dist/cli-setup.js +110 -0
  12. package/dist/cli-setup.js.map +1 -0
  13. package/dist/cli.d.ts +14 -0
  14. package/dist/cli.js +183 -0
  15. package/dist/cli.js.map +1 -0
  16. package/dist/patch-worker.d.ts +6 -0
  17. package/dist/patch-worker.js +27 -0
  18. package/dist/patch-worker.js.map +1 -0
  19. package/dist/patches/always-show-context.d.ts +23 -0
  20. package/dist/patches/always-show-context.js +97 -0
  21. package/dist/patches/always-show-context.js.map +1 -0
  22. package/dist/patches/always-show-thinking.d.ts +18 -0
  23. package/dist/patches/always-show-thinking.js +55 -0
  24. package/dist/patches/always-show-thinking.js.map +1 -0
  25. package/dist/patches/banner.d.ts +10 -0
  26. package/dist/patches/banner.js +105 -0
  27. package/dist/patches/banner.js.map +1 -0
  28. package/dist/patches/cd-command.d.ts +16 -0
  29. package/dist/patches/cd-command.js +89 -0
  30. package/dist/patches/cd-command.js.map +1 -0
  31. package/dist/patches/cx-badge.d.ts +10 -0
  32. package/dist/patches/cx-badge.js +115 -0
  33. package/dist/patches/cx-badge.js.map +1 -0
  34. package/dist/patches/cx-resume-commands.d.ts +14 -0
  35. package/dist/patches/cx-resume-commands.js +53 -0
  36. package/dist/patches/cx-resume-commands.js.map +1 -0
  37. package/dist/patches/disable-paste-collapse.d.ts +16 -0
  38. package/dist/patches/disable-paste-collapse.js +49 -0
  39. package/dist/patches/disable-paste-collapse.js.map +1 -0
  40. package/dist/patches/disable-telemetry.d.ts +13 -0
  41. package/dist/patches/disable-telemetry.js +76 -0
  42. package/dist/patches/disable-telemetry.js.map +1 -0
  43. package/{patches/index.js → dist/patches/index.d.ts} +2 -0
  44. package/dist/patches/index.js +20 -0
  45. package/dist/patches/index.js.map +1 -0
  46. package/dist/patches/no-attribution.d.ts +15 -0
  47. package/dist/patches/no-attribution.js +42 -0
  48. package/dist/patches/no-attribution.js.map +1 -0
  49. package/dist/patches/no-feedback.d.ts +12 -0
  50. package/dist/patches/no-feedback.js +31 -0
  51. package/dist/patches/no-feedback.js.map +1 -0
  52. package/dist/patches/no-npm-warning.d.ts +9 -0
  53. package/dist/patches/no-npm-warning.js +31 -0
  54. package/dist/patches/no-npm-warning.js.map +1 -0
  55. package/dist/patches/no-tips.d.ts +10 -0
  56. package/dist/patches/no-tips.js +26 -0
  57. package/dist/patches/no-tips.js.map +1 -0
  58. package/dist/patches/persist-max-effort.d.ts +15 -0
  59. package/dist/patches/persist-max-effort.js +75 -0
  60. package/dist/patches/persist-max-effort.js.map +1 -0
  61. package/dist/patches/queue.d.ts +10 -0
  62. package/dist/patches/queue.js +202 -0
  63. package/dist/patches/queue.js.map +1 -0
  64. package/dist/patches/random-clawd.d.ts +9 -0
  65. package/dist/patches/random-clawd.js +49 -0
  66. package/dist/patches/random-clawd.js.map +1 -0
  67. package/dist/patches/reload.d.ts +10 -0
  68. package/dist/patches/reload.js +50 -0
  69. package/dist/patches/reload.js.map +1 -0
  70. package/dist/patches/show-file-in-collapsed-read.d.ts +17 -0
  71. package/dist/patches/show-file-in-collapsed-read.js +151 -0
  72. package/dist/patches/show-file-in-collapsed-read.js.map +1 -0
  73. package/dist/patches/simple-spinner.d.ts +12 -0
  74. package/dist/patches/simple-spinner.js +31 -0
  75. package/dist/patches/simple-spinner.js.map +1 -0
  76. package/dist/patches/swap-enter-submit.d.ts +26 -0
  77. package/dist/patches/swap-enter-submit.js +155 -0
  78. package/dist/patches/swap-enter-submit.js.map +1 -0
  79. package/dist/setup.d.ts +11 -0
  80. package/dist/setup.js +268 -0
  81. package/dist/setup.js.map +1 -0
  82. package/dist/transform-worker.d.ts +10 -0
  83. package/dist/transform-worker.js +35 -0
  84. package/dist/transform-worker.js.map +1 -0
  85. package/dist/transform.d.ts +12 -0
  86. package/dist/transform.js +83 -0
  87. package/dist/transform.js.map +1 -0
  88. package/dist/types.d.ts +105 -0
  89. package/dist/types.js +8 -0
  90. package/dist/types.js.map +1 -0
  91. package/package.json +19 -11
  92. package/ast.js +0 -276
  93. package/cx +0 -228
  94. package/cx-setup +0 -101
  95. package/patch-worker.js +0 -31
  96. package/patches/always-show-context.js +0 -123
  97. package/patches/always-show-thinking.js +0 -65
  98. package/patches/banner.js +0 -58
  99. package/patches/cd-command.js +0 -104
  100. package/patches/cx-badge.js +0 -112
  101. package/patches/cx-resume-commands.js +0 -58
  102. package/patches/disable-paste-collapse.js +0 -52
  103. package/patches/disable-telemetry.js +0 -84
  104. package/patches/no-attribution.js +0 -55
  105. package/patches/no-npm-warning.js +0 -32
  106. package/patches/no-tips.js +0 -29
  107. package/patches/persist-max-effort.js +0 -70
  108. package/patches/queue.js +0 -215
  109. package/patches/random-clawd.js +0 -52
  110. package/patches/reload.js +0 -68
  111. package/patches/show-file-in-collapsed-read.js +0 -178
  112. package/patches/swap-enter-submit.js +0 -188
  113. package/setup.js +0 -222
  114. package/transform-worker.js +0 -38
  115. package/transform.js +0 -99
package/dist/cli.js ADDED
@@ -0,0 +1,183 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * cx — Claude Code Extensions
4
+ *
5
+ * Pure drop-in replacement for `claude`. Applies enabled patches at runtime
6
+ * via AST transformation. The original cli.js is never modified.
7
+ * All arguments pass through to claude untouched.
8
+ *
9
+ * Related commands:
10
+ * cx-setup — interactive patch configurator
11
+ * cx-list — show patch status
12
+ * cx-reload — signal a running cx instance to reload Claude
13
+ */
14
+ import { existsSync, readFileSync, writeFileSync, statSync, mkdirSync, unlinkSync } from 'fs';
15
+ import { execSync, spawn as nodeSpawn } from 'child_process';
16
+ import { resolve, dirname } from 'path';
17
+ import { fileURLToPath } from 'url';
18
+ import { transformAsync, listPatches } from './transform.js';
19
+ const __dirname = dirname(fileURLToPath(import.meta.url));
20
+ const CONFIG_PATH = resolve(__dirname, '..', '.cx-patches.json');
21
+ const cacheDir = resolve(__dirname, '..', '.cache');
22
+ const cachedCliPath = resolve(cacheDir, 'cli.mjs');
23
+ const metaPath = resolve(cacheDir, 'meta.json');
24
+ const PID_FILE = resolve(__dirname, '..', '.cx-pid');
25
+ const RELOAD_EXIT_CODE = 75;
26
+ // ── Config ───────────────────────────────────────────────────────────────
27
+ function loadConfig() {
28
+ if (!existsSync(CONFIG_PATH))
29
+ return null;
30
+ try {
31
+ return JSON.parse(readFileSync(CONFIG_PATH, 'utf-8'));
32
+ }
33
+ catch {
34
+ return null;
35
+ }
36
+ }
37
+ function getEnabledPatches() {
38
+ const config = loadConfig();
39
+ const all = listPatches();
40
+ if (!config?.patches)
41
+ return all.map(p => p.id);
42
+ return all.filter((p) => {
43
+ if (p.id in config.patches)
44
+ return config.patches[p.id] !== false;
45
+ return p.defaultEnabled !== false;
46
+ }).map(p => p.id);
47
+ }
48
+ // ── First run ────────────────────────────────────────────────────────────
49
+ if (!existsSync(CONFIG_PATH)) {
50
+ if (process.stdin.isTTY) {
51
+ const { default: setup } = await import('./setup.js');
52
+ await setup({ firstRun: true });
53
+ }
54
+ else {
55
+ process.stderr.write('\x1b[2mcx: first run — all patches enabled. run cx setup to configure.\x1b[0m\n');
56
+ }
57
+ }
58
+ // ── Locate cli.js ────────────────────────────────────────────────────────
59
+ let cliPath;
60
+ try {
61
+ const npmRoot = execSync('npm root -g', { encoding: 'utf-8' }).trim();
62
+ cliPath = resolve(npmRoot, '@anthropic-ai/claude-code/cli.js');
63
+ }
64
+ catch { /* fallthrough */ }
65
+ if (!cliPath || !existsSync(cliPath)) {
66
+ console.error('cx: could not find @anthropic-ai/claude-code. Install it:');
67
+ console.error(' npm install -g @anthropic-ai/claude-code');
68
+ process.exit(1);
69
+ }
70
+ // ── Cache ────────────────────────────────────────────────────────────────
71
+ async function ensureCache() {
72
+ const enabled = getEnabledPatches();
73
+ const stat = statSync(cliPath);
74
+ const key = `${stat.size}:${stat.mtimeMs}:${[...enabled].sort().join(',')}`;
75
+ let valid = false;
76
+ if (existsSync(cachedCliPath) && existsSync(metaPath)) {
77
+ try {
78
+ valid = JSON.parse(readFileSync(metaPath, 'utf-8')).key === key;
79
+ }
80
+ catch { }
81
+ }
82
+ if (!valid) {
83
+ const t0 = performance.now();
84
+ const total = enabled.length;
85
+ // Line 0: prepare with elapsed timer, Lines 1..N: patch checklist
86
+ process.stderr.write(`\x1b[2m ◇ preparing (0s)\x1b[0m\n`);
87
+ for (const id of enabled) {
88
+ process.stderr.write(`\x1b[2m ◻ ${id}\x1b[0m\n`);
89
+ }
90
+ const timer = setInterval(() => {
91
+ const elapsed = ((performance.now() - t0) / 1000).toFixed(1);
92
+ const up = total + 1;
93
+ process.stderr.write(`\x1b[${up}A\r\x1b[2m ◇ preparing (${elapsed}s)\x1b[0m\x1b[K\x1b[${up}B\r`);
94
+ }, 100);
95
+ const original = readFileSync(cliPath, 'utf-8');
96
+ const patched = await transformAsync(original, enabled, {
97
+ onReady() {
98
+ clearInterval(timer);
99
+ const up = total + 1;
100
+ const elapsed = ((performance.now() - t0) / 1000).toFixed(1);
101
+ process.stderr.write(`\x1b[${up}A\r\x1b[2m ◇ ready (${elapsed}s)\x1b[0m\x1b[K\x1b[${up}B\r`);
102
+ },
103
+ onDone(id) {
104
+ const idx = enabled.indexOf(id);
105
+ const up = total - idx;
106
+ process.stderr.write(`\x1b[${up}A\r\x1b[32m ✔ ${id}\x1b[0m\x1b[K\x1b[${up}B\r`);
107
+ },
108
+ });
109
+ // Replace prepare line with summary
110
+ const up = total + 1;
111
+ process.stderr.write(`\x1b[${up}A\r\x1b[2m ◆ ${total} patches applied (${((performance.now() - t0) / 1000).toFixed(1)}s)\x1b[0m\x1b[K\x1b[${up}B\r`);
112
+ mkdirSync(cacheDir, { recursive: true });
113
+ writeFileSync(cachedCliPath, patched);
114
+ writeFileSync(metaPath, JSON.stringify({ key, ts: new Date().toISOString() }));
115
+ }
116
+ }
117
+ // ── PID file ─────────────────────────────────────────────────────────────
118
+ writeFileSync(PID_FILE, String(process.pid));
119
+ function cleanPid() { try {
120
+ unlinkSync(PID_FILE);
121
+ }
122
+ catch { } }
123
+ process.on('exit', cleanPid);
124
+ // ── Reload loop ──────────────────────────────────────────────────────────
125
+ let child = null;
126
+ let shouldReload = false;
127
+ process.on('SIGUSR1', () => {
128
+ shouldReload = true;
129
+ if (child)
130
+ child.kill('SIGTERM');
131
+ });
132
+ // Let child handle Ctrl+C — don't let it kill the wrapper
133
+ process.on('SIGINT', () => {
134
+ if (!child) {
135
+ cleanPid();
136
+ process.exit(130);
137
+ }
138
+ });
139
+ process.on('SIGTERM', () => {
140
+ if (child)
141
+ child.kill('SIGTERM');
142
+ cleanPid();
143
+ process.exit(143);
144
+ });
145
+ /**
146
+ * Build args for a reload: strip --continue/--resume, prepend --continue.
147
+ */
148
+ function reloadArgs(original) {
149
+ const skip = new Set(['--continue', '-c', '--resume', '-r']);
150
+ const result = ['--continue'];
151
+ for (let i = 0; i < original.length; i++) {
152
+ if (skip.has(original[i])) {
153
+ // --resume/-r may have an optional value; skip it too
154
+ if ((original[i] === '--resume' || original[i] === '-r') &&
155
+ i + 1 < original.length && !original[i + 1].startsWith('-')) {
156
+ i++;
157
+ }
158
+ continue;
159
+ }
160
+ result.push(original[i]);
161
+ }
162
+ return result;
163
+ }
164
+ const userArgs = process.argv.slice(2);
165
+ let isReload = false;
166
+ while (true) {
167
+ await ensureCache();
168
+ const args = isReload ? reloadArgs(userArgs) : userArgs;
169
+ child = nodeSpawn(process.execPath, [cachedCliPath, ...args], {
170
+ stdio: 'inherit',
171
+ env: process.env,
172
+ });
173
+ const code = await new Promise(r => child.on('close', (c) => r(c)));
174
+ child = null;
175
+ if (shouldReload || code === RELOAD_EXIT_CODE) {
176
+ shouldReload = false;
177
+ isReload = true;
178
+ process.stderr.write('\n\x1b[2mcx: reloading…\x1b[0m\n');
179
+ continue;
180
+ }
181
+ process.exit(code ?? 0);
182
+ }
183
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAC9F,OAAO,EAAE,QAAQ,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG7D,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,WAAW,GAAG,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,kBAAkB,CAAC,CAAC;AACjE,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;AACpD,MAAM,aAAa,GAAG,OAAO,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;AACnD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;AAChD,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;AACrD,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAG5B,4EAA4E;AAE5E,SAAS,UAAU;IACjB,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1C,IAAI,CAAC;QAAC,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAa,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC;AACnG,CAAC;AAED,SAAS,iBAAiB;IACxB,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,GAAG,GAAG,WAAW,EAAE,CAAC;IAC1B,IAAI,CAAC,MAAM,EAAE,OAAO;QAAE,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAChD,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,CAAY,EAAE,EAAE;QACjC,IAAI,CAAC,CAAC,EAAE,IAAI,MAAM,CAAC,OAAO;YAAE,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,KAAK,CAAC;QAClE,OAAO,CAAC,CAAC,cAAc,KAAK,KAAK,CAAC;IACpC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AACpB,CAAC;AAGD,4EAA4E;AAE5E,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;IAC7B,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACxB,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;QACtD,MAAM,KAAK,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IAClC,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iFAAiF,CAAC,CAAC;IAC1G,CAAC;AACH,CAAC;AAED,4EAA4E;AAE5E,IAAI,OAA2B,CAAC;AAChC,IAAI,CAAC;IACH,MAAM,OAAO,GAAG,QAAQ,CAAC,aAAa,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACtE,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,kCAAkC,CAAC,CAAC;AACjE,CAAC;AAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC;AAE7B,IAAI,CAAC,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;IACrC,OAAO,CAAC,KAAK,CAAC,2DAA2D,CAAC,CAAC;IAC3E,OAAO,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAC5D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,4EAA4E;AAE5E,KAAK,UAAU,WAAW;IACxB,MAAM,OAAO,GAAG,iBAAiB,EAAE,CAAC;IACpC,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAQ,CAAC,CAAC;IAChC,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;IAE5E,IAAI,KAAK,GAAG,KAAK,CAAC;IAClB,IAAI,UAAU,CAAC,aAAa,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACtD,IAAI,CAAC;YAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IACnF,CAAC;IAED,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC;QAE7B,kEAAkE;QAClE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;QAC3D,KAAK,MAAM,EAAE,IAAI,OAAO,EAAE,CAAC;YACzB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;QACpD,CAAC;QAED,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;YAC7B,MAAM,OAAO,GAAG,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YAC7D,MAAM,EAAE,GAAG,KAAK,GAAG,CAAC,CAAC;YACrB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,4BAA4B,OAAO,uBAAuB,EAAE,KAAK,CAAC,CAAC;QACpG,CAAC,EAAE,GAAG,CAAC,CAAC;QAER,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAQ,EAAE,OAAO,CAAC,CAAC;QACjD,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE;YACtD,OAAO;gBACL,aAAa,CAAC,KAAK,CAAC,CAAC;gBACrB,MAAM,EAAE,GAAG,KAAK,GAAG,CAAC,CAAC;gBACrB,MAAM,OAAO,GAAG,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;gBAC7D,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,wBAAwB,OAAO,uBAAuB,EAAE,KAAK,CAAC,CAAC;YAChG,CAAC;YACD,MAAM,CAAC,EAAU;gBACf,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;gBAChC,MAAM,EAAE,GAAG,KAAK,GAAG,GAAG,CAAC;gBACvB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,KAAK,CAAC,CAAC;YACnF,CAAC;SACF,CAAC,CAAC;QAEH,oCAAoC;QACpC,MAAM,EAAE,GAAG,KAAK,GAAG,CAAC,CAAC;QACrB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,iBAAiB,KAAK,qBAAqB,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB,EAAE,KAAK,CAAC,CAAC;QAEtJ,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzC,aAAa,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;QACtC,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC;IACjF,CAAC;AACH,CAAC;AAED,4EAA4E;AAE5E,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7C,SAAS,QAAQ,KAAW,IAAI,CAAC;IAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;AAAC,CAAC;AAAC,MAAM,CAAC,CAAA,CAAC,CAAC,CAAC;AACpE,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AAE7B,4EAA4E;AAE5E,IAAI,KAAK,GAAwC,IAAI,CAAC;AACtD,IAAI,YAAY,GAAG,KAAK,CAAC;AAEzB,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;IACzB,YAAY,GAAG,IAAI,CAAC;IACpB,IAAI,KAAK;QAAE,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AACnC,CAAC,CAAC,CAAC;AAEH,0DAA0D;AAC1D,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;IACxB,IAAI,CAAC,KAAK,EAAE,CAAC;QAAC,QAAQ,EAAE,CAAC;QAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAAC,CAAC;AAChD,CAAC,CAAC,CAAC;AAEH,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;IACzB,IAAI,KAAK;QAAE,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACjC,QAAQ,EAAE,CAAC;IACX,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACpB,CAAC,CAAC,CAAC;AAEH;;GAEG;AACH,SAAS,UAAU,CAAC,QAAkB;IACpC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC;IAC7D,MAAM,MAAM,GAAG,CAAC,YAAY,CAAC,CAAC;IAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1B,sDAAsD;YACtD,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,UAAU,IAAI,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;gBACpD,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBAChE,CAAC,EAAE,CAAC;YACN,CAAC;YACD,SAAS;QACX,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3B,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACvC,IAAI,QAAQ,GAAG,KAAK,CAAC;AAErB,OAAO,IAAI,EAAE,CAAC;IACZ,MAAM,WAAW,EAAE,CAAC;IAEpB,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IAExD,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,aAAa,EAAE,GAAG,IAAI,CAAC,EAAE;QAC5D,KAAK,EAAE,SAAS;QAChB,GAAG,EAAE,OAAO,CAAC,GAAG;KACjB,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,MAAM,IAAI,OAAO,CAAgB,CAAC,CAAC,EAAE,CAAC,KAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACpF,KAAK,GAAG,IAAI,CAAC;IAEb,IAAI,YAAY,IAAI,IAAI,KAAK,gBAAgB,EAAE,CAAC;QAC9C,YAAY,GAAG,KAAK,CAAC;QACrB,QAAQ,GAAG,IAAI,CAAC;QAChB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;QACzD,SAAS;IACX,CAAC;IAED,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Worker thread that runs a single patch and returns its edits.
3
+ * Receives: { source, patchId, patchesDir }
4
+ * Returns: { edits: [{pos, deleteCount, text}] } or { error: string }
5
+ */
6
+ export {};
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Worker thread that runs a single patch and returns its edits.
3
+ * Receives: { source, patchId, patchesDir }
4
+ * Returns: { edits: [{pos, deleteCount, text}] } or { error: string }
5
+ */
6
+ import { workerData, parentPort } from 'worker_threads';
7
+ import * as acorn from 'acorn';
8
+ import { ASTIndex, buildContext } from './ast.js';
9
+ const { source, patchId, patchesDir } = workerData;
10
+ try {
11
+ const ast = acorn.parse(source, { ecmaVersion: 'latest', sourceType: 'module', allowHashBang: true });
12
+ const index = new ASTIndex(ast);
13
+ parentPort.postMessage({ type: 'ready' });
14
+ const edits = [];
15
+ const editor = {
16
+ insertAt(pos, text) { edits.push({ pos, deleteCount: 0, text }); },
17
+ replaceRange(start, end, text) { edits.push({ pos: start, deleteCount: end - start, text }); },
18
+ };
19
+ const ctx = buildContext(source, index, editor);
20
+ const patchModule = await import(`${patchesDir}/${patchId}.js`);
21
+ patchModule.default.apply(ctx);
22
+ parentPort.postMessage({ type: 'done', edits });
23
+ }
24
+ catch (err) {
25
+ parentPort.postMessage({ type: 'error', error: err.message });
26
+ }
27
+ //# sourceMappingURL=patch-worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patch-worker.js","sourceRoot":"","sources":["../src/patch-worker.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAGlD,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,UAA6B,CAAC;AAEtE,IAAI,CAAC;IACH,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,IAAI,EAAE,CAAuB,CAAC;IAC5H,MAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC;IAChC,UAAW,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IAE3C,MAAM,KAAK,GAAiB,EAAE,CAAC;IAC/B,MAAM,MAAM,GAAgB;QAC1B,QAAQ,CAAC,GAAW,EAAE,IAAY,IAAI,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,WAAW,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAClF,YAAY,CAAC,KAAa,EAAE,GAAW,EAAE,IAAY,IAAI,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,GAAG,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;KACvH,CAAC;IAEF,MAAM,GAAG,GAAG,YAAY,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IAChD,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,GAAG,UAAU,IAAI,OAAO,KAAK,CAAC,CAAC;IAC/D,WAAW,CAAC,OAAiB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAE1C,UAAW,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;AACnD,CAAC;AAAC,OAAO,GAAG,EAAE,CAAC;IACb,UAAW,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAG,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;AAC5E,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Always Show Context
3
+ *
4
+ * Shows context usage percentage at all times, not just when approaching
5
+ * the limit. The built-in TokenWarning only fires within 20k tokens of
6
+ * the threshold — on a 1M context window, that's ~98% full, far too late.
7
+ *
8
+ * Addresses: https://github.com/anthropics/claude-code/issues/18456 (51 thumbs up)
9
+ *
10
+ * Strategy:
11
+ * 1. Find TokenWarning by its unique "Context low" string
12
+ * 2. Remove the isAboveWarningThreshold gate so the indicator always renders
13
+ * 3. Fix the warning color to be neutral when below threshold
14
+ * 4. Soften "Context low" label to "Context" for always-on display
15
+ *
16
+ * For auto-compact users (the default): shows a dim "X% context used"
17
+ * line at all times. For manual-compact users: shows "Context (X% remaining)"
18
+ * in neutral color when below threshold, escalating to warning/error colors
19
+ * as context fills up.
20
+ */
21
+ import type { Patch } from '../types.js';
22
+ declare const patch: Patch;
23
+ export default patch;
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Always Show Context
3
+ *
4
+ * Shows context usage percentage at all times, not just when approaching
5
+ * the limit. The built-in TokenWarning only fires within 20k tokens of
6
+ * the threshold — on a 1M context window, that's ~98% full, far too late.
7
+ *
8
+ * Addresses: https://github.com/anthropics/claude-code/issues/18456 (51 thumbs up)
9
+ *
10
+ * Strategy:
11
+ * 1. Find TokenWarning by its unique "Context low" string
12
+ * 2. Remove the isAboveWarningThreshold gate so the indicator always renders
13
+ * 3. Fix the warning color to be neutral when below threshold
14
+ * 4. Soften "Context low" label to "Context" for always-on display
15
+ *
16
+ * For auto-compact users (the default): shows a dim "X% context used"
17
+ * line at all times. For manual-compact users: shows "Context (X% remaining)"
18
+ * in neutral color when below threshold, escalating to warning/error colors
19
+ * as context fills up.
20
+ */
21
+ const patch = {
22
+ id: 'always-show-context',
23
+ name: 'Always Show Context',
24
+ description: 'Always display context usage percentage, not just when near limit',
25
+ apply(ctx) {
26
+ const { ast, editor, find, index, assert, src } = ctx;
27
+ const { findFirst } = find;
28
+ // Find TokenWarning function via its unique "Context low" marker.
29
+ // Check indexed literals first (string concat), then template elements.
30
+ let marker = null;
31
+ for (const [value, nodes] of index.literalsByValue) {
32
+ if (typeof value === 'string' && value.includes('Context low')) {
33
+ marker = nodes[0];
34
+ break;
35
+ }
36
+ }
37
+ if (!marker) {
38
+ marker = findFirst(ast, (n) => n.type === 'TemplateElement' &&
39
+ n.value?.raw?.includes('Context low'));
40
+ }
41
+ assert(marker, 'Could not find "Context low" marker in bundle');
42
+ const fn = index.enclosingFunction(marker);
43
+ assert(fn, 'Could not find TokenWarning function');
44
+ // Find the early-return gate:
45
+ // if (!isAboveWarningThreshold || suppressWarning) { return null; }
46
+ // Pattern: IfStatement → test: !X || Y, consequent: return null,
47
+ // and it must appear before the "Context low" string.
48
+ const gate = findFirst(fn, (n) => {
49
+ if (n.type !== 'IfStatement' || n.start >= marker.start)
50
+ return false;
51
+ const t = n.test;
52
+ if (t.type !== 'LogicalExpression' || t.operator !== '||')
53
+ return false;
54
+ if (t.left.type !== 'UnaryExpression' || t.left.operator !== '!')
55
+ return false;
56
+ return findFirst(n.consequent, (r) => r.type === 'ReturnStatement' &&
57
+ r.argument?.type === 'Literal' &&
58
+ r.argument.value === null) !== null;
59
+ });
60
+ assert(gate, 'Could not find early-return gate: if(!X||Y){return null}');
61
+ // Save the minified name for isAboveWarningThreshold before editing
62
+ const warnVar = gate.test.left.argument;
63
+ assert(warnVar.type === 'Identifier', 'Expected Identifier for isAboveWarningThreshold');
64
+ // Edit 1: Remove threshold check from gate, keep suppress check.
65
+ // !isAboveWarningThreshold || suppressWarning → suppressWarning
66
+ editor.replaceRange(gate.test.start, gate.test.end, src(gate.test.right));
67
+ // Edit 2: Neutral color when below warning threshold.
68
+ // Find: isAboveErrorThreshold ? "error" : "warning"
69
+ // Replace "warning" with: isAboveWarningThreshold ? "warning" : void 0
70
+ // This makes text render in default color when context usage is low.
71
+ const colorTernary = findFirst(fn, (n) => n.type === 'ConditionalExpression' &&
72
+ n.consequent.type === 'Literal' && n.consequent.value === 'error' &&
73
+ n.alternate.type === 'Literal' && n.alternate.value === 'warning');
74
+ if (colorTernary) {
75
+ editor.replaceRange(colorTernary.alternate.start, colorTernary.alternate.end, `${warnVar.name}?"warning":void 0`);
76
+ }
77
+ // Edit 3: Soften "Context low" → "Context" for neutral always-on display.
78
+ const fnSrc = src(fn);
79
+ const needle = 'Context low';
80
+ let pos = 0;
81
+ while ((pos = fnSrc.indexOf(needle, pos)) !== -1) {
82
+ editor.replaceRange(fn.start + pos, fn.start + pos + needle.length, 'Context');
83
+ pos += needle.length;
84
+ }
85
+ // Edit 4: Change "X% until auto-compact" → "X% context used"
86
+ // The bundle has: reactiveOnlyMode ? `${100-var}% context used` : `${var}% until auto-compact`
87
+ // reactiveOnlyMode is always false, so patch the alternate branch to also show context used.
88
+ const autocompactTpl = findFirst(fn, (n) => n.type === 'TemplateLiteral' &&
89
+ n.quasis.some((q) => q.value?.raw?.includes('% until auto-compact')));
90
+ if (autocompactTpl) {
91
+ const varName = src(autocompactTpl.expressions[0]);
92
+ editor.replaceRange(autocompactTpl.start, autocompactTpl.end, `\`\${100-${varName}}% context used\``);
93
+ }
94
+ },
95
+ };
96
+ export default patch;
97
+ //# sourceMappingURL=always-show-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"always-show-context.js","sourceRoot":"","sources":["../../src/patches/always-show-context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Always Show Thinking Patch
3
+ *
4
+ * Makes Claude's thinking blocks always display expanded instead of
5
+ * collapsed behind "∴ Thinking (ctrl+o to expand)".
6
+ *
7
+ * Addresses: https://github.com/anthropics/claude-code/issues/8477 (195 thumbs up)
8
+ *
9
+ * In AssistantThinkingMessage, the gate is:
10
+ * const shouldShowFullThinking = isTranscriptMode || verbose;
11
+ * if (!shouldShowFullThinking) { return <collapsed view> }
12
+ *
13
+ * We find the function by its unique "∴ Thinking" string and replace
14
+ * the negated OR gate with `false` so the expanded view always renders.
15
+ */
16
+ import type { Patch } from '../types.js';
17
+ declare const patch: Patch;
18
+ export default patch;
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Always Show Thinking Patch
3
+ *
4
+ * Makes Claude's thinking blocks always display expanded instead of
5
+ * collapsed behind "∴ Thinking (ctrl+o to expand)".
6
+ *
7
+ * Addresses: https://github.com/anthropics/claude-code/issues/8477 (195 thumbs up)
8
+ *
9
+ * In AssistantThinkingMessage, the gate is:
10
+ * const shouldShowFullThinking = isTranscriptMode || verbose;
11
+ * if (!shouldShowFullThinking) { return <collapsed view> }
12
+ *
13
+ * We find the function by its unique "∴ Thinking" string and replace
14
+ * the negated OR gate with `false` so the expanded view always renders.
15
+ */
16
+ const patch = {
17
+ id: 'always-show-thinking',
18
+ name: 'Always Show Thinking',
19
+ description: 'Show thinking block content inline instead of collapsed',
20
+ apply(ctx) {
21
+ const { ast, editor, find, index, assert, src } = ctx;
22
+ const { findFirst } = find;
23
+ // Find the AssistantThinkingMessage function by its unique string literal.
24
+ // The "∴" character (U+2234, "therefore") only appears in this component.
25
+ // Use the literal index to find the marker, then walk up to its enclosing function.
26
+ let thinkingMarker = null;
27
+ for (const [value, nodes] of index.literalsByValue) {
28
+ if (typeof value === 'string' && value.includes('\u2234 Thinking')) {
29
+ thinkingMarker = nodes[0];
30
+ break;
31
+ }
32
+ }
33
+ assert(thinkingMarker, 'Could not find "∴ Thinking" literal');
34
+ const thinkingFn = index.enclosingFunction(thinkingMarker);
35
+ assert(thinkingFn, 'Could not find AssistantThinkingMessage function (marker: "∴ Thinking")');
36
+ // Find the gate: if(!(Y||O)) where Y=isTranscriptMode, O=verbose.
37
+ // Structure: IfStatement whose test is UnaryExpression(!) wrapping LogicalExpression(||)
38
+ // This is the FIRST such pattern in the function, appearing before the "∴ Thinking" strings.
39
+ const gate = findFirst(thinkingFn, (n) => n.type === 'IfStatement'
40
+ && n.test.type === 'UnaryExpression'
41
+ && n.test.operator === '!'
42
+ && n.test.argument.type === 'LogicalExpression'
43
+ && n.test.argument.operator === '||');
44
+ assert(gate, 'Could not find thinking display gate: if(!(X||Y))');
45
+ // Verify this is the right gate by checking it appears before the "∴ Thinking" string
46
+ const firstThinkingLiteral = findFirst(thinkingFn, (n) => n.type === 'Literal' && typeof n.value === 'string'
47
+ && n.value.includes('\u2234 Thinking'));
48
+ assert(gate.start < firstThinkingLiteral.start, 'Gate should appear before "∴ Thinking" literal');
49
+ // Replace the test expression with `false` so the collapsed branch is never taken.
50
+ // This makes thinking always display in expanded mode.
51
+ editor.replaceRange(gate.test.start, gate.test.end, 'false');
52
+ },
53
+ };
54
+ export default patch;
55
+ //# sourceMappingURL=always-show-thinking.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"always-show-thinking.js","sourceRoot":"","sources":["../../src/patches/always-show-thinking.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,MAAM,KAAK,GAAU;IACnB,EAAE,EAAE,sBAAsB;IAC1B,IAAI,EAAE,sBAAsB;IAC5B,WAAW,EAAE,yDAAyD;IAEtE,KAAK,CAAC,GAAG;QACP,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC;QACtD,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;QAE3B,2EAA2E;QAC3E,0EAA0E;QAC1E,oFAAoF;QACpF,IAAI,cAAc,GAAG,IAAI,CAAC;QAC1B,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,KAAK,CAAC,eAAe,EAAE,CAAC;YACnD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC;gBACnE,cAAc,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBAC1B,MAAM;YACR,CAAC;QACH,CAAC;QACD,MAAM,CAAC,cAAc,EAAE,qCAAqC,CAAC,CAAC;QAC9D,MAAM,UAAU,GAAG,KAAK,CAAC,iBAAiB,CAAC,cAAc,CAAC,CAAC;QAC3D,MAAM,CAAC,UAAU,EAAE,yEAAyE,CAAC,CAAC;QAE9F,kEAAkE;QAClE,yFAAyF;QACzF,6FAA6F;QAC7F,MAAM,IAAI,GAAG,SAAS,CAAC,UAAU,EAAE,CAAC,CAAM,EAAE,EAAE,CAC5C,CAAC,CAAC,IAAI,KAAK,aAAa;eACrB,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,iBAAiB;eACjC,CAAC,CAAC,IAAI,CAAC,QAAQ,KAAK,GAAG;eACvB,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,mBAAmB;eAC5C,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,KAAK,IAAI,CACrC,CAAC;QACF,MAAM,CAAC,IAAI,EAAE,mDAAmD,CAAC,CAAC;QAElE,sFAAsF;QACtF,MAAM,oBAAoB,GAAG,SAAS,CAAC,UAAU,EAAE,CAAC,CAAM,EAAE,EAAE,CAC5D,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ;eAChD,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC,CAAC;QAC1C,MAAM,CACJ,IAAI,CAAC,KAAK,GAAG,oBAAoB,CAAC,KAAK,EACvC,gDAAgD,CACjD,CAAC;QAEF,mFAAmF;QACnF,uDAAuD;QACvD,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC/D,CAAC;CACF,CAAC;AAEF,eAAe,KAAK,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Attribution Banner Patch
3
+ *
4
+ * Changes "Claude Code" to "Claude Code Extensions (cx) v<version> by @wormcoffee" on the title line.
5
+ * Targets the bold <Text> in the condensed layout and the border title
6
+ * in the boxed layout. No extra elements, no layout changes.
7
+ */
8
+ import type { Patch } from '../types.js';
9
+ declare const patch: Patch;
10
+ export default patch;
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Attribution Banner Patch
3
+ *
4
+ * Changes "Claude Code" to "Claude Code Extensions (cx) v<version> by @wormcoffee" on the title line.
5
+ * Targets the bold <Text> in the condensed layout and the border title
6
+ * in the boxed layout. No extra elements, no layout changes.
7
+ */
8
+ import { readFileSync } from 'fs';
9
+ import { resolve, dirname } from 'path';
10
+ import { fileURLToPath } from 'url';
11
+ const __dirname = dirname(fileURLToPath(import.meta.url));
12
+ const pkg = JSON.parse(readFileSync(resolve(__dirname, '..', '..', 'package.json'), 'utf-8'));
13
+ const version = pkg.version;
14
+ const patch = {
15
+ id: 'banner',
16
+ name: 'Attribution Banner',
17
+ description: 'Show "@wormcoffee" on the Claude Code title line',
18
+ apply(ctx) {
19
+ const { ast, editor, find, index, src, assert } = ctx;
20
+ const { findFirst } = find;
21
+ // ── Condensed layout: createElement(T, {bold:true}, "Claude Code") ──
22
+ // Use literal index to find "Claude Code", then walk up to the createElement call.
23
+ const claudeCodeLiterals = index.literalsByValue.get('Claude Code') || [];
24
+ let boldTextCall = null;
25
+ for (const lit of claudeCodeLiterals) {
26
+ const call = index.ancestor(lit, 'CallExpression');
27
+ if (!call || call.callee.type !== 'MemberExpression' || call.callee.property.name !== 'createElement')
28
+ continue;
29
+ const hasBold = call.arguments.some((a) => a?.type === 'ObjectExpression' &&
30
+ a.properties.some((p) => p.key?.type === 'Identifier' && p.key.name === 'bold'));
31
+ if (hasBold) {
32
+ boldTextCall = call;
33
+ break;
34
+ }
35
+ }
36
+ assert(boldTextCall, 'Could not find createElement(T, {bold}, "Claude Code")');
37
+ const textLiteral = boldTextCall.arguments.find((a) => a.type === 'Literal' && a.value === 'Claude Code');
38
+ editor.replaceRange(textLiteral.start, textLiteral.end, `"Claude Code Extensions (cx) v${version} by x.com/@wormcoffee"`);
39
+ // ── Star-the-repo line in the condensed layout ──
40
+ // The column Box has children: I (title), B (model), R (cwd), g, F
41
+ // We find the column Box (flexDirection:"column") that contains the bold title,
42
+ // then inject a dimColor text after the title argument.
43
+ const condensedFn = index.enclosingFunction(boldTextCall);
44
+ assert(condensedFn, 'Could not find enclosing function for condensed logo');
45
+ // Find the column Box: createElement(u, {flexDirection:"column"}, I, B, R, ...)
46
+ const columnBox = find.findFirst(condensedFn, (n) => n.type === 'CallExpression' &&
47
+ n.arguments?.[1]?.type === 'ObjectExpression' &&
48
+ n.arguments[1].properties?.some?.((p) => p.key?.name === 'flexDirection' && p.value?.value === 'column'));
49
+ assert(columnBox, 'Could not find column Box in condensed logo');
50
+ // The first child after the props object is the title element (I).
51
+ // Insert our star text element right after it.
52
+ const columnArgs = columnBox.arguments;
53
+ // args[0] = Box component, args[1] = {flexDirection:"column"}, args[2..] = children
54
+ assert(columnArgs.length >= 3, 'Column Box has no children');
55
+ const titleChild = columnArgs[2]; // I — the title element
56
+ // Get the React namespace, Text and Box components from the createElement calls
57
+ const reactNs = src(boldTextCall.callee.object); // e.g. "qO"
58
+ const textComp = src(boldTextCall.arguments[0]); // e.g. "T"
59
+ const boxComp = src(columnBox.arguments[0]); // e.g. "u"
60
+ const starText = `${reactNs}.createElement(${textComp},{dimColor:!0},"I don\\u0027t ask for money. Just for love!\\nPlease star the repo \\u2B50\\uFE0F https://github.com/magidandrew/cx")`;
61
+ editor.insertAt(titleChild.end, `,${starText}`);
62
+ // ── Boxed (v2) layout: inject star lines at the bottom ──
63
+ // Find the compact boxed container: createElement(u, {borderStyle:"round", borderColor:"claude", borderText:...})
64
+ // and inject star lines after the last child (cwd line).
65
+ const borderTextLiterals = index.allNodes.filter((n) => n.type === 'Property' && n.key?.name === 'borderText');
66
+ for (const prop of borderTextLiterals) {
67
+ const obj = index.parentMap.get(prop);
68
+ if (!obj || obj.type !== 'ObjectExpression')
69
+ continue;
70
+ // Must also have borderColor:"claude"
71
+ const hasClaudeColor = obj.properties.some((p) => p.key?.name === 'borderColor' && p.value?.value === 'claude');
72
+ if (!hasClaudeColor)
73
+ continue;
74
+ // This is the boxed logo. Find the enclosing createElement call.
75
+ const boxCall = index.parentMap.get(obj);
76
+ if (!boxCall || boxCall.type !== 'CallExpression')
77
+ continue;
78
+ // Last argument is the last child — inject after it
79
+ const lastArg = boxCall.arguments[boxCall.arguments.length - 1];
80
+ // Get React namespace from this scope
81
+ const boxReactNs = src(boxCall.callee.object);
82
+ editor.insertAt(lastArg.end, `,${boxReactNs}.createElement(${textComp},{dimColor:!0},"\\nI don\\u0027t ask for money. Just for love!\\nPlease star the repo \\u2B50\\uFE0F https://github.com/magidandrew/cx")`);
83
+ break;
84
+ }
85
+ // ── Boxed layout: b7("claude",o)("Claude Code") ──
86
+ // Find "Claude Code" literal whose parent CallExpression's callee is another call with "claude"
87
+ let titleCall = null;
88
+ for (const lit of claudeCodeLiterals) {
89
+ const call = index.parentMap.get(lit);
90
+ if (!call || call.type !== 'CallExpression' || call.arguments.length !== 1)
91
+ continue;
92
+ if (call.callee.type === 'CallExpression' &&
93
+ call.callee.arguments[0]?.type === 'Literal' &&
94
+ call.callee.arguments[0].value === 'claude') {
95
+ titleCall = call;
96
+ break;
97
+ }
98
+ }
99
+ if (titleCall) {
100
+ editor.replaceRange(titleCall.arguments[0].start, titleCall.arguments[0].end, `"Claude Code Extensions (cx) v${version} by x.com/@wormcoffee"`);
101
+ }
102
+ },
103
+ };
104
+ export default patch;
105
+ //# sourceMappingURL=banner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"banner.js","sourceRoot":"","sources":["../../src/patches/banner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * /cd Command Patch
3
+ *
4
+ * Adds a /cd <path> slash command to change the working directory
5
+ * mid-session without losing conversation context.
6
+ *
7
+ * Addresses: https://github.com/anthropics/claude-code/issues/3473 (54 thumbs up)
8
+ *
9
+ * AST strategy: find the bundled setCwd function (via its "tengu_shell_set_cwd"
10
+ * telemetry string) and getCwdState (via its named export mapping), then inject
11
+ * a new LocalCommand into the memoized COMMANDS array. The command calls setCwd
12
+ * and reports the new working directory.
13
+ */
14
+ import type { Patch } from '../types.js';
15
+ declare const patch: Patch;
16
+ export default patch;