claude-code-extensions 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ast.d.ts +43 -0
- package/dist/ast.js +308 -0
- package/dist/ast.js.map +1 -0
- package/dist/cli-setup.d.ts +14 -0
- package/dist/cli-setup.js +110 -0
- package/dist/cli-setup.js.map +1 -0
- package/dist/cli.d.ts +18 -0
- package/dist/cli.js +218 -0
- package/dist/cli.js.map +1 -0
- package/dist/patch-worker.d.ts +6 -0
- package/dist/patch-worker.js +27 -0
- package/dist/patch-worker.js.map +1 -0
- package/dist/patches/always-show-context.d.ts +23 -0
- package/dist/patches/always-show-context.js +97 -0
- package/dist/patches/always-show-context.js.map +1 -0
- package/dist/patches/always-show-thinking.d.ts +18 -0
- package/dist/patches/always-show-thinking.js +55 -0
- package/dist/patches/always-show-thinking.js.map +1 -0
- package/dist/patches/banner.d.ts +10 -0
- package/dist/patches/banner.js +60 -0
- package/dist/patches/banner.js.map +1 -0
- package/dist/patches/cd-command.d.ts +16 -0
- package/dist/patches/cd-command.js +89 -0
- package/dist/patches/cd-command.js.map +1 -0
- package/dist/patches/cx-badge.d.ts +10 -0
- package/dist/patches/cx-badge.js +115 -0
- package/dist/patches/cx-badge.js.map +1 -0
- package/dist/patches/cx-resume-commands.d.ts +14 -0
- package/dist/patches/cx-resume-commands.js +53 -0
- package/dist/patches/cx-resume-commands.js.map +1 -0
- package/dist/patches/disable-paste-collapse.d.ts +16 -0
- package/dist/patches/disable-paste-collapse.js +49 -0
- package/dist/patches/disable-paste-collapse.js.map +1 -0
- package/dist/patches/disable-telemetry.d.ts +13 -0
- package/dist/patches/disable-telemetry.js +76 -0
- package/dist/patches/disable-telemetry.js.map +1 -0
- package/{patches/index.js → dist/patches/index.d.ts} +4 -0
- package/dist/patches/index.js +22 -0
- package/dist/patches/index.js.map +1 -0
- package/dist/patches/no-attribution.d.ts +15 -0
- package/dist/patches/no-attribution.js +42 -0
- package/dist/patches/no-attribution.js.map +1 -0
- package/dist/patches/no-feedback.d.ts +12 -0
- package/dist/patches/no-feedback.js +31 -0
- package/dist/patches/no-feedback.js.map +1 -0
- package/dist/patches/no-npm-warning.d.ts +9 -0
- package/dist/patches/no-npm-warning.js +31 -0
- package/dist/patches/no-npm-warning.js.map +1 -0
- package/dist/patches/no-tips.d.ts +10 -0
- package/dist/patches/no-tips.js +26 -0
- package/dist/patches/no-tips.js.map +1 -0
- package/dist/patches/persist-max-effort.d.ts +15 -0
- package/dist/patches/persist-max-effort.js +75 -0
- package/dist/patches/persist-max-effort.js.map +1 -0
- package/dist/patches/queue.d.ts +10 -0
- package/dist/patches/queue.js +202 -0
- package/dist/patches/queue.js.map +1 -0
- package/dist/patches/random-clawd.d.ts +9 -0
- package/dist/patches/random-clawd.js +49 -0
- package/dist/patches/random-clawd.js.map +1 -0
- package/dist/patches/reload.d.ts +10 -0
- package/dist/patches/reload.js +50 -0
- package/dist/patches/reload.js.map +1 -0
- package/dist/patches/session-export.d.ts +16 -0
- package/dist/patches/session-export.js +93 -0
- package/dist/patches/session-export.js.map +1 -0
- package/dist/patches/session-timer.d.ts +18 -0
- package/dist/patches/session-timer.js +217 -0
- package/dist/patches/session-timer.js.map +1 -0
- package/dist/patches/show-file-in-collapsed-read.d.ts +17 -0
- package/dist/patches/show-file-in-collapsed-read.js +151 -0
- package/dist/patches/show-file-in-collapsed-read.js.map +1 -0
- package/dist/patches/simple-spinner.d.ts +12 -0
- package/dist/patches/simple-spinner.js +30 -0
- package/dist/patches/simple-spinner.js.map +1 -0
- package/dist/patches/swap-enter-submit.d.ts +26 -0
- package/dist/patches/swap-enter-submit.js +155 -0
- package/dist/patches/swap-enter-submit.js.map +1 -0
- package/dist/setup.d.ts +11 -0
- package/dist/setup.js +268 -0
- package/dist/setup.js.map +1 -0
- package/dist/transform-worker.d.ts +10 -0
- package/dist/transform-worker.js +35 -0
- package/dist/transform-worker.js.map +1 -0
- package/dist/transform.d.ts +12 -0
- package/dist/transform.js +83 -0
- package/dist/transform.js.map +1 -0
- package/dist/types.d.ts +105 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/package.json +16 -11
- package/ast.js +0 -276
- package/cx +0 -228
- package/cx-setup +0 -101
- package/patch-worker.js +0 -31
- package/patches/always-show-context.js +0 -123
- package/patches/always-show-thinking.js +0 -65
- package/patches/banner.js +0 -58
- package/patches/cd-command.js +0 -104
- package/patches/cx-badge.js +0 -112
- package/patches/cx-resume-commands.js +0 -58
- package/patches/disable-paste-collapse.js +0 -52
- package/patches/disable-telemetry.js +0 -84
- package/patches/no-attribution.js +0 -55
- package/patches/no-npm-warning.js +0 -32
- package/patches/no-tips.js +0 -29
- package/patches/persist-max-effort.js +0 -70
- package/patches/queue.js +0 -215
- package/patches/random-clawd.js +0 -52
- package/patches/reload.js +0 -68
- package/patches/show-file-in-collapsed-read.js +0 -178
- package/patches/swap-enter-submit.js +0 -188
- package/setup.js +0 -222
- package/transform-worker.js +0 -38
- package/transform.js +0 -99
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* /export Command Patch
|
|
3
|
+
*
|
|
4
|
+
* Adds a /export slash command to copy the entire conversation session
|
|
5
|
+
* to the system clipboard as readable markdown.
|
|
6
|
+
*
|
|
7
|
+
* Addresses: https://github.com/magidandrew/cx/issues/2
|
|
8
|
+
*
|
|
9
|
+
* AST strategy: find the COMMANDS array (same approach as cd-command),
|
|
10
|
+
* then inject a new LocalCommand that reads context.messages,
|
|
11
|
+
* formats them as markdown, and copies to clipboard using
|
|
12
|
+
* child_process (pbcopy on macOS, xclip/xsel/wl-copy on Linux).
|
|
13
|
+
*/
|
|
14
|
+
const patch = {
|
|
15
|
+
id: 'session-export',
|
|
16
|
+
name: '/export Command',
|
|
17
|
+
description: '/export — copy the full session transcript to clipboard as markdown',
|
|
18
|
+
apply(ctx) {
|
|
19
|
+
const { ast, editor, find, query, index, src, assert } = ctx;
|
|
20
|
+
// ── 1. Find the COMMANDS array (same as cd-command) ─────────────
|
|
21
|
+
const compactObj = query.findObjectWithStringProps(ast, [
|
|
22
|
+
['name', 'compact'],
|
|
23
|
+
['type', 'local'],
|
|
24
|
+
]);
|
|
25
|
+
assert(compactObj, 'Could not find compact command definition');
|
|
26
|
+
let assignNode = index.parentMap.get(compactObj);
|
|
27
|
+
while (assignNode && assignNode.type !== 'AssignmentExpression') {
|
|
28
|
+
assignNode = index.parentMap.get(assignNode);
|
|
29
|
+
}
|
|
30
|
+
assert(assignNode?.type === 'AssignmentExpression' &&
|
|
31
|
+
assignNode.left?.type === 'Identifier', 'Could not find compact assignment');
|
|
32
|
+
const localVar = assignNode.left.name;
|
|
33
|
+
const reExport = find.findFirst(ast, (n) => n.type === 'AssignmentExpression' &&
|
|
34
|
+
n.right?.type === 'Identifier' && n.right.name === localVar &&
|
|
35
|
+
n.left?.type === 'Identifier' && n.left.name !== localVar);
|
|
36
|
+
assert(reExport, 'Could not find compact re-export');
|
|
37
|
+
const exportVar = reExport.left.name;
|
|
38
|
+
const commandsArr = find.findFirst(ast, (n) => {
|
|
39
|
+
if (n.type !== 'ArrayExpression')
|
|
40
|
+
return false;
|
|
41
|
+
if (n.elements.length < 20)
|
|
42
|
+
return false;
|
|
43
|
+
return n.elements.some((el) => el?.type === 'Identifier' && el.name === exportVar);
|
|
44
|
+
});
|
|
45
|
+
assert(commandsArr, 'Could not find COMMANDS array');
|
|
46
|
+
// ── 2. Inject /export command ───────────────────────────────────
|
|
47
|
+
const lastEl = commandsArr.elements[commandsArr.elements.length - 1];
|
|
48
|
+
// The call signature for type:"local" is: call(args, context)
|
|
49
|
+
// context.messages is Message[] with shape:
|
|
50
|
+
// { type: "user"|"assistant"|..., message: { role, content } }
|
|
51
|
+
// content is string | Array<{type:"text",text:string}|...>
|
|
52
|
+
//
|
|
53
|
+
// Clipboard: use child_process.execSync to pipe to pbcopy (macOS)
|
|
54
|
+
// or xclip/xsel/wl-copy (Linux). This avoids needing to locate
|
|
55
|
+
// the bundled setClipboard function in the minified AST.
|
|
56
|
+
const exportCmd = `,{type:"local",name:"export",description:"Copy full session transcript to clipboard"` +
|
|
57
|
+
`,supportsNonInteractive:false` +
|
|
58
|
+
`,load:()=>Promise.resolve({call:async(_args,_ctx)=>{` +
|
|
59
|
+
`let msgs=_ctx.messages;` +
|
|
60
|
+
`let parts=[];` +
|
|
61
|
+
`for(let m of msgs){` +
|
|
62
|
+
`if(m.type!=="user"&&m.type!=="assistant")continue;` +
|
|
63
|
+
`if(m.isMeta)continue;` +
|
|
64
|
+
`let role=m.type==="user"?"User":"Assistant";` +
|
|
65
|
+
`let c=m.message&&m.message.content;` +
|
|
66
|
+
`if(!c)continue;` +
|
|
67
|
+
`let txt="";` +
|
|
68
|
+
`if(typeof c==="string"){txt=c}` +
|
|
69
|
+
`else if(Array.isArray(c)){` +
|
|
70
|
+
`txt=c.filter(b=>b.type==="text").map(b=>b.text).join("\\n")` +
|
|
71
|
+
`}` +
|
|
72
|
+
`if(!txt.trim())continue;` +
|
|
73
|
+
`parts.push("## "+role+"\\n\\n"+txt)` +
|
|
74
|
+
`}` +
|
|
75
|
+
`if(!parts.length)return{type:"text",value:"No messages to export."};` +
|
|
76
|
+
`let md=parts.join("\\n\\n---\\n\\n");` +
|
|
77
|
+
`try{` +
|
|
78
|
+
`let cp=require("child_process");` +
|
|
79
|
+
`let cmd=process.platform==="darwin"?"pbcopy"` +
|
|
80
|
+
`:"xclip -selection clipboard";` +
|
|
81
|
+
`cp.execSync(cmd,{input:md,timeout:5000});` +
|
|
82
|
+
`let lines=md.split("\\n").length;` +
|
|
83
|
+
`let chars=md.length;` +
|
|
84
|
+
`return{type:"text",value:"Session exported to clipboard ("+chars+" chars, "+lines+" lines)"}` +
|
|
85
|
+
`}catch(e){` +
|
|
86
|
+
`return{type:"text",value:"Failed to copy to clipboard: "+(e.message||e)}` +
|
|
87
|
+
`}` +
|
|
88
|
+
`}})}`;
|
|
89
|
+
editor.insertAt(lastEl.end, exportCmd);
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
export default patch;
|
|
93
|
+
//# sourceMappingURL=session-export.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-export.js","sourceRoot":"","sources":["../../src/patches/session-export.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Timer Patch
|
|
3
|
+
*
|
|
4
|
+
* Displays two timers in the prompt footer:
|
|
5
|
+
* Claude Active: 6m 15s (34%)
|
|
6
|
+
* Session: 18m 42s
|
|
7
|
+
*
|
|
8
|
+
* - "Claude Active" is the hero metric — time Claude was generating
|
|
9
|
+
* responses or running tools (tracked via the isLoading prop).
|
|
10
|
+
* - "Session" is wall-clock time since the component first mounted.
|
|
11
|
+
* - Percentage shows what fraction of the session Claude was active.
|
|
12
|
+
*
|
|
13
|
+
* Hooks into the same ModeIndicator function that cx-badge uses,
|
|
14
|
+
* injecting React state/effect hooks to track and display the timers.
|
|
15
|
+
*/
|
|
16
|
+
import type { Patch } from '../types.js';
|
|
17
|
+
declare const patch: Patch;
|
|
18
|
+
export default patch;
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Timer Patch
|
|
3
|
+
*
|
|
4
|
+
* Displays two timers in the prompt footer:
|
|
5
|
+
* Claude Active: 6m 15s (34%)
|
|
6
|
+
* Session: 18m 42s
|
|
7
|
+
*
|
|
8
|
+
* - "Claude Active" is the hero metric — time Claude was generating
|
|
9
|
+
* responses or running tools (tracked via the isLoading prop).
|
|
10
|
+
* - "Session" is wall-clock time since the component first mounted.
|
|
11
|
+
* - Percentage shows what fraction of the session Claude was active.
|
|
12
|
+
*
|
|
13
|
+
* Hooks into the same ModeIndicator function that cx-badge uses,
|
|
14
|
+
* injecting React state/effect hooks to track and display the timers.
|
|
15
|
+
*/
|
|
16
|
+
const patch = {
|
|
17
|
+
id: 'session-timer',
|
|
18
|
+
name: 'Session Timer',
|
|
19
|
+
description: 'Show Claude active time and session duration in the footer',
|
|
20
|
+
defaultEnabled: false,
|
|
21
|
+
apply(ctx) {
|
|
22
|
+
const { ast, editor, find, src, assert } = ctx;
|
|
23
|
+
const { findFirst } = find;
|
|
24
|
+
// ── Find ModeIndicator via "? for shortcuts" marker ──────────────
|
|
25
|
+
const shortcutsHint = findFirst(ast, (n) => n.type === 'Literal' && n.value === '? for shortcuts');
|
|
26
|
+
assert(shortcutsHint, 'Could not find "? for shortcuts" literal');
|
|
27
|
+
const modeIndicatorFn = findFirst(ast, (node) => {
|
|
28
|
+
if (node.type !== 'FunctionDeclaration' && node.type !== 'FunctionExpression')
|
|
29
|
+
return false;
|
|
30
|
+
let found = false;
|
|
31
|
+
const check = (n) => {
|
|
32
|
+
if (n === shortcutsHint) {
|
|
33
|
+
found = true;
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (found)
|
|
37
|
+
return;
|
|
38
|
+
for (const key of Object.keys(n)) {
|
|
39
|
+
if (key === 'type' || key === 'start' || key === 'end')
|
|
40
|
+
continue;
|
|
41
|
+
const val = n[key];
|
|
42
|
+
if (val && typeof val === 'object') {
|
|
43
|
+
if (Array.isArray(val)) {
|
|
44
|
+
for (const item of val) {
|
|
45
|
+
if (item && typeof item.type === 'string')
|
|
46
|
+
check(item);
|
|
47
|
+
if (found)
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
else if (typeof val.type === 'string') {
|
|
52
|
+
check(val);
|
|
53
|
+
if (found)
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
check(node);
|
|
60
|
+
return found;
|
|
61
|
+
});
|
|
62
|
+
assert(modeIndicatorFn, 'Could not find ModeIndicator function');
|
|
63
|
+
// ── Find the final <Box height={1} overflow="hidden"> return ─────
|
|
64
|
+
const boxWithHeight1 = findFirst(modeIndicatorFn, (n) => {
|
|
65
|
+
if (n.type !== 'CallExpression')
|
|
66
|
+
return false;
|
|
67
|
+
return n.arguments.some((arg) => {
|
|
68
|
+
if (arg?.type !== 'ObjectExpression')
|
|
69
|
+
return false;
|
|
70
|
+
let hasHeight = false;
|
|
71
|
+
let hasOverflow = false;
|
|
72
|
+
for (const p of arg.properties) {
|
|
73
|
+
if (p.key?.name === 'height' && p.value?.value === 1)
|
|
74
|
+
hasHeight = true;
|
|
75
|
+
if (p.key?.name === 'overflow' && p.value?.value === 'hidden')
|
|
76
|
+
hasOverflow = true;
|
|
77
|
+
}
|
|
78
|
+
return hasHeight && hasOverflow;
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
assert(boxWithHeight1, 'Could not find <Box height={1} overflow="hidden">');
|
|
82
|
+
// ── Extract React namespace, Box, and Text references ────────────
|
|
83
|
+
const callee = boxWithHeight1.callee;
|
|
84
|
+
let R;
|
|
85
|
+
if (callee.type === 'MemberExpression') {
|
|
86
|
+
R = src(callee.object);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
R = src(callee);
|
|
90
|
+
}
|
|
91
|
+
const BoxRef = src(boxWithHeight1.arguments[0]);
|
|
92
|
+
// Find Text component via " · " separator (same approach as cx-badge)
|
|
93
|
+
const separatorCall = findFirst(modeIndicatorFn, (n) => {
|
|
94
|
+
if (n.type !== 'CallExpression')
|
|
95
|
+
return false;
|
|
96
|
+
return n.arguments.some((a) => a?.type === 'Literal' && a.value === ' · ');
|
|
97
|
+
});
|
|
98
|
+
assert(separatorCall, 'Could not find separator " · " createElement');
|
|
99
|
+
const TextRef = src(separatorCall.arguments[0]);
|
|
100
|
+
// ── Find isLoading in the function's props ───────────────────────
|
|
101
|
+
// ModeIndicator receives destructured props: { mode, ..., isLoading, ... }
|
|
102
|
+
// The param is an ObjectPattern; we need the minified local name for isLoading.
|
|
103
|
+
const propsParam = modeIndicatorFn.params[0];
|
|
104
|
+
assert(propsParam, 'ModeIndicator has no params');
|
|
105
|
+
let isLoadingVar = null;
|
|
106
|
+
if (propsParam.type === 'ObjectPattern') {
|
|
107
|
+
for (const prop of propsParam.properties) {
|
|
108
|
+
if (prop.type === 'Property' &&
|
|
109
|
+
((prop.key.type === 'Identifier' && prop.key.name === 'isLoading') ||
|
|
110
|
+
(prop.key.type === 'Literal' && prop.key.value === 'isLoading'))) {
|
|
111
|
+
isLoadingVar = prop.value.type === 'Identifier' ? prop.value.name
|
|
112
|
+
: prop.value.type === 'AssignmentPattern' ? prop.value.left.name
|
|
113
|
+
: null;
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// If not destructured directly, the props may be accessed as t0.isLoading
|
|
119
|
+
// (the React compiler pattern). In that case we use the param name directly.
|
|
120
|
+
if (!isLoadingVar) {
|
|
121
|
+
if (propsParam.type === 'Identifier') {
|
|
122
|
+
isLoadingVar = `${propsParam.name}.isLoading`;
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
// Search for .isLoading member access in the function body
|
|
126
|
+
const memberAccess = findFirst(modeIndicatorFn, (n) => n.type === 'MemberExpression' &&
|
|
127
|
+
n.property.type === 'Identifier' &&
|
|
128
|
+
n.property.name === 'isLoading');
|
|
129
|
+
assert(memberAccess, 'Could not find isLoading access in ModeIndicator');
|
|
130
|
+
isLoadingVar = src(memberAccess);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// ── Inject timer hooks at the start of the function body ─────────
|
|
134
|
+
// We inject:
|
|
135
|
+
// 1. A session start ref (persists across re-renders)
|
|
136
|
+
// 2. A state variable for active accumulated ms
|
|
137
|
+
// 3. A ref for tracking the loading-start timestamp
|
|
138
|
+
// 4. A useEffect that reacts to isLoading changes
|
|
139
|
+
// 5. A 1-second interval useEffect to force re-renders for session time
|
|
140
|
+
const body = modeIndicatorFn.body;
|
|
141
|
+
assert(body.type === 'BlockStatement', 'ModeIndicator body is not a block');
|
|
142
|
+
// Insert right after the opening brace
|
|
143
|
+
const insertPos = body.start + 1;
|
|
144
|
+
// Timer formatting function (inline, no external deps)
|
|
145
|
+
// Formats seconds into "Xm Ys" or "Xh Ym" depending on magnitude
|
|
146
|
+
const fmtFn = `function __stFmt(ms){` +
|
|
147
|
+
`var s=Math.floor(ms/1000),m=Math.floor(s/60),h=Math.floor(m/60);` +
|
|
148
|
+
`s=s%60;m=m%60;` +
|
|
149
|
+
`if(h>0)return h+"h "+m+"m";` +
|
|
150
|
+
`if(m>0)return m+"m "+s+"s";` +
|
|
151
|
+
`return s+"s"` +
|
|
152
|
+
`}`;
|
|
153
|
+
// The hooks code. We use a global-ish object on window to persist state
|
|
154
|
+
// across React re-renders without additional hook overhead. The session
|
|
155
|
+
// start is captured once. Active time is accumulated via useEffect on
|
|
156
|
+
// isLoading transitions.
|
|
157
|
+
const hooksCode =
|
|
158
|
+
// Timer state: [activeMs, forceUpdate counter]
|
|
159
|
+
`var __stState=${R}.useState(function(){return{active:0,tick:0}});` +
|
|
160
|
+
`var __stActive=__stState[0].active,__stTick=__stState[0].tick,__stSet=__stState[1];` +
|
|
161
|
+
// Ref to persist session start and loading-start timestamp
|
|
162
|
+
`var __stRef=${R}.useRef(null);` +
|
|
163
|
+
`if(!__stRef.current)__stRef.current={start:Date.now(),loadStart:0};` +
|
|
164
|
+
// Effect: track isLoading transitions
|
|
165
|
+
`${R}.useEffect(function(){` +
|
|
166
|
+
`var r=__stRef.current;` +
|
|
167
|
+
`if(${isLoadingVar}){` +
|
|
168
|
+
`if(!r.loadStart)r.loadStart=Date.now();` +
|
|
169
|
+
`}else{` +
|
|
170
|
+
`if(r.loadStart){` +
|
|
171
|
+
`var elapsed=Date.now()-r.loadStart;` +
|
|
172
|
+
`r.loadStart=0;` +
|
|
173
|
+
`__stSet(function(p){return{active:p.active+elapsed,tick:p.tick}});` +
|
|
174
|
+
`}` +
|
|
175
|
+
`}` +
|
|
176
|
+
`},[${isLoadingVar}]);` +
|
|
177
|
+
// Effect: 1-second interval for live session clock + active clock while loading
|
|
178
|
+
`${R}.useEffect(function(){` +
|
|
179
|
+
`var id=setInterval(function(){` +
|
|
180
|
+
`__stSet(function(p){` +
|
|
181
|
+
`var r=__stRef.current;` +
|
|
182
|
+
`var bonus=(r.loadStart?Date.now()-r.loadStart:0);` +
|
|
183
|
+
`return{active:p.active+bonus,tick:p.tick+1};` +
|
|
184
|
+
`});` +
|
|
185
|
+
// Reset loadStart to now if still loading to avoid double-counting
|
|
186
|
+
`if(__stRef.current.loadStart)__stRef.current.loadStart=Date.now();` +
|
|
187
|
+
`},1000);` +
|
|
188
|
+
`return function(){clearInterval(id)};` +
|
|
189
|
+
`},[]);` +
|
|
190
|
+
// Compute display values
|
|
191
|
+
`var __stNow=Date.now();` +
|
|
192
|
+
`var __stSessionMs=__stNow-(__stRef.current?__stRef.current.start:__stNow);` +
|
|
193
|
+
`var __stActiveMs=__stActive;` +
|
|
194
|
+
`var __stPct=__stSessionMs>0?Math.round(__stActiveMs/__stSessionMs*100):0;` +
|
|
195
|
+
fmtFn;
|
|
196
|
+
editor.insertAt(insertPos, hooksCode);
|
|
197
|
+
// ── Inject timer display in the footer Box ───────────────────────
|
|
198
|
+
// Add timer after the last child of the Box, right-aligned.
|
|
199
|
+
// We add a spacer Box with flexGrow:1 and then the timer text.
|
|
200
|
+
// The Box call ends with ')'. The children are all arguments after the
|
|
201
|
+
// props object. We insert before the closing ')' of createElement.
|
|
202
|
+
const boxEnd = boxWithHeight1.end;
|
|
203
|
+
// Timer element: right-aligned, dimmed session timer with active hero metric
|
|
204
|
+
const timerEl = `,${R}.createElement(${BoxRef},{flexGrow:1})` +
|
|
205
|
+
`,${R}.createElement(${BoxRef},{flexShrink:0},` +
|
|
206
|
+
`${R}.createElement(${TextRef},{dimColor:true},` +
|
|
207
|
+
`"Active: "+__stFmt(__stActiveMs)` +
|
|
208
|
+
`+(__stPct>0?" ("+__stPct+"%)":"")` +
|
|
209
|
+
`+" \u00b7 Session: "+__stFmt(__stSessionMs)` +
|
|
210
|
+
`)` +
|
|
211
|
+
`)`;
|
|
212
|
+
// Insert just before the closing paren of the createElement call
|
|
213
|
+
editor.insertAt(boxEnd - 1, timerEl);
|
|
214
|
+
},
|
|
215
|
+
};
|
|
216
|
+
export default patch;
|
|
217
|
+
//# sourceMappingURL=session-timer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-timer.js","sourceRoot":"","sources":["../../src/patches/session-timer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Show File Paths in Collapsed Read/Search Display
|
|
3
|
+
*
|
|
4
|
+
* Instead of just "Read 3 files", shows the actual file paths:
|
|
5
|
+
* Read 3 files (src/foo.ts, src/bar.ts, src/baz.ts)
|
|
6
|
+
* Instead of just "Searched for 1 pattern", shows:
|
|
7
|
+
* Searched for 1 pattern ("handleSubmit")
|
|
8
|
+
*
|
|
9
|
+
* Addresses: https://github.com/anthropics/claude-code/issues/21151 (184 thumbs up)
|
|
10
|
+
*
|
|
11
|
+
* The data is already there — readFilePaths and searchArgs are extracted
|
|
12
|
+
* from the message but only shown during active execution as a hint.
|
|
13
|
+
* This patch adds them to the completed collapsed display.
|
|
14
|
+
*/
|
|
15
|
+
import type { Patch } from '../types.js';
|
|
16
|
+
declare const patch: Patch;
|
|
17
|
+
export default patch;
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Show File Paths in Collapsed Read/Search Display
|
|
3
|
+
*
|
|
4
|
+
* Instead of just "Read 3 files", shows the actual file paths:
|
|
5
|
+
* Read 3 files (src/foo.ts, src/bar.ts, src/baz.ts)
|
|
6
|
+
* Instead of just "Searched for 1 pattern", shows:
|
|
7
|
+
* Searched for 1 pattern ("handleSubmit")
|
|
8
|
+
*
|
|
9
|
+
* Addresses: https://github.com/anthropics/claude-code/issues/21151 (184 thumbs up)
|
|
10
|
+
*
|
|
11
|
+
* The data is already there — readFilePaths and searchArgs are extracted
|
|
12
|
+
* from the message but only shown during active execution as a hint.
|
|
13
|
+
* This patch adds them to the completed collapsed display.
|
|
14
|
+
*/
|
|
15
|
+
const patch = {
|
|
16
|
+
id: 'show-file-in-collapsed-read',
|
|
17
|
+
name: 'Show File in Collapsed Read',
|
|
18
|
+
description: 'Show file paths and search patterns in collapsed tool display',
|
|
19
|
+
apply(ctx) {
|
|
20
|
+
const { ast, editor, find, index, assert, src, query } = ctx;
|
|
21
|
+
const { findFirst, findAll } = find;
|
|
22
|
+
// ─── Step 1: Find the collapsed display rendering function ───
|
|
23
|
+
// Identified by containing key:"read", key:"search", and key:"comma-r" literals.
|
|
24
|
+
// Use the indexed findFunctionsContainingStrings for O(matches) lookup.
|
|
25
|
+
const renderFns = query.findFunctionsContainingStrings(ast, 'comma-r', 'read', 'search');
|
|
26
|
+
const renderFn = renderFns[0];
|
|
27
|
+
assert(renderFn, 'Could not find collapsed display render function (markers: key:"read", key:"search", key:"comma-r")');
|
|
28
|
+
// ─── Step 2: Discover variable names ───
|
|
29
|
+
// Find the readFilePaths variable: pattern is X=q.readFilePaths
|
|
30
|
+
// Find the searchArgs variable: pattern is X=q.searchArgs
|
|
31
|
+
// Find the getDisplayPath function: pattern is X(Y):M where it's used near readFilePaths
|
|
32
|
+
// Find readFilePaths property access
|
|
33
|
+
const readFilePathsAccess = findFirst(renderFn, (n) => n.type === 'MemberExpression'
|
|
34
|
+
&& n.property.type === 'Identifier'
|
|
35
|
+
&& n.property.name === 'readFilePaths');
|
|
36
|
+
assert(readFilePathsAccess, 'Could not find q.readFilePaths access');
|
|
37
|
+
// The assignment: Q = q.readFilePaths — Q is the variable we need
|
|
38
|
+
const readPathsAssignment = findFirst(renderFn, (n) => n.type === 'VariableDeclarator'
|
|
39
|
+
&& n.init === readFilePathsAccess);
|
|
40
|
+
assert(readPathsAssignment, 'Could not find readFilePaths variable assignment');
|
|
41
|
+
const readPathsVar = readPathsAssignment.id.name;
|
|
42
|
+
// Find searchArgs variable similarly
|
|
43
|
+
const searchArgsAccess = findFirst(renderFn, (n) => n.type === 'MemberExpression'
|
|
44
|
+
&& n.property.type === 'Identifier'
|
|
45
|
+
&& n.property.name === 'searchArgs');
|
|
46
|
+
assert(searchArgsAccess, 'Could not find q.searchArgs access');
|
|
47
|
+
const searchArgsAssignment = findFirst(renderFn, (n) => n.type === 'VariableDeclarator'
|
|
48
|
+
&& n.init === searchArgsAccess);
|
|
49
|
+
assert(searchArgsAssignment, 'Could not find searchArgs variable assignment');
|
|
50
|
+
const searchArgsVar = searchArgsAssignment.id.name;
|
|
51
|
+
// Find getDisplayPath function name by looking for its call pattern:
|
|
52
|
+
// It's called like: F5(X6) right after readFilePaths is accessed,
|
|
53
|
+
// in the pattern: X!==void 0?F5(X):M
|
|
54
|
+
// The call is on a variable that came from Q?.at(-1)
|
|
55
|
+
const getDisplayPathCall = findFirst(renderFn, (n) => {
|
|
56
|
+
if (n.type !== 'ConditionalExpression')
|
|
57
|
+
return false;
|
|
58
|
+
// Look for: X!==void 0 ? CALL(X) : Y
|
|
59
|
+
// where CALL is a single-argument function call
|
|
60
|
+
if (n.consequent.type !== 'CallExpression')
|
|
61
|
+
return false;
|
|
62
|
+
if (n.consequent.arguments.length !== 1)
|
|
63
|
+
return false;
|
|
64
|
+
// The callee should be an Identifier (the getDisplayPath function)
|
|
65
|
+
if (n.consequent.callee.type !== 'Identifier')
|
|
66
|
+
return false;
|
|
67
|
+
// This should appear after readFilePaths is used
|
|
68
|
+
return n.start > readFilePathsAccess.start;
|
|
69
|
+
});
|
|
70
|
+
assert(getDisplayPathCall, 'Could not find getDisplayPath call pattern');
|
|
71
|
+
const displayPathFn = getDisplayPathCall.consequent.callee.name;
|
|
72
|
+
// ─── Step 3: Find the React library reference ───
|
|
73
|
+
// Look for createElement calls in the function — C4.default.createElement(...)
|
|
74
|
+
// Find the pattern: X.default.createElement(Y, {key:"read"}, ...)
|
|
75
|
+
const readElement = findFirst(renderFn, (n) => {
|
|
76
|
+
if (n.type !== 'CallExpression')
|
|
77
|
+
return false;
|
|
78
|
+
// Check for: X.default.createElement
|
|
79
|
+
const callee = n.callee;
|
|
80
|
+
if (callee.type !== 'MemberExpression')
|
|
81
|
+
return false;
|
|
82
|
+
if (callee.property.name !== 'createElement')
|
|
83
|
+
return false;
|
|
84
|
+
// Check args for key:"read"
|
|
85
|
+
return n.arguments.some((arg) => arg.type === 'ObjectExpression'
|
|
86
|
+
&& arg.properties?.some((p) => p.key?.name === 'key' && p.value?.value === 'read'));
|
|
87
|
+
});
|
|
88
|
+
assert(readElement, 'Could not find createElement with key:"read"');
|
|
89
|
+
// Extract the React reference (e.g., C4) from C4.default.createElement
|
|
90
|
+
const reactRef = src(readElement.callee.object.object);
|
|
91
|
+
// ─── Step 4: Find the Text component reference ───
|
|
92
|
+
// The readElement is: createElement(T, {key:"read"}, M6, " ", createElement(T, {bold:!0}, b), ...)
|
|
93
|
+
// The first argument (index 0) is the Text component reference.
|
|
94
|
+
const textComponent = src(readElement.arguments[0]);
|
|
95
|
+
// ─── Step 5: Find the "Searched for" element and inject search pattern ───
|
|
96
|
+
// Pattern: z6.push(createElement(T, {key:"search"}, M6, " ", createElement(T, {bold:true}, I), " ", I===1?"pattern":"patterns"))
|
|
97
|
+
// We want to add the search pattern text after "patterns")
|
|
98
|
+
const searchElement = findFirst(renderFn, (n) => {
|
|
99
|
+
if (n.type !== 'CallExpression')
|
|
100
|
+
return false;
|
|
101
|
+
if (n.callee.type !== 'MemberExpression')
|
|
102
|
+
return false;
|
|
103
|
+
if (n.callee.property.name !== 'createElement')
|
|
104
|
+
return false;
|
|
105
|
+
return n.arguments.some((arg) => arg.type === 'ObjectExpression'
|
|
106
|
+
&& arg.properties?.some((p) => p.key?.name === 'key' && p.value?.value === 'search'));
|
|
107
|
+
});
|
|
108
|
+
assert(searchElement, 'Could not find createElement with key:"search"');
|
|
109
|
+
// Find the push() call that contains this search element
|
|
110
|
+
const searchPush = findFirst(renderFn, (n) => n.type === 'CallExpression'
|
|
111
|
+
&& n.callee.type === 'MemberExpression'
|
|
112
|
+
&& n.callee.property.name === 'push'
|
|
113
|
+
&& n.arguments.length === 1
|
|
114
|
+
&& n.arguments[0] === searchElement);
|
|
115
|
+
assert(searchPush, 'Could not find push() call for search element');
|
|
116
|
+
// After the search push, inject a conditional that shows the search patterns
|
|
117
|
+
// Show: (pattern1, pattern2, ...)
|
|
118
|
+
const searchPathCode = `;if(${searchArgsVar}&&${searchArgsVar}.length>0){` +
|
|
119
|
+
`z6.push(${reactRef}.default.createElement(${textComponent},{key:"search-args",dimColor:!0},` +
|
|
120
|
+
`" (",${searchArgsVar}.map(function(p){return\'"\\'\\'"+p+\'"\\'\\'\'}).join(", "),")"))` +
|
|
121
|
+
`}`;
|
|
122
|
+
// Wait — the array variable name might not be z6. Let's find it.
|
|
123
|
+
// The push() callee object is the array variable.
|
|
124
|
+
const elemArrayVar = src(searchPush.callee.object);
|
|
125
|
+
const searchPathCodeFinal = `;if(${searchArgsVar}&&${searchArgsVar}.length>0){` +
|
|
126
|
+
`${elemArrayVar}.push(${reactRef}.default.createElement(${textComponent},{key:"search-args",dimColor:!0},` +
|
|
127
|
+
`" (",${searchArgsVar}.map(function(p){return '"'+p+'"'}).join(", "),")"))` +
|
|
128
|
+
`}`;
|
|
129
|
+
// Find the enclosing if-block for the search element by walking up the parent chain
|
|
130
|
+
const searchIfBlock = index.ancestor(searchElement, 'IfStatement');
|
|
131
|
+
assert(searchIfBlock, 'Could not find if block containing search element');
|
|
132
|
+
editor.insertAt(searchIfBlock.end, searchPathCodeFinal);
|
|
133
|
+
// ─── Step 6: Find the "Read" element and inject file paths ───
|
|
134
|
+
// After the if(b>0){...} block, inject file path display
|
|
135
|
+
const readIfBlock = index.ancestor(readElement, 'IfStatement');
|
|
136
|
+
assert(readIfBlock, 'Could not find if block containing read element');
|
|
137
|
+
// Inject after the read if-block:
|
|
138
|
+
// Show file paths: " (src/foo.ts, src/bar.ts)" for up to 3 files,
|
|
139
|
+
// or " (src/foo.ts… +2 more)" for >3 files
|
|
140
|
+
const readPathCode = `;if(${readPathsVar}&&${readPathsVar}.length>0){` +
|
|
141
|
+
`var __paths=${readPathsVar}.length<=3?` +
|
|
142
|
+
`${readPathsVar}.map(${displayPathFn}).join(", "):` +
|
|
143
|
+
`${displayPathFn}(${readPathsVar}[${readPathsVar}.length-1])+"… +"+(${readPathsVar}.length-1)+" more";` +
|
|
144
|
+
`${elemArrayVar}.push(${reactRef}.default.createElement(${textComponent},{key:"read-paths",dimColor:!0},` +
|
|
145
|
+
`" (",__paths,")"))` +
|
|
146
|
+
`}`;
|
|
147
|
+
editor.insertAt(readIfBlock.end, readPathCode);
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
export default patch;
|
|
151
|
+
//# sourceMappingURL=show-file-in-collapsed-read.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"show-file-in-collapsed-read.js","sourceRoot":"","sources":["../../src/patches/show-file-in-collapsed-read.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple Spinner Patch
|
|
3
|
+
*
|
|
4
|
+
* Replaces the rotating spinner verbs ("Thinking", "Analyzing", etc.)
|
|
5
|
+
* with a single static "working" verb, and replaces the completion
|
|
6
|
+
* verbs ("Baked", "Brewed", etc.) with a single "worked" verb.
|
|
7
|
+
*
|
|
8
|
+
* The spinner animation (dots) is preserved — only the text is simplified.
|
|
9
|
+
*/
|
|
10
|
+
import type { Patch } from '../types.js';
|
|
11
|
+
declare const patch: Patch;
|
|
12
|
+
export default patch;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple Spinner Patch
|
|
3
|
+
*
|
|
4
|
+
* Replaces the rotating spinner verbs ("Thinking", "Analyzing", etc.)
|
|
5
|
+
* with a single static "working" verb, and replaces the completion
|
|
6
|
+
* verbs ("Baked", "Brewed", etc.) with a single "worked" verb.
|
|
7
|
+
*
|
|
8
|
+
* The spinner animation (dots) is preserved — only the text is simplified.
|
|
9
|
+
*/
|
|
10
|
+
const patch = {
|
|
11
|
+
id: 'simple-spinner',
|
|
12
|
+
name: 'Simple Spinner',
|
|
13
|
+
description: 'Replace spinner verb cycling with static "working" / "worked"',
|
|
14
|
+
apply(ctx) {
|
|
15
|
+
const { ast, editor, query, assert } = ctx;
|
|
16
|
+
const { findArrayWithConsecutiveStrings } = query;
|
|
17
|
+
// ── Active spinner verbs ────────────────────────────────────────────
|
|
18
|
+
// SPINNER_VERBS is a large array starting with "Accomplishing", "Actioning", ...
|
|
19
|
+
const spinnerArr = findArrayWithConsecutiveStrings(ast, 'Accomplishing', 'Actioning');
|
|
20
|
+
assert(spinnerArr, 'Could not find SPINNER_VERBS array (looked for "Accomplishing","Actioning")');
|
|
21
|
+
editor.replaceRange(spinnerArr.start, spinnerArr.end, '["working"]');
|
|
22
|
+
// ── Completion verbs ────────────────────────────────────────────────
|
|
23
|
+
// TURN_COMPLETION_VERBS is a smaller array starting with "Baked", "Brewed", ...
|
|
24
|
+
const completionArr = findArrayWithConsecutiveStrings(ast, 'Baked', 'Brewed');
|
|
25
|
+
assert(completionArr, 'Could not find TURN_COMPLETION_VERBS array (looked for "Baked","Brewed")');
|
|
26
|
+
editor.replaceRange(completionArr.start, completionArr.end, '["worked"]');
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
export default patch;
|
|
30
|
+
//# sourceMappingURL=simple-spinner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"simple-spinner.js","sourceRoot":"","sources":["../../src/patches/simple-spinner.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,MAAM,KAAK,GAAU;IACnB,EAAE,EAAE,gBAAgB;IACpB,IAAI,EAAE,gBAAgB;IACtB,WAAW,EAAE,+DAA+D;IAE5E,KAAK,CAAC,GAAG;QACP,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC;QAC3C,MAAM,EAAE,+BAA+B,EAAE,GAAG,KAAK,CAAC;QAElD,uEAAuE;QACvE,iFAAiF;QACjF,MAAM,UAAU,GAAG,+BAA+B,CAAC,GAAG,EAAE,eAAe,EAAE,WAAW,CAAC,CAAC;QACtF,MAAM,CAAC,UAAU,EAAE,6EAA6E,CAAC,CAAC;QAClG,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,KAAK,EAAE,UAAU,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;QAErE,uEAAuE;QACvE,gFAAgF;QAChF,MAAM,aAAa,GAAG,+BAA+B,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;QAC9E,MAAM,CAAC,aAAa,EAAE,0EAA0E,CAAC,CAAC;QAClG,MAAM,CAAC,YAAY,CAAC,aAAa,CAAC,KAAK,EAAE,aAAa,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IAC5E,CAAC;CACF,CAAC;AAEF,eAAe,KAAK,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Swap Enter / Meta+Enter
|
|
3
|
+
*
|
|
4
|
+
* Makes Enter insert a newline and Meta+Enter (Option+Enter on macOS) submit.
|
|
5
|
+
*
|
|
6
|
+
* Addresses: https://github.com/anthropics/claude-code/issues/2054 (72 reactions)
|
|
7
|
+
*
|
|
8
|
+
* CJK users, SSH users, and anyone with Slack-style muscle memory constantly
|
|
9
|
+
* submit half-written prompts by accident. This patch swaps the default
|
|
10
|
+
* bindings so Enter is safe (newline) and Meta+Enter is deliberate (submit).
|
|
11
|
+
*
|
|
12
|
+
* Why keybinding changes alone aren't enough:
|
|
13
|
+
*
|
|
14
|
+
* The Enter key's submit behavior is hard-coded in useTextInput.ts's
|
|
15
|
+
* handleEnter() function — it directly calls onSubmit() for plain Enter
|
|
16
|
+
* and cursor.insert('\n') for Meta/Shift+Enter, bypassing the keybinding
|
|
17
|
+
* system entirely.
|
|
18
|
+
*
|
|
19
|
+
* This patch modifies THREE layers:
|
|
20
|
+
* 1. DEFAULT_BINDINGS — so shortcut hints and the help menu show correctly
|
|
21
|
+
* 2. handleEnter() — so the actual key behavior is swapped
|
|
22
|
+
* 3. Tip/help text — so instructions match the new behavior
|
|
23
|
+
*/
|
|
24
|
+
import type { Patch } from '../types.js';
|
|
25
|
+
declare const patch: Patch;
|
|
26
|
+
export default patch;
|