cc-sidebar 0.1.0
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/LICENSE +21 -0
- package/README.md +128 -0
- package/commands/sidebar.md +62 -0
- package/package.json +40 -0
- package/skills/sidebar-awareness/SKILL.md +69 -0
- package/src/cli.ts +166 -0
- package/src/components/RawSidebar.tsx +1155 -0
- package/src/components/Sidebar.tsx +542 -0
- package/src/ipc/client.ts +96 -0
- package/src/ipc/server.ts +92 -0
- package/src/minimal-test.ts +45 -0
- package/src/node-test.mjs +50 -0
- package/src/persistence/store.ts +346 -0
- package/src/standalone-input.ts +101 -0
- package/src/sync-todos.ts +157 -0
- package/src/terminal/iterm.ts +187 -0
- package/src/terminal/prompt.ts +30 -0
- package/src/terminal/tmux.ts +246 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Tyler Nishida
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# cc-sidebar
|
|
2
|
+
|
|
3
|
+
A visual sidebar for managing tasks alongside [Claude Code](https://claude.ai/code). Run it in a split pane next to your Claude Code session to queue tasks, track progress, and stay organized.
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
+-------------------------------+------------------+
|
|
7
|
+
| | cc-sidebar |
|
|
8
|
+
| Claude Code |------------------|
|
|
9
|
+
| | Claude |
|
|
10
|
+
| | Fixing bug... |
|
|
11
|
+
| | |
|
|
12
|
+
| | Queue |
|
|
13
|
+
| | Add tests |
|
|
14
|
+
| | Update docs |
|
|
15
|
+
+-------------------------------+------------------+
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Features
|
|
19
|
+
|
|
20
|
+
- **Task Queue**: Add tasks for Claude to work through
|
|
21
|
+
- **Auto-completion detection**: Sidebar detects when Claude finishes a task
|
|
22
|
+
- **Keyboard-driven**: Full keyboard navigation
|
|
23
|
+
- **iTerm2 + tmux support**: Works with both (iTerm2 preferred)
|
|
24
|
+
- **Persistent**: Data survives restarts
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
Requires [Bun](https://bun.sh) runtime.
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
bun add -g cc-sidebar
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Quick Start
|
|
35
|
+
|
|
36
|
+
### Option 1: iTerm2 (Recommended)
|
|
37
|
+
|
|
38
|
+
1. Open iTerm2
|
|
39
|
+
2. Start Claude Code: `claude`
|
|
40
|
+
3. Run: `cc-sidebar spawn`
|
|
41
|
+
|
|
42
|
+
A split pane opens on the right with the sidebar.
|
|
43
|
+
|
|
44
|
+
### Option 2: tmux
|
|
45
|
+
|
|
46
|
+
1. Start tmux: `tmux`
|
|
47
|
+
2. Start Claude Code: `claude`
|
|
48
|
+
3. Run: `cc-sidebar spawn --tmux`
|
|
49
|
+
|
|
50
|
+
## Usage
|
|
51
|
+
|
|
52
|
+
### Keyboard Shortcuts
|
|
53
|
+
|
|
54
|
+
| Key | Action |
|
|
55
|
+
|-----|--------|
|
|
56
|
+
| `a` | Add new task |
|
|
57
|
+
| `Enter` | Send task to Claude |
|
|
58
|
+
| `e` | Edit selected task |
|
|
59
|
+
| `d` | Delete selected task |
|
|
60
|
+
| `j/k` or arrows | Navigate list |
|
|
61
|
+
| `Tab` | Switch sections |
|
|
62
|
+
| `q` or `Esc` | Quit sidebar |
|
|
63
|
+
|
|
64
|
+
### How It Works
|
|
65
|
+
|
|
66
|
+
1. **Add tasks** to the Queue using `a`
|
|
67
|
+
2. **Send a task** to Claude by pressing `Enter`
|
|
68
|
+
3. **Task moves to Active** while Claude works
|
|
69
|
+
4. **Auto-completes** when Claude returns to prompt
|
|
70
|
+
|
|
71
|
+
### Data Storage
|
|
72
|
+
|
|
73
|
+
Data is stored in `~/.claude-sidebar/`:
|
|
74
|
+
|
|
75
|
+
| File | Purpose |
|
|
76
|
+
|------|---------|
|
|
77
|
+
| `tasks.json` | Task queue |
|
|
78
|
+
| `active.json` | Current active task |
|
|
79
|
+
| `history.log` | Completed tasks |
|
|
80
|
+
|
|
81
|
+
## Claude Integration
|
|
82
|
+
|
|
83
|
+
For automatic task completion tracking, add this to your `~/.claude/CLAUDE.md`:
|
|
84
|
+
|
|
85
|
+
```markdown
|
|
86
|
+
## Sidebar Integration
|
|
87
|
+
|
|
88
|
+
When completing work, check if this project uses the sidebar task queue.
|
|
89
|
+
|
|
90
|
+
**Detection:**
|
|
91
|
+
- Compute project hash: `sha256(cwd).slice(0, 12)`
|
|
92
|
+
- Check if `~/.claude-sidebar/projects/<hash>/tasks.json` exists
|
|
93
|
+
- If not, skip this section
|
|
94
|
+
|
|
95
|
+
**On task completion:**
|
|
96
|
+
1. Read the tasks.json file for this project
|
|
97
|
+
2. Find any task that semantically matches what you just completed
|
|
98
|
+
3. Move the matching task to done.json (Review section) for user confirmation:
|
|
99
|
+
- Remove from tasks.json array
|
|
100
|
+
- Add to done.json array with `completedAt` timestamp
|
|
101
|
+
4. Write both files back
|
|
102
|
+
|
|
103
|
+
Keep it simple - if no clear match, don't move anything. User can manually mark tasks done.
|
|
104
|
+
|
|
105
|
+
**done.json format:**
|
|
106
|
+
```json
|
|
107
|
+
[{"id": "...", "content": "task content", "completedAt": "ISO timestamp"}]
|
|
108
|
+
```
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Commands
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
cc-sidebar show # Render in current terminal
|
|
115
|
+
cc-sidebar spawn # Launch in split pane (auto-detects iTerm2 vs tmux)
|
|
116
|
+
cc-sidebar spawn --tmux # Force tmux mode
|
|
117
|
+
cc-sidebar env # Show environment info
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Requirements
|
|
121
|
+
|
|
122
|
+
- [Bun](https://bun.sh) >= 1.0.0
|
|
123
|
+
- iTerm2 or tmux
|
|
124
|
+
- macOS (iTerm2 support) or Linux (tmux)
|
|
125
|
+
|
|
126
|
+
## License
|
|
127
|
+
|
|
128
|
+
MIT
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sidebar
|
|
3
|
+
description: Open the Claude Code sidebar panel for task queue management
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Sidebar Command
|
|
7
|
+
|
|
8
|
+
Spawn the Claude Sidebar in a tmux split pane.
|
|
9
|
+
|
|
10
|
+
## Requirements
|
|
11
|
+
|
|
12
|
+
**You must be running Claude Code inside a tmux session.** Check the TMUX environment variable - if it's empty, tell the user to:
|
|
13
|
+
1. Start or attach to tmux: `tmux` or `tmux attach`
|
|
14
|
+
2. Run Claude Code from inside tmux
|
|
15
|
+
|
|
16
|
+
## Spawning the Sidebar
|
|
17
|
+
|
|
18
|
+
Run this command to spawn the sidebar:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
cd ${CLAUDE_PLUGIN_ROOT} && bun run src/cli.ts spawn
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The sidebar will appear on the right side (50 chars wide) showing:
|
|
25
|
+
- **Active**: Current task sent to Claude (auto-completes when Claude finishes)
|
|
26
|
+
- **Queue**: User's task backlog
|
|
27
|
+
|
|
28
|
+
## Keyboard Shortcuts (in sidebar)
|
|
29
|
+
|
|
30
|
+
| Key | Action |
|
|
31
|
+
|-----|--------|
|
|
32
|
+
| Tab | Switch between Active and Queue sections |
|
|
33
|
+
| ↑↓ or j/k | Navigate queue list |
|
|
34
|
+
| 1-9 | Quick select queue item by number |
|
|
35
|
+
| a | Add new task to queue |
|
|
36
|
+
| e | Edit selected queue item |
|
|
37
|
+
| d | Delete selected item (or clear active task) |
|
|
38
|
+
| Enter | Send selected task to Claude |
|
|
39
|
+
| Esc | Close sidebar |
|
|
40
|
+
|
|
41
|
+
## How It Works
|
|
42
|
+
|
|
43
|
+
1. Sidebar spawns in a tmux split pane (50 chars fixed width)
|
|
44
|
+
2. User adds tasks to Queue via `a` key
|
|
45
|
+
3. User presses Enter to send a task to Claude
|
|
46
|
+
4. Task moves to Active section, text is injected into Claude's input
|
|
47
|
+
5. Sidebar polls Claude's pane for completion (detects when Claude returns to prompt)
|
|
48
|
+
6. When complete, task is logged to history and Active section clears
|
|
49
|
+
|
|
50
|
+
## Checking Sidebar Status
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
cd ${CLAUDE_PLUGIN_ROOT} && bun run src/cli.ts env
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Closing the Sidebar
|
|
57
|
+
|
|
58
|
+
User can press `Esc` in the sidebar, or close the tmux pane:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
tmux kill-pane -t $(cat /tmp/claude-sidebar-pane-id)
|
|
62
|
+
```
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "cc-sidebar",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Visual sidebar for managing todos, tasks, and context alongside Claude Code",
|
|
5
|
+
"author": "Tyler Nishida",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/tylernishida/cc-sidebar"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"claude",
|
|
13
|
+
"claude-code",
|
|
14
|
+
"sidebar",
|
|
15
|
+
"task-management",
|
|
16
|
+
"terminal",
|
|
17
|
+
"cli"
|
|
18
|
+
],
|
|
19
|
+
"module": "src/cli.ts",
|
|
20
|
+
"type": "module",
|
|
21
|
+
"bin": {
|
|
22
|
+
"cc-sidebar": "src/cli.ts"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"src",
|
|
26
|
+
"skills",
|
|
27
|
+
"commands"
|
|
28
|
+
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"start": "bun run src/cli.ts",
|
|
31
|
+
"show": "bun run src/cli.ts show",
|
|
32
|
+
"spawn": "bun run src/cli.ts spawn"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"commander": "^14.0.2"
|
|
36
|
+
},
|
|
37
|
+
"peerDependencies": {
|
|
38
|
+
"bun": ">=1.0.0"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Claude Code Sidebar Integration
|
|
2
|
+
|
|
3
|
+
You have access to a sidebar that the user uses to manage tasks for you. The sidebar runs in a tmux split pane alongside this conversation.
|
|
4
|
+
|
|
5
|
+
## How It Works
|
|
6
|
+
|
|
7
|
+
1. **User adds tasks** to the Queue in the sidebar
|
|
8
|
+
2. **User sends a task** to you by pressing Enter on a queue item
|
|
9
|
+
3. **Task moves to Active** section while you work on it
|
|
10
|
+
4. **When you finish**, the sidebar auto-detects completion and clears the active task
|
|
11
|
+
|
|
12
|
+
## Active Task
|
|
13
|
+
|
|
14
|
+
When the user sends you a task, it appears as text input in your conversation AND is stored in:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
cat ~/.claude-sidebar/active.json
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Format:
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"id": "uuid",
|
|
24
|
+
"content": "Fix the authentication bug in login.ts",
|
|
25
|
+
"sentAt": "2024-01-15T10:35:00Z"
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**When you receive input that matches an active task, work on it.**
|
|
30
|
+
|
|
31
|
+
## Task Queue
|
|
32
|
+
|
|
33
|
+
The user's queue of upcoming tasks:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
cat ~/.claude-sidebar/tasks.json
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Format:
|
|
40
|
+
```json
|
|
41
|
+
[
|
|
42
|
+
{
|
|
43
|
+
"id": "uuid",
|
|
44
|
+
"content": "Add unit tests for user service",
|
|
45
|
+
"createdAt": "2024-01-15T10:30:00Z"
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Completion Detection
|
|
51
|
+
|
|
52
|
+
The sidebar monitors your output. When you return to the input prompt and stay idle for a few seconds, it automatically:
|
|
53
|
+
1. Marks the active task as complete
|
|
54
|
+
2. Logs it to `~/.claude-sidebar/history.log`
|
|
55
|
+
3. Clears the Active section
|
|
56
|
+
|
|
57
|
+
## Data Files Summary
|
|
58
|
+
|
|
59
|
+
| File | What it is | Who writes |
|
|
60
|
+
|------|-----------|------------|
|
|
61
|
+
| `~/.claude-sidebar/tasks.json` | User's task queue | User (via sidebar) |
|
|
62
|
+
| `~/.claude-sidebar/active.json` | Current task you're working on | Sidebar (when user sends) |
|
|
63
|
+
| `~/.claude-sidebar/history.log` | Completed tasks log | Sidebar (on completion) |
|
|
64
|
+
|
|
65
|
+
## Best Practices
|
|
66
|
+
|
|
67
|
+
1. **Focus on the task** - when you receive input matching an active task, work on it
|
|
68
|
+
2. **Complete thoroughly** - the sidebar waits for you to finish before clearing
|
|
69
|
+
3. **Don't check queue** - the user controls when to send you the next task
|
package/src/cli.ts
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* Claude Sidebar CLI
|
|
4
|
+
*
|
|
5
|
+
* Commands:
|
|
6
|
+
* show - Render sidebar in current terminal
|
|
7
|
+
* spawn - Launch sidebar in tmux split pane
|
|
8
|
+
* update - Send data to running sidebar via IPC
|
|
9
|
+
* env - Show environment info (tmux status, etc.)
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { program } from "commander";
|
|
13
|
+
import { isInTmux, getEnvInfo, spawnSidebarPane } from "./terminal/tmux";
|
|
14
|
+
import { isInITerm, spawnITermSidebarPane, getITermEnvInfo } from "./terminal/iterm";
|
|
15
|
+
import { createIPCServer } from "./ipc/server";
|
|
16
|
+
import { sendMessage } from "./ipc/client";
|
|
17
|
+
import { getSocketPath, ensureDir } from "./persistence/store";
|
|
18
|
+
import { dirname } from "path";
|
|
19
|
+
import { RawSidebar } from "./components/RawSidebar";
|
|
20
|
+
|
|
21
|
+
// Terminal title disabled - could cause flicker
|
|
22
|
+
// process.stdout.write("\x1b]0;claude-sidebar\x07");
|
|
23
|
+
|
|
24
|
+
program
|
|
25
|
+
.name("cc-sidebar")
|
|
26
|
+
.description("Visual sidebar for Claude Code")
|
|
27
|
+
.version("0.1.0");
|
|
28
|
+
|
|
29
|
+
// Show command - render sidebar in current terminal
|
|
30
|
+
program
|
|
31
|
+
.command("show")
|
|
32
|
+
.description("Render sidebar in current terminal")
|
|
33
|
+
.option("-s, --socket <path>", "Unix socket path for IPC")
|
|
34
|
+
.action(async (options) => {
|
|
35
|
+
ensureDir();
|
|
36
|
+
const socketPath = options.socket || getSocketPath();
|
|
37
|
+
|
|
38
|
+
// Start IPC server for receiving updates
|
|
39
|
+
const server = createIPCServer({
|
|
40
|
+
socketPath,
|
|
41
|
+
onMessage: (_message) => {
|
|
42
|
+
// IPC messages can be handled here if needed
|
|
43
|
+
},
|
|
44
|
+
onError: (error) => {
|
|
45
|
+
console.error("IPC error:", error.message);
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// Use raw terminal rendering (bypasses Ink completely for flicker-free input)
|
|
50
|
+
const sidebar = new RawSidebar(() => {
|
|
51
|
+
server.close();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
sidebar.start();
|
|
55
|
+
|
|
56
|
+
// Handle Ctrl+C and termination signals for clean exit
|
|
57
|
+
const cleanup = () => {
|
|
58
|
+
sidebar.stop();
|
|
59
|
+
server.close();
|
|
60
|
+
process.exit(0);
|
|
61
|
+
};
|
|
62
|
+
process.on('SIGINT', cleanup);
|
|
63
|
+
process.on('SIGTERM', cleanup);
|
|
64
|
+
|
|
65
|
+
// Keep process running
|
|
66
|
+
await new Promise(() => {});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// Spawn command - launch sidebar in split pane (iTerm2 or tmux)
|
|
70
|
+
program
|
|
71
|
+
.command("spawn")
|
|
72
|
+
.description("Launch sidebar in split pane (iTerm2 preferred, tmux fallback)")
|
|
73
|
+
.option("--tmux", "Force tmux mode even in iTerm2")
|
|
74
|
+
.action(async (options) => {
|
|
75
|
+
// Get the path to this script and current working directory
|
|
76
|
+
const scriptPath = process.argv[1];
|
|
77
|
+
const cwd = process.cwd();
|
|
78
|
+
// Include cd to ensure sidebar runs in the same directory (for per-project tasks)
|
|
79
|
+
const command = `cd "${cwd}" && bun ${scriptPath} show`;
|
|
80
|
+
|
|
81
|
+
// Prefer iTerm2 if available (avoids scrollback corruption)
|
|
82
|
+
if (isInITerm() && !options.tmux) {
|
|
83
|
+
console.log("Using iTerm2 split (preserves scrollback)...");
|
|
84
|
+
const sessionId = await spawnITermSidebarPane(command);
|
|
85
|
+
if (sessionId) {
|
|
86
|
+
console.log(`Sidebar spawned in iTerm2 session: ${sessionId}`);
|
|
87
|
+
} else {
|
|
88
|
+
console.error("Failed to spawn iTerm2 sidebar");
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Fall back to tmux
|
|
95
|
+
if (!isInTmux()) {
|
|
96
|
+
console.error("Error: Not running in tmux or iTerm2.");
|
|
97
|
+
console.error("Options:");
|
|
98
|
+
console.error(" - Run inside iTerm2 (recommended)");
|
|
99
|
+
console.error(" - Start a tmux session: tmux");
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
console.log("Using tmux split (may affect scrollback)...");
|
|
104
|
+
const paneId = await spawnSidebarPane(command);
|
|
105
|
+
if (paneId) {
|
|
106
|
+
console.log(`Sidebar spawned in tmux pane: ${paneId}`);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// Update command - send data to running sidebar
|
|
111
|
+
program
|
|
112
|
+
.command("update")
|
|
113
|
+
.description("Send data to running sidebar via IPC")
|
|
114
|
+
.option("-s, --socket <path>", "Unix socket path")
|
|
115
|
+
.option("-t, --type <type>", "Message type", "update")
|
|
116
|
+
.option("-d, --data <json>", "Message data (JSON)")
|
|
117
|
+
.action(async (options) => {
|
|
118
|
+
const socketPath = options.socket || getSocketPath();
|
|
119
|
+
|
|
120
|
+
let data: unknown;
|
|
121
|
+
if (options.data) {
|
|
122
|
+
try {
|
|
123
|
+
data = JSON.parse(options.data);
|
|
124
|
+
} catch {
|
|
125
|
+
console.error("Invalid JSON data");
|
|
126
|
+
process.exit(1);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
await sendMessage(socketPath, {
|
|
132
|
+
type: options.type,
|
|
133
|
+
data,
|
|
134
|
+
});
|
|
135
|
+
console.log("Message sent");
|
|
136
|
+
} catch (err) {
|
|
137
|
+
console.error("Failed to send message:", err instanceof Error ? err.message : err);
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
// Env command - show environment info
|
|
143
|
+
program
|
|
144
|
+
.command("env")
|
|
145
|
+
.description("Show environment info")
|
|
146
|
+
.action(() => {
|
|
147
|
+
const tmuxInfo = getEnvInfo();
|
|
148
|
+
const itermInfo = getITermEnvInfo();
|
|
149
|
+
console.log("Environment:");
|
|
150
|
+
console.log(` In iTerm2: ${itermInfo.inITerm ? "Yes" : "No"}`);
|
|
151
|
+
console.log(` In tmux: ${tmuxInfo.inTmux ? "Yes" : "No"}`);
|
|
152
|
+
console.log(` TERM_PROGRAM: ${itermInfo.termProgram}`);
|
|
153
|
+
console.log(` TERM: ${tmuxInfo.term}`);
|
|
154
|
+
console.log(` SHELL: ${tmuxInfo.shell}`);
|
|
155
|
+
console.log(` Socket: ${getSocketPath()}`);
|
|
156
|
+
if (tmuxInfo.inTmux) {
|
|
157
|
+
console.log(` Stored tmux pane: ${tmuxInfo.storedPaneId || "none"}`);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// Default to show if no command given
|
|
162
|
+
if (process.argv.length === 2) {
|
|
163
|
+
process.argv.push("show");
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
program.parse();
|