-
-
Notifications
You must be signed in to change notification settings - Fork 920
Show Claude icon in terminal header while Claude Code is active #3046
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 9 commits
bef3b3c
b24ac2e
a07d08d
b92080c
d15dad6
00c361f
3f30447
7608afc
e2b5ec1
a909188
0a88565
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| import { describe, expect, it } from "vitest"; | ||
|
|
||
| import { isClaudeCodeCommand } from "./osc-handlers"; | ||
|
|
||
| describe("isClaudeCodeCommand", () => { | ||
| it("matches direct Claude Code invocations", () => { | ||
| expect(isClaudeCodeCommand("claude")).toBe(true); | ||
| expect(isClaudeCodeCommand("claude --dangerously-skip-permissions")).toBe(true); | ||
| expect(isClaudeCodeCommand("/usr/local/bin/claude chat")).toBe(true); | ||
| }); | ||
|
|
||
| it("matches Claude Code invocations wrapped with env assignments", () => { | ||
| expect(isClaudeCodeCommand('ANTHROPIC_API_KEY="test" claude')).toBe(true); | ||
| expect(isClaudeCodeCommand("FOO=bar env claude --print")).toBe(true); | ||
| }); | ||
|
|
||
| it("ignores other commands", () => { | ||
| expect(isClaudeCodeCommand("claudes")).toBe(false); | ||
| expect(isClaudeCodeCommand("echo claude")).toBe(false); | ||
| expect(isClaudeCodeCommand("")).toBe(false); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -25,6 +25,8 @@ const Osc52MaxRawLength = 128 * 1024; // includes selector + base64 + whitespace | |||||||||||||||||||||||||||||||||||||
| // See aiprompts/wave-osc-16162.md for full documentation | ||||||||||||||||||||||||||||||||||||||
| export type ShellIntegrationStatus = "ready" | "running-command"; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const ClaudeCodeRegex = /(?:^|\/)claude\b/; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| type Osc16162Command = | ||||||||||||||||||||||||||||||||||||||
| | { command: "A"; data: Record<string, never> } | ||||||||||||||||||||||||||||||||||||||
| | { command: "C"; data: { cmd64?: string } } | ||||||||||||||||||||||||||||||||||||||
|
|
@@ -43,41 +45,56 @@ type Osc16162Command = | |||||||||||||||||||||||||||||||||||||
| | { command: "I"; data: { inputempty?: boolean } } | ||||||||||||||||||||||||||||||||||||||
| | { command: "R"; data: Record<string, never> }; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| function normalizeCmd(decodedCmd: string): string { | ||||||||||||||||||||||||||||||||||||||
| let normalizedCmd = decodedCmd.trim(); | ||||||||||||||||||||||||||||||||||||||
| normalizedCmd = normalizedCmd.replace(/^(?:\w+=(?:"[^"]*"|'[^']*'|\S+)\s+)*/, ""); | ||||||||||||||||||||||||||||||||||||||
| normalizedCmd = normalizedCmd.replace(/^env\s+/, ""); | ||||||||||||||||||||||||||||||||||||||
| return normalizedCmd; | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+48
to
+52
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Line 51 strips 🔧 Suggested fix function normalizeCmd(decodedCmd: string): string {
- let normalizedCmd = decodedCmd.trim();
- normalizedCmd = normalizedCmd.replace(/^(?:\w+=(?:"[^"]*"|'[^']*'|\S+)\s+)*/, "");
- normalizedCmd = normalizedCmd.replace(/^env\s+/, "");
- return normalizedCmd;
+ let normalizedCmd = decodedCmd.trim();
+ while (true) {
+ const prev = normalizedCmd;
+ normalizedCmd = normalizedCmd.replace(/^env\s+/, "");
+ normalizedCmd = normalizedCmd.replace(/^(?:\w+=(?:"[^"]*"|'[^']*'|\S+)\s+)*/, "");
+ normalizedCmd = normalizedCmd.trimStart();
+ if (normalizedCmd === prev) {
+ break;
+ }
+ }
+ return normalizedCmd;
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| function checkCommandForTelemetry(decodedCmd: string) { | ||||||||||||||||||||||||||||||||||||||
| if (!decodedCmd) { | ||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| if (decodedCmd.startsWith("ssh ")) { | ||||||||||||||||||||||||||||||||||||||
| const normalizedCmd = normalizeCmd(decodedCmd); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| if (normalizedCmd.startsWith("ssh ")) { | ||||||||||||||||||||||||||||||||||||||
| recordTEvent("conn:connect", { "conn:conntype": "ssh-manual" }); | ||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const editorsRegex = /^(vim|vi|nano|nvim)\b/; | ||||||||||||||||||||||||||||||||||||||
| if (editorsRegex.test(decodedCmd)) { | ||||||||||||||||||||||||||||||||||||||
| if (editorsRegex.test(normalizedCmd)) { | ||||||||||||||||||||||||||||||||||||||
| recordTEvent("action:term", { "action:type": "cli-edit" }); | ||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const tailFollowRegex = /(^|\|\s*)tail\s+-[fF]\b/; | ||||||||||||||||||||||||||||||||||||||
| if (tailFollowRegex.test(decodedCmd)) { | ||||||||||||||||||||||||||||||||||||||
| if (tailFollowRegex.test(normalizedCmd)) { | ||||||||||||||||||||||||||||||||||||||
| recordTEvent("action:term", { "action:type": "cli-tailf" }); | ||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const claudeRegex = /^claude\b/; | ||||||||||||||||||||||||||||||||||||||
| if (claudeRegex.test(decodedCmd)) { | ||||||||||||||||||||||||||||||||||||||
| if (ClaudeCodeRegex.test(normalizedCmd)) { | ||||||||||||||||||||||||||||||||||||||
| recordTEvent("action:term", { "action:type": "claude" }); | ||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const opencodeRegex = /^opencode\b/; | ||||||||||||||||||||||||||||||||||||||
| if (opencodeRegex.test(decodedCmd)) { | ||||||||||||||||||||||||||||||||||||||
| if (opencodeRegex.test(normalizedCmd)) { | ||||||||||||||||||||||||||||||||||||||
| recordTEvent("action:term", { "action:type": "opencode" }); | ||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| export function isClaudeCodeCommand(decodedCmd: string): boolean { | ||||||||||||||||||||||||||||||||||||||
| if (!decodedCmd) { | ||||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| return ClaudeCodeRegex.test(normalizeCmd(decodedCmd)); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| function handleShellIntegrationCommandStart( | ||||||||||||||||||||||||||||||||||||||
| termWrap: TermWrap, | ||||||||||||||||||||||||||||||||||||||
| blockId: string, | ||||||||||||||||||||||||||||||||||||||
|
|
@@ -101,16 +118,20 @@ function handleShellIntegrationCommandStart( | |||||||||||||||||||||||||||||||||||||
| const decodedCmd = base64ToString(cmd.data.cmd64); | ||||||||||||||||||||||||||||||||||||||
| rtInfo["shell:lastcmd"] = decodedCmd; | ||||||||||||||||||||||||||||||||||||||
| globalStore.set(termWrap.lastCommandAtom, decodedCmd); | ||||||||||||||||||||||||||||||||||||||
| const isCC = isClaudeCodeCommand(decodedCmd); | ||||||||||||||||||||||||||||||||||||||
| globalStore.set(termWrap.claudeCodeActiveAtom, isCC); | ||||||||||||||||||||||||||||||||||||||
| checkCommandForTelemetry(decodedCmd); | ||||||||||||||||||||||||||||||||||||||
| } catch (e) { | ||||||||||||||||||||||||||||||||||||||
| console.error("Error decoding cmd64:", e); | ||||||||||||||||||||||||||||||||||||||
| rtInfo["shell:lastcmd"] = null; | ||||||||||||||||||||||||||||||||||||||
| globalStore.set(termWrap.lastCommandAtom, null); | ||||||||||||||||||||||||||||||||||||||
| globalStore.set(termWrap.claudeCodeActiveAtom, false); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||
| rtInfo["shell:lastcmd"] = null; | ||||||||||||||||||||||||||||||||||||||
| globalStore.set(termWrap.lastCommandAtom, null); | ||||||||||||||||||||||||||||||||||||||
| globalStore.set(termWrap.claudeCodeActiveAtom, false); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| rtInfo["shell:lastcmdexitcode"] = null; | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
@@ -287,6 +308,7 @@ export function handleOsc16162Command(data: string, blockId: string, loaded: boo | |||||||||||||||||||||||||||||||||||||
| case "A": { | ||||||||||||||||||||||||||||||||||||||
| rtInfo["shell:state"] = "ready"; | ||||||||||||||||||||||||||||||||||||||
| globalStore.set(termWrap.shellIntegrationStatusAtom, "ready"); | ||||||||||||||||||||||||||||||||||||||
| globalStore.set(termWrap.claudeCodeActiveAtom, false); | ||||||||||||||||||||||||||||||||||||||
| const marker = terminal.registerMarker(0); | ||||||||||||||||||||||||||||||||||||||
| if (marker) { | ||||||||||||||||||||||||||||||||||||||
| termWrap.promptMarkers.push(marker); | ||||||||||||||||||||||||||||||||||||||
|
|
@@ -324,6 +346,7 @@ export function handleOsc16162Command(data: string, blockId: string, loaded: boo | |||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| break; | ||||||||||||||||||||||||||||||||||||||
| case "D": | ||||||||||||||||||||||||||||||||||||||
| globalStore.set(termWrap.claudeCodeActiveAtom, false); | ||||||||||||||||||||||||||||||||||||||
| if (cmd.data.exitcode != null) { | ||||||||||||||||||||||||||||||||||||||
| rtInfo["shell:lastcmdexitcode"] = cmd.data.exitcode; | ||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||
|
|
@@ -337,6 +360,7 @@ export function handleOsc16162Command(data: string, blockId: string, loaded: boo | |||||||||||||||||||||||||||||||||||||
| break; | ||||||||||||||||||||||||||||||||||||||
| case "R": | ||||||||||||||||||||||||||||||||||||||
| globalStore.set(termWrap.shellIntegrationStatusAtom, null); | ||||||||||||||||||||||||||||||||||||||
| globalStore.set(termWrap.claudeCodeActiveAtom, false); | ||||||||||||||||||||||||||||||||||||||
| if (terminal.buffer.active.type === "alternate") { | ||||||||||||||||||||||||||||||||||||||
| terminal.write("\x1b[?1049l"); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,4 +1,4 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Copyright 2025, Command Line Inc. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Copyright 2026, Command Line Inc. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // SPDX-License-Identifier: Apache-2.0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import type { BlockNodeModel } from "@/app/block/blocktypes"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -32,6 +32,7 @@ import { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| handleOsc16162Command, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| handleOsc52Command, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| handleOsc7Command, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| isClaudeCodeCommand, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type ShellIntegrationStatus, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } from "./osc-handlers"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { bufferLinesToText, createTempFileFromBlob, extractAllClipboardData, normalizeCursorStyle } from "./termutil"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -92,6 +93,7 @@ export class TermWrap { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| promptMarkers: TermTypes.IMarker[] = []; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| shellIntegrationStatusAtom: jotai.PrimitiveAtom<ShellIntegrationStatus | null>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| lastCommandAtom: jotai.PrimitiveAtom<string | null>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| claudeCodeActiveAtom: jotai.PrimitiveAtom<boolean>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| nodeModel: BlockNodeModel; // this can be null | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| hoveredLinkUri: string | null = null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onLinkHover?: (uri: string | null, mouseX: number, mouseY: number) => void; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -131,6 +133,7 @@ export class TermWrap { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.promptMarkers = []; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.shellIntegrationStatusAtom = jotai.atom(null) as jotai.PrimitiveAtom<ShellIntegrationStatus | null>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.lastCommandAtom = jotai.atom(null) as jotai.PrimitiveAtom<string | null>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.claudeCodeActiveAtom = jotai.atom(false); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.webglEnabledAtom = jotai.atom(false) as jotai.PrimitiveAtom<boolean>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.terminal = new Terminal(options); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.fitAddon = new FitAddon(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -171,16 +174,34 @@ export class TermWrap { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.setTermRenderer(WebGLSupported && waveOptions.useWebGl ? "webgl" : "dom"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Register OSC handlers | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.terminal.parser.registerOscHandler(7, (data: string) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return handleOsc7Command(data, this.blockId, this.loaded); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return handleOsc7Command(data, this.blockId, this.loaded); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (e) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error("[termwrap] osc 7 handler error", this.blockId, e); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.terminal.parser.registerOscHandler(52, (data: string) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return handleOsc52Command(data, this.blockId, this.loaded, this); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return handleOsc52Command(data, this.blockId, this.loaded, this); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (e) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error("[termwrap] osc 52 handler error", this.blockId, e); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.terminal.parser.registerOscHandler(16162, (data: string) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return handleOsc16162Command(data, this.blockId, this.loaded, this); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return handleOsc16162Command(data, this.blockId, this.loaded, this); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (e) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error("[termwrap] osc 16162 handler error", this.blockId, e); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
176
to
199
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🌐 Web query:
💡 Result: In xterm.js, for parser.registerOscHandler(code, handler), the handler is a callback that receives the OSC payload string and returns a boolean (or Promise). Returning true indicates the OSC sequence was successfully handled by this handler. The parser stops processing and does not invoke any further (earlier registered) handlers for this OSC code. Returning false (or any falsy value except undefined) indicates the sequence was not handled by this handler. The parser continues to the next handler in the list (handlers are tried from most recently added to earliest). Handlers are invoked in LIFO order (last in, first out). This allows later-registered handlers to intercept and handle the sequence exclusively by returning true, or pass it through by returning false to reach built-in or earlier handlers. This behavior is consistent across parser hooks (OSC, CSI, DCS, ESC). Citations:
🏁 Script executed: # First, let's look at the file and surrounding context
head -220 frontend/app/view/term/termwrap.ts | tail -100Repository: wavetermdev/waveterm Length of output: 4310 🏁 Script executed: # Search for other OSC handler registrations for codes 7, 52, 16162
rg "registerOscHandler\((7|52|16162)" --context 3Repository: wavetermdev/waveterm Length of output: 1640 🏁 Script executed: # Look for the handler function definitions
fd "termwrap\|handleOsc" -e ts | head -20Repository: wavetermdev/waveterm Length of output: 46 🏁 Script executed: # Search for handleOsc7Command, handleOsc52Command, handleOsc16162Command
rg "handleOsc(7|52|16162)Command" -A 5Repository: wavetermdev/waveterm Length of output: 3486 🏁 Script executed: # Search for comments about OSC ownership or error handling
rg "OSC.*own|own.*OSC|handler.*own|own.*handler" -i -A 2 -B 2Repository: wavetermdev/waveterm Length of output: 50377 Return Lines 181, 189, and 197 return Suggested fix this.terminal.parser.registerOscHandler(7, (data: string) => {
try {
return handleOsc7Command(data, this.blockId, this.loaded);
} catch (e) {
console.error("[termwrap] osc 7 handler error", this.blockId, e);
- return false;
+ return true;
}
});
this.terminal.parser.registerOscHandler(52, (data: string) => {
try {
return handleOsc52Command(data, this.blockId, this.loaded, this);
} catch (e) {
console.error("[termwrap] osc 52 handler error", this.blockId, e);
- return false;
+ return true;
}
});
this.terminal.parser.registerOscHandler(16162, (data: string) => {
try {
return handleOsc16162Command(data, this.blockId, this.loaded, this);
} catch (e) {
console.error("[termwrap] osc 16162 handler error", this.blockId, e);
- return false;
+ return true;
}
});📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.toDispose.push( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.terminal.parser.registerCsiHandler({ final: "J" }, (params) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (params == null || params.length < 1) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (params[0] === 3) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.lastClearScrollbackTs = Date.now(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (this.inSyncTransaction) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -193,6 +214,9 @@ export class TermWrap { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.toDispose.push( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.terminal.parser.registerCsiHandler({ prefix: "?", final: "h" }, (params) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (params == null || params.length < 1) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (params[0] === 2026) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.lastMode2026SetTs = Date.now(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.inSyncTransaction = true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -202,6 +226,9 @@ export class TermWrap { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.toDispose.push( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.terminal.parser.registerCsiHandler({ prefix: "?", final: "l" }, (params) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (params == null || params.length < 1) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (params[0] === 2026) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.lastMode2026ResetTs = Date.now(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.inSyncTransaction = false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -345,16 +372,19 @@ export class TermWrap { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const rtInfo = await RpcApi.GetRTInfoCommand(TabRpcClient, { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| oref: WOS.makeORef("block", this.blockId), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let shellState: ShellIntegrationStatus = null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (rtInfo && rtInfo["shell:integration"]) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const shellState = rtInfo["shell:state"] as ShellIntegrationStatus; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| shellState = rtInfo["shell:state"] as ShellIntegrationStatus; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| globalStore.set(this.shellIntegrationStatusAtom, shellState || null); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| globalStore.set(this.shellIntegrationStatusAtom, null); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const lastCmd = rtInfo ? rtInfo["shell:lastcmd"] : null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const isCC = shellState === "running-command" && isClaudeCodeCommand(lastCmd); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| globalStore.set(this.lastCommandAtom, lastCmd || null); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| globalStore.set(this.claudeCodeActiveAtom, isCC); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (e) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log("Error loading runtime info:", e); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -371,7 +401,9 @@ export class TermWrap { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.promptMarkers.forEach((marker) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| marker.dispose(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (_) {} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (_) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /* nothing */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.promptMarkers = []; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.webglContextLossDisposable?.dispose(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -380,7 +412,9 @@ export class TermWrap { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.toDispose.forEach((d) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| d.dispose(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (_) {} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (_) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /* nothing */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.mainFileSubject.release(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Anchor Claude detection to the command token (argv[0]) only.
Line 28 currently matches
/claudeanywhere in the command string, so inputs likeecho /usr/local/bin/claudeare false positives.🔧 Suggested fix
Also applies to: 91-96
🤖 Prompt for AI Agents