vibe-pomo 0.2.1 → 0.2.2
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/README.md +6 -2
- package/README.zh.md +6 -2
- package/bin/pomodoro.mjs +18 -48
- package/install.mjs +2 -17
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -27,6 +27,8 @@ Every session is logged — what the agent did, what you did — giving you a cl
|
|
|
27
27
|
|
|
28
28
|
**Prerequisites:** Node.js 20+, Claude Code CLI
|
|
29
29
|
|
|
30
|
+
**Recommended:** run Claude Code inside `tmux`. That is the primary supported interactive timer experience: vibe-pomo uses a `tmux` popup to cover the current pane during a Pomodoro. Outside `tmux`, sessions still run, but timer UI falls back to headless mode.
|
|
31
|
+
|
|
30
32
|
```bash
|
|
31
33
|
npm i -g vibe-pomo
|
|
32
34
|
pomodoro install
|
|
@@ -71,6 +73,8 @@ pomodoro daemon
|
|
|
71
73
|
|
|
72
74
|
### 2. Start a session
|
|
73
75
|
|
|
76
|
+
For the intended covered-screen workflow, open Claude Code inside a `tmux` session before running `/pomodoro ...`.
|
|
77
|
+
|
|
74
78
|
```bash
|
|
75
79
|
# From Claude Code (recommended)
|
|
76
80
|
/pomodoro 25m Refactor the auth module
|
|
@@ -80,7 +84,7 @@ pomodoro start 25m Refactor the auth module
|
|
|
80
84
|
pomodoro start Refactor the auth module # uses default duration
|
|
81
85
|
```
|
|
82
86
|
|
|
83
|
-
If Claude Code is running inside `tmux`, vibe-pomo opens a popup over the current pane so the ongoing task stays covered until you end or break the session. Outside `tmux`, it
|
|
87
|
+
If Claude Code is running inside `tmux`, vibe-pomo opens a popup over the current pane so the ongoing task stays covered until you end or break the session. Outside `tmux`, it stays headless: the session still runs, but visualization remains in the daemon dashboard and stats view instead of opening another terminal window.
|
|
84
88
|
|
|
85
89
|
```
|
|
86
90
|
🍅 Pomodoro
|
|
@@ -163,7 +167,7 @@ Recent Sessions
|
|
|
163
167
|
|--------|--------|-------------|
|
|
164
168
|
| `defaultDurationMs` | ms | Default session duration (25 min = `1500000`) |
|
|
165
169
|
| `decisionStrategy` | `"wait"` / `"break"` | When the agent is blocked: wait silently until you end the session (default), or end immediately |
|
|
166
|
-
| `terminalEmulator` | `"auto"` / `"tmux"` / `"
|
|
170
|
+
| `terminalEmulator` | `"auto"` / `"tmux"` / `"none"` | Timer surface. `"tmux"` opens a popup overlay, `"none"` forces headless mode, and `"auto"` uses the popup only when `$TMUX` is set. |
|
|
167
171
|
| `soundOnOvertime` | bool | Play a sound when the timer hits zero |
|
|
168
172
|
|
|
169
173
|
---
|
package/README.zh.md
CHANGED
|
@@ -84,6 +84,8 @@ What did you do during this session?
|
|
|
84
84
|
|
|
85
85
|
**前置条件:** Node.js 20+、Claude Code CLI
|
|
86
86
|
|
|
87
|
+
**推荐条件:** 请在 `tmux` 里运行 Claude Code。这是 vibe-pomo 当前主推的交互方式:番茄钟会通过 `tmux popup` 覆盖当前 pane。非 `tmux` 环境下,会话仍然会正常运行,但计时器 UI 会退化为无界面模式。
|
|
88
|
+
|
|
87
89
|
```bash
|
|
88
90
|
npm install -g vibe-pomo
|
|
89
91
|
pomodoro install
|
|
@@ -111,6 +113,8 @@ pomodoro daemon
|
|
|
111
113
|
|
|
112
114
|
### 2. 开始一个会话
|
|
113
115
|
|
|
116
|
+
如果你希望获得“盖住当前 Claude Code 窗口”的预期体验,请先在 `tmux` session 里打开 Claude Code,再执行 `/pomodoro ...`。
|
|
117
|
+
|
|
114
118
|
```bash
|
|
115
119
|
# 在 Claude Code 中(推荐)
|
|
116
120
|
/pomodoro 25m Refactor the auth module
|
|
@@ -120,7 +124,7 @@ pomodoro start 25m Refactor the auth module
|
|
|
120
124
|
pomodoro start Refactor the auth module # 使用默认时长
|
|
121
125
|
```
|
|
122
126
|
|
|
123
|
-
如果 Claude Code 跑在 `tmux` 里,vibe-pomo 会在当前 pane 上弹出一个覆盖式 popup,把正在进行的任务界面盖住,直到你结束或中断番茄钟。非 `tmux`
|
|
127
|
+
如果 Claude Code 跑在 `tmux` 里,vibe-pomo 会在当前 pane 上弹出一个覆盖式 popup,把正在进行的任务界面盖住,直到你结束或中断番茄钟。非 `tmux` 环境下则保持无界面模式:会话照常运行,但只通过 daemon 仪表板和统计视图展示,不再额外弹出终端窗口。
|
|
124
128
|
|
|
125
129
|
### 3. 会话进行中
|
|
126
130
|
|
|
@@ -177,7 +181,7 @@ Recent Sessions
|
|
|
177
181
|
|------|------|------|
|
|
178
182
|
| `defaultDurationMs` | 毫秒数 | 默认会话时长(25 分钟 = `1500000`) |
|
|
179
183
|
| `decisionStrategy` | `"wait"` / `"break"` | 代理被阻塞时的策略:静默等待直到你结束会话(默认),或立即结束 |
|
|
180
|
-
| `terminalEmulator` | `"auto"` / `"tmux"` / `"
|
|
184
|
+
| `terminalEmulator` | `"auto"` / `"tmux"` / `"none"` | 计时器展示方式。`"tmux"` 打开覆盖式 popup,`"none"` 强制无界面模式,`"auto"` 仅在检测到 `$TMUX` 时使用 popup |
|
|
181
185
|
| `soundOnOvertime` | 布尔值 | 计时归零时播放提示音 |
|
|
182
186
|
|
|
183
187
|
---
|
package/bin/pomodoro.mjs
CHANGED
|
@@ -109,20 +109,16 @@ async function cmdStart(args) {
|
|
|
109
109
|
spawnWatcher(resp.sessionId)
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
//
|
|
112
|
+
// Only launch an interactive timer UI when we can safely cover the current
|
|
113
|
+
// Claude Code pane with a tmux popup. Otherwise stay headless and let the
|
|
114
|
+
// daemon/dashboard own visualization so the conversation flow is not disturbed.
|
|
113
115
|
const timerEntry = join(ROOT, 'src', 'tui', 'timer', 'index.tsx')
|
|
114
|
-
|
|
116
|
+
await launchTerminal({
|
|
115
117
|
tsx: TSX,
|
|
116
118
|
entryFile: timerEntry,
|
|
117
119
|
sessionId: resp.sessionId,
|
|
118
120
|
termPref: config.terminalEmulator,
|
|
119
121
|
})
|
|
120
|
-
|
|
121
|
-
if (!launched) {
|
|
122
|
-
console.log(`POMODORO_TIMER_NOT_LAUNCHED`)
|
|
123
|
-
console.log(` To watch the timer: node ${TSX} ${timerEntry} ${resp.sessionId}`)
|
|
124
|
-
console.log(` To end the session: node ${join(ROOT, 'bin', 'pomodoro.mjs')} stop`)
|
|
125
|
-
}
|
|
126
122
|
}
|
|
127
123
|
|
|
128
124
|
async function cmdStop(args) {
|
|
@@ -187,52 +183,23 @@ async function cmdStopDaemon() {
|
|
|
187
183
|
// ── Terminal launch helpers ───────────────────────────────────────────────────
|
|
188
184
|
|
|
189
185
|
async function launchTerminal({ tsx, entryFile, sessionId, termPref }) {
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
for (const term of terminals) {
|
|
195
|
-
const ok = await trySpawn(term, tsx, entryFile, sessionId)
|
|
196
|
-
if (ok) return true
|
|
197
|
-
}
|
|
198
|
-
return false
|
|
186
|
+
const mode = resolveTimerMode(termPref)
|
|
187
|
+
if (mode !== 'tmux-popup') return false
|
|
188
|
+
return trySpawn(mode, tsx, entryFile, sessionId)
|
|
199
189
|
}
|
|
200
190
|
|
|
201
|
-
function
|
|
202
|
-
const
|
|
203
|
-
if (
|
|
204
|
-
|
|
205
|
-
return
|
|
191
|
+
function resolveTimerMode(termPref) {
|
|
192
|
+
const pref = termPref ?? 'auto'
|
|
193
|
+
if (pref === 'none' || pref === 'headless') return 'none'
|
|
194
|
+
if ((pref === 'auto' || pref === 'tmux' || pref === 'tmux-popup') && process.env.TMUX) {
|
|
195
|
+
return 'tmux-popup'
|
|
206
196
|
}
|
|
207
|
-
|
|
208
|
-
if (process.env.TMUX) list.push('tmux-popup')
|
|
209
|
-
if (process.env.STY) list.push('screen')
|
|
210
|
-
if (process.env.KITTY_WINDOW_ID) list.push('kitty')
|
|
211
|
-
if (process.env.TERM_PROGRAM === 'WezTerm') list.push('wezterm')
|
|
212
|
-
list.push('tmux-window', 'gnome-terminal', 'xfce4-terminal', 'konsole', 'xterm', 'alacritty', 'wezterm', 'kitty')
|
|
213
|
-
return list
|
|
197
|
+
return 'none'
|
|
214
198
|
}
|
|
215
199
|
|
|
216
200
|
function buildCmd(term, tsx, entryFile, sessionId) {
|
|
217
|
-
// Quote paths for Windows (handles spaces in paths like AppData\Roaming\npm\...)
|
|
218
|
-
const q = isWin ? (p) => `"${p}"` : (p) => p
|
|
219
|
-
const inner = isWin
|
|
220
|
-
? `${q(tsx)} ${q(entryFile)} ${sessionId}`
|
|
221
|
-
: `${tsx} ${entryFile} ${sessionId}`
|
|
222
201
|
switch (term) {
|
|
223
|
-
case 'wt': return ['wt', 'new-tab', '--', 'cmd.exe', '/k', inner]
|
|
224
|
-
case 'cmd': return ['cmd.exe', '/c', `start cmd.exe /k "${inner}"`]
|
|
225
|
-
case 'tmux':
|
|
226
202
|
case 'tmux-popup': return buildTmuxPopupCmd(tsx, entryFile, sessionId)
|
|
227
|
-
case 'tmux-window': return ['tmux', 'new-window', inner]
|
|
228
|
-
case 'screen': return ['screen', '-X', 'screen', 'bash', '-c', inner]
|
|
229
|
-
case 'gnome-terminal': return ['gnome-terminal', '--', 'bash', '-c', inner]
|
|
230
|
-
case 'xfce4-terminal': return ['xfce4-terminal', '-e', inner]
|
|
231
|
-
case 'konsole': return ['konsole', '-e', inner]
|
|
232
|
-
case 'xterm': return ['xterm', '-e', inner]
|
|
233
|
-
case 'alacritty': return ['alacritty', '-e', 'bash', '-c', inner]
|
|
234
|
-
case 'wezterm': return ['wezterm', 'start', '--', 'bash', '-c', inner]
|
|
235
|
-
case 'kitty': return ['kitty', 'bash', '-c', inner]
|
|
236
203
|
default: return null
|
|
237
204
|
}
|
|
238
205
|
}
|
|
@@ -279,8 +246,11 @@ function buildTmuxPopupCmd(tsx, entryFile, sessionId) {
|
|
|
279
246
|
'tmux',
|
|
280
247
|
'display-popup',
|
|
281
248
|
'-E',
|
|
282
|
-
'-w', '
|
|
283
|
-
'-h', '
|
|
249
|
+
'-w', '100%',
|
|
250
|
+
'-h', '100%',
|
|
251
|
+
'-x', '0',
|
|
252
|
+
'-y', '0',
|
|
253
|
+
'-B',
|
|
284
254
|
'-T', 'Pomodoro',
|
|
285
255
|
`bash -lc ${shellQuote(timerCmd)}`,
|
|
286
256
|
]
|
package/install.mjs
CHANGED
|
@@ -109,23 +109,7 @@ argument-hint: "[duration e.g. 25m] [task description]"
|
|
|
109
109
|
node ${pomodoroPath} start $ARGUMENTS
|
|
110
110
|
\`\`\`
|
|
111
111
|
|
|
112
|
-
## Step 2:
|
|
113
|
-
|
|
114
|
-
Read the output from Step 1 carefully.
|
|
115
|
-
|
|
116
|
-
If the output contains **\`POMODORO_TIMER_NOT_LAUNCHED\`**, the system could not open a separate timer window (common in SSH, VSCode, or headless environments). In this case you MUST tell the user BEFORE doing any work:
|
|
117
|
-
|
|
118
|
-
> ⚠️ **No timer window could be opened automatically.**
|
|
119
|
-
>
|
|
120
|
-
> Run one of these in another terminal to control your Pomodoro:
|
|
121
|
-
> - **Watch timer:** (the command shown on the "To watch" line above)
|
|
122
|
-
> - **End session:** (the command shown on the "To end" line above)
|
|
123
|
-
>
|
|
124
|
-
> I'll now work on your task. The session will stay active until you run the stop command.
|
|
125
|
-
|
|
126
|
-
After telling the user that once, continue immediately. Do not wait for a reply.
|
|
127
|
-
|
|
128
|
-
## Step 3: Work autonomously during the focus session
|
|
112
|
+
## Step 2: Work autonomously during the focus session
|
|
129
113
|
|
|
130
114
|
The user has started a Pomodoro focus session and **will not be checking the screen** until the timer ends. Do not interrupt them.
|
|
131
115
|
|
|
@@ -136,6 +120,7 @@ The user has started a Pomodoro focus session and **will not be checking the scr
|
|
|
136
120
|
- Focus only on what is **unambiguously clear** from the task description
|
|
137
121
|
- If you encounter something that requires a user decision, **stop and record it** in \`.claude/pomodoro-pending.md\` — do NOT make assumptions or proceed on the user's behalf
|
|
138
122
|
- Do not send notifications or ask questions — the user is in focus mode
|
|
123
|
+
- If a timer UI is available, it may appear as a tmux popup. If not, continue headlessly — do not mention missing timer UI to the user unless they ask
|
|
139
124
|
- When you have done all you can, write a summary to \`.claude/pomodoro-summary.md\`
|
|
140
125
|
- Then wait quietly — the Pomodoro hook will manage the session lifecycle
|
|
141
126
|
`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vibe-pomo",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "You and your agent, both in flow. A Pomodoro timer for Claude Code that keeps agents working autonomously while you stay deep in focus — uninterrupted.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|