commandmate 0.2.8 → 0.2.10
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/.next/BUILD_ID +1 -1
- package/.next/app-build-manifest.json +8 -9
- package/.next/app-path-routes-manifest.json +1 -1
- package/.next/build-manifest.json +2 -2
- package/.next/cache/.tsbuildinfo +1 -1
- package/.next/cache/config.json +3 -3
- package/.next/cache/webpack/client-production/0.pack +0 -0
- package/.next/cache/webpack/client-production/1.pack +0 -0
- package/.next/cache/webpack/client-production/2.pack +0 -0
- package/.next/cache/webpack/client-production/index.pack +0 -0
- package/.next/cache/webpack/client-production/index.pack.old +0 -0
- package/.next/cache/webpack/edge-server-production/index.pack +0 -0
- package/.next/cache/webpack/server-production/0.pack +0 -0
- package/.next/cache/webpack/server-production/index.pack +0 -0
- package/.next/next-server.js.nft.json +1 -1
- package/.next/prerender-manifest.json +1 -1
- package/.next/required-server-files.json +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/api/app/update-check/route.js +1 -1
- package/.next/server/app/api/repositories/route.js +10 -10
- package/.next/server/app/api/repositories/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/auto-yes/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/auto-yes/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/current-output/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/current-output/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/files/[...path]/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/prompt-response/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/search/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tree/[...path]/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tree/route.js +1 -1
- package/.next/server/app/page.js +3 -3
- package/.next/server/app/page.js.nft.json +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/page.js +3 -3
- package/.next/server/app/worktrees/[id]/page.js.nft.json +1 -1
- package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
- package/.next/server/app-paths-manifest.json +7 -7
- package/.next/server/chunks/2683.js +1 -1
- package/.next/server/chunks/5823.js +1 -1
- package/.next/server/chunks/667.js +1 -0
- package/.next/server/chunks/6837.js +1 -1
- package/.next/server/chunks/7266.js +1 -1
- package/.next/server/chunks/7536.js +1 -1
- package/.next/server/chunks/7808.js +1 -0
- package/.next/server/chunks/8585.js +1 -1
- package/.next/server/chunks/9238.js +35 -0
- package/.next/server/functions-config-manifest.json +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/2335-98a211e00b94c7ac.js +1 -0
- package/.next/static/chunks/{4733-50bdfc169adb4881.js → 5970-dc8fb1c8c0217636.js} +1 -1
- package/.next/static/chunks/{6140-389f1951062dcf4f.js → 8864-2f60eadc8404fdd0.js} +1 -1
- package/.next/static/chunks/app/page-a6593b9640df66a6.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/page-1b8e4c49fbaf3f99.js +1 -0
- package/.next/static/css/{6a92c8ad3c94d15a.css → a69d9c70fce558b4.css} +1 -1
- package/.next/trace +5 -5
- package/README.md +234 -47
- package/dist/server/src/lib/auto-yes-manager.js +10 -59
- package/dist/server/src/lib/prompt-answer-sender.js +89 -0
- package/dist/server/src/lib/prompt-detector.js +9 -0
- package/package.json +1 -1
- package/.next/server/chunks/4704.js +0 -35
- package/.next/server/chunks/5781.js +0 -1
- package/.next/static/chunks/2330-0299b9879f4977d2.js +0 -1
- package/.next/static/chunks/8216-00e20326f32abd12.js +0 -1
- package/.next/static/chunks/app/page-43b5de1a0a788b1f.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/page-a836cda4ee0339c5.js +0 -1
- /package/.next/static/{yrO0L8bN6ioX1pKYKzlmV → NGcx1ej6oVBba0MO0bwCg}/_buildManifest.js +0 -0
- /package/.next/static/{yrO0L8bN6ioX1pKYKzlmV → NGcx1ej6oVBba0MO0bwCg}/_ssgManifest.js +0 -0
package/README.md
CHANGED
|
@@ -1,26 +1,156 @@
|
|
|
1
1
|
# CommandMate
|
|
2
2
|
|
|
3
|
+

|
|
4
|
+

|
|
5
|
+

|
|
6
|
+

|
|
7
|
+
**Status: Beta**
|
|
8
|
+
|
|
3
9
|
[English](./README.md) | [日本語](./docs/ja/README.md)
|
|
4
10
|
|
|
5
|
-
|
|
6
|
-
|
|
11
|
+
<!-- TODO: Add a 30-second demo GIF here to boost adoption -->
|
|
12
|
+
<!-- Example:  -->
|
|
13
|
+
|
|
14
|
+
> **Your AI coding companion — never miss a prompt, work from anywhere.**
|
|
15
|
+
|
|
16
|
+
- **Detect prompt/confirmation state** in real-time
|
|
17
|
+
- **Send instructions from mobile or desktop** — no need to sit at your PC
|
|
18
|
+
- **Manage sessions per Git worktree** — run parallel tasks with ease
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install -g commandmate
|
|
22
|
+
```
|
|
7
23
|
|
|
8
24
|

|
|
9
25
|
|
|
26
|
+
## Table of Contents
|
|
27
|
+
|
|
28
|
+
- [What is this?](#what-is-this)
|
|
29
|
+
- [Who is this for?](#who-is-this-for)
|
|
30
|
+
- [What makes it unique?](#what-makes-it-unique)
|
|
31
|
+
- [Quick Start](#quick-start-3-steps)
|
|
32
|
+
- [Troubleshooting](#troubleshooting)
|
|
33
|
+
- [How it works](#how-it-works)
|
|
34
|
+
- [Key Features](#key-features)
|
|
35
|
+
- [Use Cases](#use-cases)
|
|
36
|
+
- [Security](#security)
|
|
37
|
+
- [CLI Commands](#cli-commands)
|
|
38
|
+
- [Developer Setup](#developer-setup)
|
|
39
|
+
- [FAQ](#faq)
|
|
40
|
+
- [Documentation](#documentation)
|
|
41
|
+
- [Contributing](#contributing)
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
10
45
|
## What is this?
|
|
11
46
|
|
|
12
47
|
A development companion tool that manages Claude Code sessions per Git worktree and lets you send instructions from your browser.
|
|
13
48
|
|
|
14
49
|
During your commute, childcare breaks, or lunch — send the next instruction as easily as replying to an email, and keep your side projects moving forward.
|
|
15
50
|
|
|
16
|
-
##
|
|
51
|
+
## Who is this for?
|
|
52
|
+
|
|
53
|
+
**Great fit:**
|
|
54
|
+
- Developers juggling childcare, commutes, or meetings — can't sit at the PC all day
|
|
55
|
+
- Users who miss Claude Code's input prompts and lose flow
|
|
56
|
+
- Teams using Git worktree for parallel development but finding tmux management tedious
|
|
57
|
+
|
|
58
|
+
**Not ideal for:**
|
|
59
|
+
- GUI IDE-only workflows (CommandMate is terminal/CLI-based)
|
|
60
|
+
- Multi-user SaaS expectations (CommandMate is designed for local, individual use)
|
|
61
|
+
|
|
62
|
+
## What makes it unique?
|
|
63
|
+
|
|
64
|
+
CommandMate is not a terminal replacement. It **complements** Claude Code by focusing on three things:
|
|
65
|
+
|
|
66
|
+
- **Prompt detection** — know instantly when Claude Code needs your input
|
|
67
|
+
- **Response UI** — reply from any browser, including your phone
|
|
68
|
+
- **Worktree organization** — manage multiple sessions in one place
|
|
69
|
+
|
|
70
|
+
Supports **Claude Code**, **Codex CLI**, and **Gemini CLI**. Built with the Strategy pattern for extensibility — adding new CLI tools is straightforward.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Quick Start (3 Steps)
|
|
75
|
+
|
|
76
|
+
**Prerequisites:** macOS / Linux, Node.js v20+, npm, git, tmux, openssl
|
|
77
|
+
|
|
78
|
+
> Windows is not supported due to the tmux dependency. WSL2 has not been tested.
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# 1. Install
|
|
82
|
+
npm install -g commandmate
|
|
83
|
+
|
|
84
|
+
# 2. Initialize (dependency check, environment setup, DB init)
|
|
85
|
+
commandmate init
|
|
86
|
+
|
|
87
|
+
# 3. Start
|
|
88
|
+
commandmate start --daemon
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Open http://localhost:3000 in your browser.
|
|
92
|
+
|
|
93
|
+
**Useful commands:**
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
commandmate status # Check server status
|
|
97
|
+
commandmate stop # Stop the server
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
See the [CLI Setup Guide](./docs/en/user-guide/cli-setup-guide.md) for details.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Troubleshooting
|
|
105
|
+
|
|
106
|
+
**Claude CLI not found / path changed?**
|
|
107
|
+
If you switch between npm and standalone versions of Claude CLI, the path may change. CommandMate auto-detects the new path on the next session start. To set a custom path, add `CLAUDE_PATH=/path/to/claude` to `.env`.
|
|
108
|
+
|
|
109
|
+
**Port conflict?**
|
|
110
|
+
```bash
|
|
111
|
+
commandmate start -p 3001
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**Session stuck or not responding?**
|
|
115
|
+
Check tmux sessions directly. CommandMate manages sessions with the naming format `mcbd-{tool}-{worktree}`:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
# List all CommandMate sessions
|
|
119
|
+
tmux list-sessions | grep mcbd
|
|
120
|
+
|
|
121
|
+
# View session output (without attaching)
|
|
122
|
+
tmux capture-pane -t "mcbd-claude-feature-123" -p
|
|
123
|
+
|
|
124
|
+
# Attach to inspect (detach with Ctrl+b then d)
|
|
125
|
+
tmux attach -t "mcbd-claude-feature-123"
|
|
17
126
|
|
|
18
|
-
|
|
19
|
-
-
|
|
127
|
+
# Kill a broken session
|
|
128
|
+
tmux kill-session -t "mcbd-claude-feature-123"
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
> **Note:** When attached, avoid typing directly into the session — this can interfere with CommandMate's session management. Use `Ctrl+b` then `d` to detach and operate through the CommandMate UI instead.
|
|
132
|
+
|
|
133
|
+
**Sessions fail when launching from within Claude Code?**
|
|
134
|
+
Claude Code sets `CLAUDECODE=1` to prevent nesting. CommandMate removes this automatically, but if it persists, run: `tmux set-environment -g -u CLAUDECODE`
|
|
20
135
|
|
|
21
|
-
|
|
136
|
+
---
|
|
22
137
|
|
|
23
|
-
|
|
138
|
+
## How it works
|
|
139
|
+
|
|
140
|
+
CommandMate treats Claude Code (CLI) as a managed "execution session", making its state (running / waiting for input / idle) visible through a web UI.
|
|
141
|
+
|
|
142
|
+
```mermaid
|
|
143
|
+
flowchart LR
|
|
144
|
+
A["Browser / Phone"] -->|HTTP| B["CommandMate Server"]
|
|
145
|
+
B --> C["Session Manager"]
|
|
146
|
+
C -->|"spawn / attach"| D["tmux sessions<br/>(per worktree)"]
|
|
147
|
+
D --> E["Claude Code CLI"]
|
|
148
|
+
C <-->|"read / write"| F[("Local DB<br/>& State")]
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Each Git worktree gets its own tmux session, so you can run multiple tasks in parallel without interference.
|
|
152
|
+
|
|
153
|
+
---
|
|
24
154
|
|
|
25
155
|
## Key Features
|
|
26
156
|
|
|
@@ -28,13 +158,17 @@ Developers with Claude Code experience who want to continue personal projects al
|
|
|
28
158
|
- **Send instructions from browser** — Operate via message UI from both mobile and desktop
|
|
29
159
|
- **Execution history & notes** — Retains conversation history per branch with note-taking support
|
|
30
160
|
- **Markdown log viewer** — View Claude's detailed output in Markdown format
|
|
31
|
-
- **File viewer** — Browse worktree files from the browser
|
|
161
|
+
- **File viewer** — Browse worktree files from the browser with file operations (move, copy, delete)
|
|
162
|
+
- **File timestamps** — Display file creation time in the file tree
|
|
32
163
|
- **Auto Yes mode** — Control automatic approval with a confirmation dialog
|
|
33
|
-
- **Repository
|
|
164
|
+
- **Repository management** — Remove repositories from app management (actual files are not deleted)
|
|
34
165
|
- **Clone URL registration** — Clone and register repositories by specifying HTTPS/SSH URLs
|
|
35
|
-
- **
|
|
166
|
+
- **Multi-CLI support** — Optimized for Claude Code, with Codex CLI and Gemini CLI support
|
|
36
167
|
- **Responsive UI** — Two-column layout on desktop, tab-based layout on mobile
|
|
37
168
|
|
|
169
|
+
<details>
|
|
170
|
+
<summary>Screenshots</summary>
|
|
171
|
+
|
|
38
172
|
### Worktree Detail View (Message / Console / History)
|
|
39
173
|
|
|
40
174
|
| Desktop | Mobile (History) | Mobile (Terminal) |
|
|
@@ -45,45 +179,106 @@ Developers with Claude Code experience who want to continue personal projects al
|
|
|
45
179
|
|
|
46
180
|

|
|
47
181
|
|
|
48
|
-
|
|
182
|
+
</details>
|
|
49
183
|
|
|
50
|
-
|
|
184
|
+
---
|
|
51
185
|
|
|
52
|
-
|
|
53
|
-
- Node.js v20+, npm, git, tmux, openssl
|
|
54
|
-
- Claude CLI (optional)
|
|
186
|
+
## Use Cases
|
|
55
187
|
|
|
56
|
-
###
|
|
188
|
+
### 1. Commute — pick up where you left off
|
|
57
189
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
190
|
+
- **Morning:** Kick off a task with Claude Code before leaving
|
|
191
|
+
- **Commute:** Check status on your phone, send the next instruction
|
|
192
|
+
- **Evening:** Review the results and merge when you get home
|
|
61
193
|
|
|
62
|
-
###
|
|
194
|
+
### 2. Childcare — 5-minute windows add up
|
|
63
195
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
```
|
|
196
|
+
- Split tasks across worktrees so each runs independently
|
|
197
|
+
- Check which sessions are waiting via CommandMate
|
|
198
|
+
- In a 5-minute break, send the next instruction and keep things moving
|
|
68
199
|
|
|
69
|
-
|
|
200
|
+
### 3. Parallel development — one UI for all your worktrees
|
|
201
|
+
|
|
202
|
+
- No need to juggle tmux panes manually
|
|
203
|
+
- See status of all worktrees at a glance in the sidebar
|
|
204
|
+
- Focus on decisions, not terminal management
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## Security
|
|
209
|
+
|
|
210
|
+
CommandMate runs **entirely locally** — the app, database, and sessions all stay on your machine. The only external communication is Claude CLI's own API calls.
|
|
211
|
+
|
|
212
|
+
**Recommended setup:**
|
|
213
|
+
- Use on `localhost` or within the same LAN
|
|
214
|
+
- For remote access, use a VPN or authenticated reverse proxy (Basic Auth, OIDC, etc.)
|
|
215
|
+
- Enabling external access via `commandmate init` sets `CM_BIND=0.0.0.0` — access from the same LAN at `http://<your-PC-IP>:3000`
|
|
216
|
+
|
|
217
|
+
**Do NOT:**
|
|
218
|
+
- Expose to the internet without authentication (never bind `0.0.0.0` without a reverse proxy)
|
|
219
|
+
|
|
220
|
+
See the [Security Guide](./docs/security-guide.md) and [Trust & Safety](./docs/en/TRUST_AND_SAFETY.md) for details.
|
|
70
221
|
|
|
71
|
-
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## CLI Commands
|
|
225
|
+
|
|
226
|
+
### Basic
|
|
72
227
|
|
|
73
228
|
| Command | Description |
|
|
74
229
|
|---------|-------------|
|
|
75
230
|
| `commandmate init` | Initial setup (interactive) |
|
|
76
231
|
| `commandmate init --defaults` | Initial setup (default values) |
|
|
232
|
+
| `commandmate init --force` | Overwrite existing configuration |
|
|
233
|
+
| `commandmate start` | Start the server (foreground) |
|
|
77
234
|
| `commandmate start --daemon` | Start in background |
|
|
235
|
+
| `commandmate start --dev` | Start in development mode |
|
|
78
236
|
| `commandmate start -p 3001` | Start on a specific port |
|
|
79
237
|
| `commandmate stop` | Stop the server |
|
|
238
|
+
| `commandmate stop --force` | Force stop (SIGKILL) |
|
|
80
239
|
| `commandmate status` | Check status |
|
|
81
240
|
|
|
82
|
-
|
|
241
|
+
### Worktree Parallel Development
|
|
83
242
|
|
|
84
|
-
|
|
243
|
+
Run separate servers per Issue/worktree with automatic port allocation.
|
|
244
|
+
|
|
245
|
+
| Command | Description |
|
|
246
|
+
|---------|-------------|
|
|
247
|
+
| `commandmate start --issue 123` | Start server for Issue #123 worktree |
|
|
248
|
+
| `commandmate start --issue 123 --auto-port` | Start with automatic port allocation |
|
|
249
|
+
| `commandmate start --issue 123 -p 3123` | Start on a specific port |
|
|
250
|
+
| `commandmate stop --issue 123` | Stop server for Issue #123 |
|
|
251
|
+
| `commandmate status --issue 123` | Check status for Issue #123 |
|
|
252
|
+
| `commandmate status --all` | Check status for all servers |
|
|
85
253
|
|
|
86
|
-
|
|
254
|
+
### GitHub Issue Management
|
|
255
|
+
|
|
256
|
+
Requires [gh CLI](https://cli.github.com/) to be installed.
|
|
257
|
+
|
|
258
|
+
| Command | Description |
|
|
259
|
+
|---------|-------------|
|
|
260
|
+
| `commandmate issue create` | Create a new issue |
|
|
261
|
+
| `commandmate issue create --bug` | Create with bug report template |
|
|
262
|
+
| `commandmate issue create --feature` | Create with feature request template |
|
|
263
|
+
| `commandmate issue create --question` | Create with question template |
|
|
264
|
+
| `commandmate issue create --title <title>` | Specify issue title |
|
|
265
|
+
| `commandmate issue create --body <body>` | Specify issue body |
|
|
266
|
+
| `commandmate issue create --labels <labels>` | Add labels (comma-separated) |
|
|
267
|
+
| `commandmate issue search <query>` | Search issues |
|
|
268
|
+
| `commandmate issue list` | List issues |
|
|
269
|
+
|
|
270
|
+
### Documentation
|
|
271
|
+
|
|
272
|
+
| Command | Description |
|
|
273
|
+
|---------|-------------|
|
|
274
|
+
| `commandmate docs` | Show documentation |
|
|
275
|
+
| `commandmate docs -s <section>` | Show a specific section |
|
|
276
|
+
| `commandmate docs -q <query>` | Search documentation |
|
|
277
|
+
| `commandmate docs --all` | List all available sections |
|
|
278
|
+
|
|
279
|
+
See `commandmate --help` for all options.
|
|
280
|
+
|
|
281
|
+
---
|
|
87
282
|
|
|
88
283
|
## Developer Setup
|
|
89
284
|
|
|
@@ -95,7 +290,8 @@ cd CommandMate
|
|
|
95
290
|
./scripts/setup.sh # Auto-runs dependency check, env setup, build, and launch
|
|
96
291
|
```
|
|
97
292
|
|
|
98
|
-
|
|
293
|
+
<details>
|
|
294
|
+
<summary>Manual Setup (for customization)</summary>
|
|
99
295
|
|
|
100
296
|
```bash
|
|
101
297
|
git clone https://github.com/Kewton/CommandMate.git
|
|
@@ -112,31 +308,22 @@ npm start
|
|
|
112
308
|
|
|
113
309
|
> **Note**: Legacy environment variable names (`MCBD_*`) are still supported for backward compatibility, but using the new names (`CM_*`) is recommended.
|
|
114
310
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
**Q: Does everything run locally?**
|
|
118
|
-
A: The app, database, and sessions all run entirely locally. The only external communication is the Claude CLI's own API calls.
|
|
311
|
+
</details>
|
|
119
312
|
|
|
120
|
-
|
|
121
|
-
A: You can use tunneling services like Cloudflare Tunnel. Within your home, simply connect your phone to the same Wi-Fi as your PC.
|
|
313
|
+
---
|
|
122
314
|
|
|
123
|
-
|
|
124
|
-
A: Claude Code's own permission settings apply as-is. This tool does not expand permissions. See [Trust & Safety](./docs/en/TRUST_AND_SAFETY.md) for details.
|
|
315
|
+
## FAQ
|
|
125
316
|
|
|
126
|
-
**Q:
|
|
127
|
-
A:
|
|
317
|
+
**Q: Is tmux required?**
|
|
318
|
+
A: CommandMate uses tmux internally to manage CLI sessions. You don't need to operate tmux directly — CommandMate handles it for you. If something goes wrong, you can inspect sessions via tmux commands (see [Troubleshooting](#troubleshooting)).
|
|
128
319
|
|
|
129
|
-
**Q:
|
|
130
|
-
A:
|
|
320
|
+
**Q: What about Claude Code's permissions?**
|
|
321
|
+
A: Claude Code's own permission settings apply as-is. CommandMate does not expand permissions. See [Trust & Safety](./docs/en/TRUST_AND_SAFETY.md) for details.
|
|
131
322
|
|
|
132
323
|
**Q: Can multiple people use it?**
|
|
133
324
|
A: Currently designed for individual use. Simultaneous multi-user access is not supported.
|
|
134
325
|
|
|
135
|
-
|
|
136
|
-
A: If you switch between npm and standalone versions of Claude CLI, the path may change. CommandMate will automatically detect the new path on the next session start attempt. If you want to specify a custom path, set the `CLAUDE_PATH` environment variable in `.env` (e.g., `CLAUDE_PATH=/opt/homebrew/bin/claude`).
|
|
137
|
-
|
|
138
|
-
**Q: Sessions fail to start when launching CommandMate from within Claude Code. Why?**
|
|
139
|
-
A: Claude Code sets the `CLAUDECODE=1` environment variable to prevent nested sessions. CommandMate automatically removes this variable from tmux sessions, so sessions should start normally. If the issue persists, manually run `tmux set-environment -g -u CLAUDECODE` to clear it from tmux's global environment.
|
|
326
|
+
---
|
|
140
327
|
|
|
141
328
|
## Documentation
|
|
142
329
|
|
|
@@ -25,7 +25,7 @@ exports.stopAllAutoYesPolling = stopAllAutoYesPolling;
|
|
|
25
25
|
const cli_session_1 = require("./cli-session");
|
|
26
26
|
const prompt_detector_1 = require("./prompt-detector");
|
|
27
27
|
const auto_yes_resolver_1 = require("./auto-yes-resolver");
|
|
28
|
-
const
|
|
28
|
+
const prompt_answer_sender_1 = require("./prompt-answer-sender");
|
|
29
29
|
const manager_1 = require("./cli-tools/manager");
|
|
30
30
|
const cli_patterns_1 = require("./cli-patterns");
|
|
31
31
|
const auto_yes_config_1 = require("../config/auto-yes-config");
|
|
@@ -261,64 +261,15 @@ async function pollAutoYes(worktreeId, cliToolId) {
|
|
|
261
261
|
const manager = manager_1.CLIToolManager.getInstance();
|
|
262
262
|
const cliTool = manager.getTool(cliToolId);
|
|
263
263
|
const sessionName = cliTool.getSessionName(worktreeId);
|
|
264
|
-
// Issue #
|
|
265
|
-
//
|
|
266
|
-
//
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
const defaultOption = mcOptions.find(o => o.isDefault);
|
|
274
|
-
const defaultNum = defaultOption?.number ?? 1;
|
|
275
|
-
const offset = targetNum - defaultNum;
|
|
276
|
-
// Detect multi-select (checkbox) prompts by checking for [ ] in option labels.
|
|
277
|
-
const isMultiSelect = mcOptions.some(o => /^\[[ x]\] /.test(o.label));
|
|
278
|
-
if (isMultiSelect) {
|
|
279
|
-
// Multi-select: toggle checkbox, then navigate to "Next" and submit
|
|
280
|
-
const checkboxCount = mcOptions.filter(o => /^\[[ x]\] /.test(o.label)).length;
|
|
281
|
-
const keys = [];
|
|
282
|
-
// 1. Navigate to target option
|
|
283
|
-
if (offset > 0) {
|
|
284
|
-
for (let i = 0; i < offset; i++)
|
|
285
|
-
keys.push('Down');
|
|
286
|
-
}
|
|
287
|
-
else if (offset < 0) {
|
|
288
|
-
for (let i = 0; i < Math.abs(offset); i++)
|
|
289
|
-
keys.push('Up');
|
|
290
|
-
}
|
|
291
|
-
// 2. Space to toggle checkbox
|
|
292
|
-
keys.push('Space');
|
|
293
|
-
// 3. Navigate to "Next" button (positioned right after all checkbox options)
|
|
294
|
-
const downToNext = checkboxCount - targetNum + 1;
|
|
295
|
-
for (let i = 0; i < downToNext; i++)
|
|
296
|
-
keys.push('Down');
|
|
297
|
-
// 4. Enter to submit
|
|
298
|
-
keys.push('Enter');
|
|
299
|
-
await (0, tmux_1.sendSpecialKeys)(sessionName, keys);
|
|
300
|
-
}
|
|
301
|
-
else {
|
|
302
|
-
// Single-select: navigate and Enter to select
|
|
303
|
-
const keys = [];
|
|
304
|
-
if (offset > 0) {
|
|
305
|
-
for (let i = 0; i < offset; i++)
|
|
306
|
-
keys.push('Down');
|
|
307
|
-
}
|
|
308
|
-
else if (offset < 0) {
|
|
309
|
-
for (let i = 0; i < Math.abs(offset); i++)
|
|
310
|
-
keys.push('Up');
|
|
311
|
-
}
|
|
312
|
-
keys.push('Enter');
|
|
313
|
-
await (0, tmux_1.sendSpecialKeys)(sessionName, keys);
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
else {
|
|
317
|
-
// Standard CLI prompt: send text + Enter (y/n, Approve?, etc.)
|
|
318
|
-
await (0, tmux_1.sendKeys)(sessionName, answer, false);
|
|
319
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
320
|
-
await (0, tmux_1.sendKeys)(sessionName, '', true);
|
|
321
|
-
}
|
|
264
|
+
// Issue #287 Bug2: Uses shared sendPromptAnswer() to unify logic
|
|
265
|
+
// with route.ts, including cursor-key navigation for Claude Code
|
|
266
|
+
// multiple-choice prompts and fallback handling.
|
|
267
|
+
await (0, prompt_answer_sender_1.sendPromptAnswer)({
|
|
268
|
+
sessionName,
|
|
269
|
+
answer,
|
|
270
|
+
cliToolId,
|
|
271
|
+
promptData: promptDetection.promptData,
|
|
272
|
+
});
|
|
322
273
|
// 6. Update timestamp
|
|
323
274
|
updateLastServerResponseTimestamp(worktreeId, Date.now());
|
|
324
275
|
// 7. Reset error count on success
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Shared prompt answer sender for cursor-key and text-based tmux input.
|
|
4
|
+
*
|
|
5
|
+
* Issue #287 Bug2: Extracted from route.ts and auto-yes-manager.ts to
|
|
6
|
+
* eliminate code duplication and ensure consistent behavior (including
|
|
7
|
+
* the promptType/defaultOptionNumber fallback introduced in Bug1).
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.sendPromptAnswer = sendPromptAnswer;
|
|
11
|
+
const tmux_1 = require("./tmux");
|
|
12
|
+
/** Regex pattern to detect checkbox-style multi-select options */
|
|
13
|
+
const CHECKBOX_OPTION_PATTERN = /^\[[ x]\] /;
|
|
14
|
+
/**
|
|
15
|
+
* Build navigation key array for cursor movement.
|
|
16
|
+
* @param offset - positive = Down, negative = Up
|
|
17
|
+
*/
|
|
18
|
+
function buildNavigationKeys(offset) {
|
|
19
|
+
if (offset === 0)
|
|
20
|
+
return [];
|
|
21
|
+
const direction = offset > 0 ? 'Down' : 'Up';
|
|
22
|
+
return Array.from({ length: Math.abs(offset) }, () => direction);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Send an answer to a tmux session, using cursor-key navigation for
|
|
26
|
+
* Claude Code multiple-choice prompts and text input for everything else.
|
|
27
|
+
*
|
|
28
|
+
* This function unifies the logic previously duplicated in:
|
|
29
|
+
* - src/app/api/worktrees/[id]/prompt-response/route.ts (L114-187)
|
|
30
|
+
* - src/lib/auto-yes-manager.ts (L340-399)
|
|
31
|
+
*/
|
|
32
|
+
async function sendPromptAnswer(params) {
|
|
33
|
+
const { sessionName, answer, cliToolId, promptData, fallbackPromptType, fallbackDefaultOptionNumber } = params;
|
|
34
|
+
// Determine if this is a Claude Code multiple-choice prompt requiring cursor navigation
|
|
35
|
+
const isClaudeMultiChoice = cliToolId === 'claude'
|
|
36
|
+
&& (promptData?.type === 'multiple_choice' || fallbackPromptType === 'multiple_choice')
|
|
37
|
+
&& /^\d+$/.test(answer);
|
|
38
|
+
if (isClaudeMultiChoice) {
|
|
39
|
+
const targetNum = parseInt(answer, 10);
|
|
40
|
+
let defaultNum;
|
|
41
|
+
let mcOptions = null;
|
|
42
|
+
if (promptData?.type === 'multiple_choice') {
|
|
43
|
+
// Primary path: use fresh promptData
|
|
44
|
+
mcOptions = promptData.options;
|
|
45
|
+
const defaultOption = mcOptions.find(o => o.isDefault);
|
|
46
|
+
defaultNum = defaultOption?.number ?? 1;
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
// Fallback path (Issue #287): promptData is undefined or type mismatch, use fallback fields
|
|
50
|
+
defaultNum = fallbackDefaultOptionNumber ?? 1;
|
|
51
|
+
}
|
|
52
|
+
const offset = targetNum - defaultNum;
|
|
53
|
+
// Detect multi-select (checkbox) prompts by checking for [ ] in option labels.
|
|
54
|
+
// Multi-select prompts require: Space to toggle checkbox -> navigate to "Next" -> Enter.
|
|
55
|
+
// Single-select prompts require: navigate to option -> Enter.
|
|
56
|
+
// Note: multi-select detection is only possible when promptData succeeded (mcOptions available).
|
|
57
|
+
const isMultiSelect = mcOptions !== null && mcOptions.some(o => CHECKBOX_OPTION_PATTERN.test(o.label));
|
|
58
|
+
if (isMultiSelect && mcOptions !== null) {
|
|
59
|
+
// Multi-select: toggle checkbox, then navigate to "Next" and submit
|
|
60
|
+
const checkboxCount = mcOptions.filter(o => CHECKBOX_OPTION_PATTERN.test(o.label)).length;
|
|
61
|
+
const keys = [
|
|
62
|
+
...buildNavigationKeys(offset), // 1. Navigate to target option
|
|
63
|
+
'Space', // 2. Toggle checkbox
|
|
64
|
+
];
|
|
65
|
+
// 3. Navigate to "Next" button (positioned right after all checkbox options)
|
|
66
|
+
const downToNext = checkboxCount - targetNum + 1;
|
|
67
|
+
keys.push(...buildNavigationKeys(downToNext));
|
|
68
|
+
// 4. Enter to submit
|
|
69
|
+
keys.push('Enter');
|
|
70
|
+
await (0, tmux_1.sendSpecialKeys)(sessionName, keys);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
// Single-select: navigate and Enter to select
|
|
74
|
+
const keys = [
|
|
75
|
+
...buildNavigationKeys(offset),
|
|
76
|
+
'Enter',
|
|
77
|
+
];
|
|
78
|
+
await (0, tmux_1.sendSpecialKeys)(sessionName, keys);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
// Standard CLI prompt: send text + Enter (y/n, Approve?, etc.)
|
|
83
|
+
await (0, tmux_1.sendKeys)(sessionName, answer, false);
|
|
84
|
+
// Wait a moment for the input to be processed
|
|
85
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
86
|
+
// Send Enter
|
|
87
|
+
await (0, tmux_1.sendKeys)(sessionName, '', true);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -561,6 +561,15 @@ function detectMultipleChoicePrompt(output, options) {
|
|
|
561
561
|
collectedOptions.unshift({ number, label, isDefault: false });
|
|
562
562
|
continue;
|
|
563
563
|
}
|
|
564
|
+
// [Issue #287 Bug3] User input prompt barrier:
|
|
565
|
+
// When no options have been collected yet and the line starts with ❯ (U+276F)
|
|
566
|
+
// but did NOT match DEFAULT_OPTION_PATTERN above, this line is a Claude Code
|
|
567
|
+
// user input prompt (e.g., "❯ 1", "❯ /command") or idle prompt ("❯").
|
|
568
|
+
// Anything above this line in the scrollback is historical conversation text,
|
|
569
|
+
// not an active prompt. Stop scanning to prevent false positives.
|
|
570
|
+
if (collectedOptions.length === 0 && line.startsWith('\u276F')) {
|
|
571
|
+
return noPromptResult(output);
|
|
572
|
+
}
|
|
564
573
|
// Non-option line handling
|
|
565
574
|
if (collectedOptions.length > 0 && line && !SEPARATOR_LINE_PATTERN.test(line)) {
|
|
566
575
|
// [MF-001 / Issue #256] Check if line is a question-like line BEFORE
|