Infrastructure
Claude Code Launchers
Two macOS .app bundles sit in ~/Applications/. Both open VS Code on ~/apps, but each spawns Claude in a different surface. Both scripts live in the cc repo so they sync across machines.
The Two Launchers
Section titled “The Two Launchers”| Icon | Name | Spawns Claude in | Script |
|---|---|---|---|
| Claude Code | Terminal tab inside VS Code (runs claude CLI) | ~/apps/cc/claude-code-launcher.sh | |
| CC Extension | VS Code editor tab via the official Claude Code extension | ~/apps/cc/cc-extension-launcher.sh |
Shared Architecture
Section titled “Shared Architecture”Both launchers follow the same three-stage pattern:
- Detect — AppleScript checks if a VS Code window with a matching title (
claude-sessionfor terminal,cc-extension-sessionfor extension) is already open. Returnsreuseif found,newif not. - Open or reuse — On
new, write a temporary.code-workspacefile pointing at~/apps, then launch VS Code with--new-window. Onreuse, raise the existing window viaAXRaise. - Trigger Claude — Run an AppleScript sequence to open Claude in the right surface (terminal or editor tab).
The .app bundles in ~/Applications/ are thin wrappers — Contents/MacOS/launcher is a one-line shell script that calls into the cc repo. This keeps the actual logic synced across all four machines via GitHub.
CC Extension — First vs Second Click
Section titled “CC Extension — First vs Second Click”This is the part that took some debugging. The CC extension has different behavior at cold start vs warm start, so the launcher script branches:
First click (cold start, REUSE="new"):
- VS Code opens fresh
- The Claude Code extension auto-opens a Claude tab on activation
- Script runs ONLY the side bar close — does NOT call
Claude: Open New Tab(would open a duplicate)
Second click (warm start, REUSE="reuse"):
- Existing window is raised
- Extension does not auto-open anything
- Script runs
Claude: Open New Tabto add a fresh Claude tab, then closes the side bar
If both paths ran the same AppleScript, the first click would open two Claude tabs.
AppleScript Sequences
Section titled “AppleScript Sequences”Both scripts use the Command Palette (Cmd+Shift+P) rather than direct keyboard shortcuts because keybindings are less reliable when VS Code is mid-startup.
CC Extension first click:
keystroke "p" using {command down, shift down}keystroke "View: Close Secondary Side Bar"keystroke returnCC Extension second click:
keystroke "p" using {command down, shift down}keystroke "Claude: Open New Tab"keystroke returndelay 2keystroke "p" using {command down, shift down}keystroke "View: Close Secondary Side Bar"keystroke returnThe side bar close exists because GitHub Copilot Chat keeps reopening the secondary side bar.
Both launchers append to ~/.claude-launcher.log:
tail -50 ~/.claude-launcher.logEach invocation writes a header line (=== <date> === or === <date> [CC-EXT] ===), the detection result (reuse vs new), and the workspace path if a new one was created.
Key Files
Section titled “Key Files”| Path | Role |
|---|---|
~/apps/cc/claude-code-launcher.sh | Terminal launcher script |
~/apps/cc/cc-extension-launcher.sh | Extension launcher script |
~/Applications/Claude Code.app | Terminal launcher .app bundle |
~/Applications/CC Extension.app | Extension launcher .app bundle |
~/apps/cc/setup-launcher-app.sh | Bootstrap script that builds the .app bundles |
~/.claude-launcher.log | Combined log for both launchers |
Recovery
Section titled “Recovery”If a launcher breaks, the known-good commit is 6223158 in the cc repo (Build 33). Diff against it to see what drifted.
cd ~/apps/ccgit diff 6223158 -- claude-code-launcher.sh cc-extension-launcher.sh