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 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();