Probe (M11): every new turn passes prompt.submit, and a hook can hold it past 10 s inside a $ call.

人與 agent 協作的工作站。把 tmux session、Claude Code 串流、對話式 agent 統一在一個介面,跨 workspace、跨 host 並行作業。
仍在 alpha (
1.0.0-alpha.233),僅支援 macOS。原名tmux-box/tmux-ai-term。
terminal / stream(wrap) / 對話詞彙與設計定錨見 PRODUCT.md。
Go daemon + React 19 SPA + Electron 41 殼。
cd spa && pnpm install
pnpm dev # SPA dev server
pnpm test # vitest
pnpm build # SPA build
pnpm electron:build # 從 root;產出 dist/mac/ + dist/mac-arm64/
環境與跨機開發流程見 CLAUDE.md。
Daemon(Go)需要存取 private module lab.protype.tw/wake/nexen。建置前, 這台機器需完成兩項一次性設定:
go env -w GOPRIVATE=lab.protype.tw
git config --global url."ssh://git@lab.protype.tw:9079/".insteadOf "https://lab.protype.tw/"
make build(或單獨 make check-goenv)會先驗證這兩項,缺一就印出對應指令 並以非零狀態結束,不會進入 go build。
冷快取驗證(確認上述設定不依賴呼叫端的 shell 環境變數也能運作;spec §6 step 0):
GOWORK=off GOMODCACHE=$(mktemp -d) go build ./cmd/pdx
PRODUCT.md — 產品定位CLAUDE.md — 開發流程CHANGELOG.md — 版本歷史hooks/register.js 41 lines1// Probe 2: does an idle session's peer delivery pass through prompt.submit,
2// and can a prompt.submit hook hold the turn past 10 s inside a $ call?
3let n = 0
4
5async function log($, msg) {
6 const line = new Date().toISOString() + ' ' + msg + '\n'
7 try {
8 const path = (await $.session.cwd()) + '/probe.log'
9 const old = await $.fs.read(path).catch(() => '')
10 await $.fs.write(path, old + line)
11 } catch {}
12}
13
14export function register(on) {
15 on('session.start', async ($, e, next) => {
16 await log($, 'loaded session=' + (await $.session.id()))
17 return next(e)
18 })
19
20 on('session.receive', async ($, e, next) => {
21 await log($, 'receive origin=' + JSON.stringify(e.origin) + ' text=' + JSON.stringify(String(e.text).slice(-60)))
22 return next(e)
23 })
24
25 on('prompt.submit', async ($, e, next) => {
26 const id = ++n
27 await log($, 'submit#' + id + ' origin=' + JSON.stringify(e.origin || null) + ' agentId=' + (e.agentId || '-') + ' text=' + JSON.stringify(String(e.text).slice(-60)))
28 if (String(e.text).includes('HOLD15')) {
29 await log($, 'submit#' + id + ' holding 15s via $.process.run')
30 const r = await $.process.run(['/bin/sleep', '15'], { timeoutMs: 60000 })
31 await log($, 'submit#' + id + ' released exit=' + r.exitCode)
32 }
33 return next(e)
34 })
35
36 on('turn.start', async ($, e, next) => {
37 if (!e.agentId) await log($, 'turn.start')
38 return next(e)
39 })
40}
41