hjworktree-cli 2.0.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/.context-snapshots/context-snapshot-20260106-110353.md +66 -0
- package/.context-snapshots/context-snapshot-20260106-110441.md +66 -0
- package/.context-snapshots/context-snapshot-20260106-220000.md +99 -0
- package/AGENTS.md +29 -0
- package/CLAUDE.md +88 -0
- package/bin/cli.js +85 -0
- package/dist/server/index.d.ts +6 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +64 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/routes/api.d.ts +3 -0
- package/dist/server/routes/api.d.ts.map +1 -0
- package/dist/server/routes/api.js +101 -0
- package/dist/server/routes/api.js.map +1 -0
- package/dist/server/services/gitService.d.ts +13 -0
- package/dist/server/services/gitService.d.ts.map +1 -0
- package/dist/server/services/gitService.js +84 -0
- package/dist/server/services/gitService.js.map +1 -0
- package/dist/server/services/worktreeService.d.ts +17 -0
- package/dist/server/services/worktreeService.d.ts.map +1 -0
- package/dist/server/services/worktreeService.js +161 -0
- package/dist/server/services/worktreeService.js.map +1 -0
- package/dist/server/socketHandlers.d.ts +4 -0
- package/dist/server/socketHandlers.d.ts.map +1 -0
- package/dist/server/socketHandlers.js +118 -0
- package/dist/server/socketHandlers.js.map +1 -0
- package/dist/shared/constants.d.ts +10 -0
- package/dist/shared/constants.d.ts.map +1 -0
- package/dist/shared/constants.js +31 -0
- package/dist/shared/constants.js.map +1 -0
- package/dist/shared/types/index.d.ts +67 -0
- package/dist/shared/types/index.d.ts.map +1 -0
- package/dist/shared/types/index.js +3 -0
- package/dist/shared/types/index.js.map +1 -0
- package/dist/web/assets/index-C61yAbey.css +32 -0
- package/dist/web/assets/index-WEdVUKxb.js +53 -0
- package/dist/web/assets/index-WEdVUKxb.js.map +1 -0
- package/dist/web/index.html +16 -0
- package/package.json +63 -0
- package/server/index.ts +75 -0
- package/server/routes/api.ts +108 -0
- package/server/services/gitService.ts +91 -0
- package/server/services/worktreeService.ts +181 -0
- package/server/socketHandlers.ts +157 -0
- package/shared/constants.ts +35 -0
- package/shared/types/index.ts +92 -0
- package/tsconfig.json +20 -0
- package/web/index.html +15 -0
- package/web/src/App.tsx +65 -0
- package/web/src/components/Layout/Header.tsx +29 -0
- package/web/src/components/Layout/LeftNavBar.tsx +67 -0
- package/web/src/components/Layout/MainLayout.tsx +23 -0
- package/web/src/components/Layout/StepContainer.tsx +71 -0
- package/web/src/components/Setup/AgentSelector.tsx +27 -0
- package/web/src/components/Setup/BranchSelector.tsx +28 -0
- package/web/src/components/Setup/SetupPanel.tsx +32 -0
- package/web/src/components/Setup/WorktreeCountSelector.tsx +30 -0
- package/web/src/components/Steps/AgentStep.tsx +20 -0
- package/web/src/components/Steps/BranchStep.tsx +20 -0
- package/web/src/components/Steps/WorktreeStep.tsx +41 -0
- package/web/src/components/Terminal/TerminalPanel.tsx +113 -0
- package/web/src/components/Terminal/XTerminal.tsx +203 -0
- package/web/src/hooks/useSocket.ts +80 -0
- package/web/src/main.tsx +10 -0
- package/web/src/stores/useAppStore.ts +348 -0
- package/web/src/styles/global.css +695 -0
- package/web/tsconfig.json +23 -0
- package/web/vite.config.ts +32 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Context Snapshot
|
|
2
|
+
|
|
3
|
+
## Session Metadata
|
|
4
|
+
- **Created**: ${iso}
|
|
5
|
+
- **CLI**: Claude Code
|
|
6
|
+
- **Project**: /Users/hyungju-lee/workspace/work/new/utils/hjWorktree-cli
|
|
7
|
+
|
|
8
|
+
## Conversation Summary
|
|
9
|
+
|
|
10
|
+
### User Requests
|
|
11
|
+
- Investigate and fix `posix_spawnp failed` when starting agents after creating worktrees.
|
|
12
|
+
- Fix Codex CLI error: `The cursor position could not be read within a normal duration`.
|
|
13
|
+
- Allow returning to the branch selection screen after running agents.
|
|
14
|
+
- Generate `AGENTS.md` contributor guide (completed earlier in session).
|
|
15
|
+
|
|
16
|
+
### Completed Tasks
|
|
17
|
+
1. Added robust PTY spawn gating (serialization, cooldown, async backoff) and clearer spawn errors.
|
|
18
|
+
2. Fixed macOS `node-pty` `spawn-helper` permissions: runtime chmod + `postinstall` script.
|
|
19
|
+
3. Added DSR (cursor position) query handling in PTY output to respond to `ESC[6n`.
|
|
20
|
+
4. Added “return to branches” action from running step via left arrow, with cleanup.
|
|
21
|
+
5. Ran build and PTY smoke tests; verified spawn-helper fix.
|
|
22
|
+
|
|
23
|
+
### Modified Files
|
|
24
|
+
- `src/services/ptyService.ts`
|
|
25
|
+
- `src/services/agentService.ts`
|
|
26
|
+
- `src/hooks/useAgentRunner.ts`
|
|
27
|
+
- `src/hooks/useKeyboardNav.ts`
|
|
28
|
+
- `src/components/Layout/Footer.tsx`
|
|
29
|
+
- `src/App.tsx`
|
|
30
|
+
- `package.json`
|
|
31
|
+
- `scripts/fix-node-pty-permissions.js`
|
|
32
|
+
- `AGENTS.md`
|
|
33
|
+
|
|
34
|
+
## Technical Context
|
|
35
|
+
|
|
36
|
+
### Key Concepts
|
|
37
|
+
- node-pty PTY spawning (macOS `spawn-helper` permissions)
|
|
38
|
+
- Ink `useInput` key handling for navigation
|
|
39
|
+
- ANSI DSR cursor query/response (`ESC[6n` / `ESC[<row>;<col>R`)
|
|
40
|
+
- Worktree lifecycle cleanup and UI step transitions
|
|
41
|
+
|
|
42
|
+
### Important Changes
|
|
43
|
+
**src/services/ptyService.ts**
|
|
44
|
+
- Serialize PTY spawns with cooldown and async retry/backoff.
|
|
45
|
+
- Ensure cwd exists before spawn and provide richer spawn errors.
|
|
46
|
+
- Ensure `spawn-helper` executable on macOS (runtime check + chmod).
|
|
47
|
+
- Detect and answer DSR cursor position queries; buffer partial sequences.
|
|
48
|
+
|
|
49
|
+
**scripts/fix-node-pty-permissions.js**
|
|
50
|
+
- Postinstall helper that chmods `node-pty` `spawn-helper` under macOS.
|
|
51
|
+
|
|
52
|
+
**package.json**
|
|
53
|
+
- Added `postinstall` hook to run permission fix.
|
|
54
|
+
|
|
55
|
+
**src/hooks/useAgentRunner.ts / src/hooks/useKeyboardNav.ts / src/App.tsx / src/components/Layout/Footer.tsx**
|
|
56
|
+
- Added “return to branches” flow from running step (`←`), with cleanup and updated UI hints.
|
|
57
|
+
|
|
58
|
+
### Issues Found / Resolved
|
|
59
|
+
- `posix_spawnp failed`: Root cause was non-executable `spawn-helper` on macOS; fixed via chmod + postinstall.
|
|
60
|
+
- Codex cursor position error: PTY now responds to DSR queries to avoid cursor-read timeouts.
|
|
61
|
+
- No path back to branches from running step: added `←` handler to return safely.
|
|
62
|
+
|
|
63
|
+
## Next Steps
|
|
64
|
+
- Validate the full interactive flow: `npm run dev` → select branch/agent/parallel → run.
|
|
65
|
+
- Confirm Codex no longer shows cursor position error in the real terminal.
|
|
66
|
+
- If Codex still errors, capture full stderr (ideally with `RUST_BACKTRACE=1`) for diagnosis.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Context Snapshot
|
|
2
|
+
|
|
3
|
+
## Session Metadata
|
|
4
|
+
- **Created**: 2026-01-06T11:04:41+09:00
|
|
5
|
+
- **CLI**: Claude Code
|
|
6
|
+
- **Project**: /Users/hyungju-lee/workspace/work/new/utils/hjWorktree-cli
|
|
7
|
+
|
|
8
|
+
## Conversation Summary
|
|
9
|
+
|
|
10
|
+
### User Requests
|
|
11
|
+
- Investigate and fix `posix_spawnp failed` when starting agents after creating worktrees.
|
|
12
|
+
- Fix Codex CLI error: `The cursor position could not be read within a normal duration`.
|
|
13
|
+
- Allow returning to the branch selection screen after running agents.
|
|
14
|
+
- Generate `AGENTS.md` contributor guide (completed earlier in session).
|
|
15
|
+
|
|
16
|
+
### Completed Tasks
|
|
17
|
+
1. Added robust PTY spawn gating (serialization, cooldown, async backoff) and clearer spawn errors.
|
|
18
|
+
2. Fixed macOS `node-pty` `spawn-helper` permissions: runtime chmod + `postinstall` script.
|
|
19
|
+
3. Added DSR (cursor position) query handling in PTY output to respond to `ESC[6n`.
|
|
20
|
+
4. Added “return to branches” action from running step via left arrow, with cleanup.
|
|
21
|
+
5. Ran build and PTY smoke tests; verified spawn-helper fix.
|
|
22
|
+
|
|
23
|
+
### Modified Files
|
|
24
|
+
- `src/services/ptyService.ts`
|
|
25
|
+
- `src/services/agentService.ts`
|
|
26
|
+
- `src/hooks/useAgentRunner.ts`
|
|
27
|
+
- `src/hooks/useKeyboardNav.ts`
|
|
28
|
+
- `src/components/Layout/Footer.tsx`
|
|
29
|
+
- `src/App.tsx`
|
|
30
|
+
- `package.json`
|
|
31
|
+
- `scripts/fix-node-pty-permissions.js`
|
|
32
|
+
- `AGENTS.md`
|
|
33
|
+
|
|
34
|
+
## Technical Context
|
|
35
|
+
|
|
36
|
+
### Key Concepts
|
|
37
|
+
- node-pty PTY spawning (macOS `spawn-helper` permissions)
|
|
38
|
+
- Ink `useInput` key handling for navigation
|
|
39
|
+
- ANSI DSR cursor query/response (`ESC[6n` / `ESC[<row>;<col>R`)
|
|
40
|
+
- Worktree lifecycle cleanup and UI step transitions
|
|
41
|
+
|
|
42
|
+
### Important Changes
|
|
43
|
+
**src/services/ptyService.ts**
|
|
44
|
+
- Serialize PTY spawns with cooldown and async retry/backoff.
|
|
45
|
+
- Ensure cwd exists before spawn and provide richer spawn errors.
|
|
46
|
+
- Ensure `spawn-helper` executable on macOS (runtime check + chmod).
|
|
47
|
+
- Detect and answer DSR cursor position queries; buffer partial sequences.
|
|
48
|
+
|
|
49
|
+
**scripts/fix-node-pty-permissions.js**
|
|
50
|
+
- Postinstall helper that chmods `node-pty` `spawn-helper` under macOS.
|
|
51
|
+
|
|
52
|
+
**package.json**
|
|
53
|
+
- Added `postinstall` hook to run permission fix.
|
|
54
|
+
|
|
55
|
+
**src/hooks/useAgentRunner.ts / src/hooks/useKeyboardNav.ts / src/App.tsx / src/components/Layout/Footer.tsx**
|
|
56
|
+
- Added “return to branches” flow from running step (`←`), with cleanup and updated UI hints.
|
|
57
|
+
|
|
58
|
+
### Issues Found / Resolved
|
|
59
|
+
- `posix_spawnp failed`: Root cause was non-executable `spawn-helper` on macOS; fixed via chmod + postinstall.
|
|
60
|
+
- Codex cursor position error: PTY now responds to DSR queries to avoid cursor-read timeouts.
|
|
61
|
+
- No path back to branches from running step: added `←` handler to return safely.
|
|
62
|
+
|
|
63
|
+
## Next Steps
|
|
64
|
+
- Validate the full interactive flow: `npm run dev` → select branch/agent/parallel → run.
|
|
65
|
+
- Confirm Codex no longer shows cursor position error in the real terminal.
|
|
66
|
+
- If Codex still errors, capture full stderr (ideally with `RUST_BACKTRACE=1`) for diagnosis.
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Context Snapshot
|
|
2
|
+
|
|
3
|
+
## Session Metadata
|
|
4
|
+
- **Created**: 2026-01-06T22:00:00+09:00
|
|
5
|
+
- **CLI**: Claude Code
|
|
6
|
+
- **Project**: /Users/hyungju-lee/workspace/work/new/utils/hjWorktree-cli
|
|
7
|
+
|
|
8
|
+
## Conversation Summary
|
|
9
|
+
|
|
10
|
+
### User Requests
|
|
11
|
+
1. hjWorktree CLI 도구 개발 (git worktree를 활용한 병렬 AI 에이전트 실행)
|
|
12
|
+
2. Worktree 삭제 버그 수정 (`cannot delete branch used by worktree` 에러)
|
|
13
|
+
3. `d`/`D` 키로 worktree 삭제 기능 추가
|
|
14
|
+
4. `posix_spawnp failed` 에러 수정 (macOS ARM64에서 PTY 스폰 실패)
|
|
15
|
+
5. main-project-1, main-project-2, main-project-3 브랜치 삭제
|
|
16
|
+
|
|
17
|
+
### Completed Tasks
|
|
18
|
+
1. hjWorktree CLI 전체 구현 (Ink + node-pty + simple-git + Zustand)
|
|
19
|
+
2. `git worktree prune` 명령으로 orphan worktree 참조 정리 버그 수정
|
|
20
|
+
3. `d` 키 (현재 에이전트 삭제), `D` 키 (전체 삭제) 기능 추가
|
|
21
|
+
4. PTY 스폰 재시도 로직 추가 (최대 3회, 지수 백오프)
|
|
22
|
+
5. 에이전트 시작 사이 150ms 지연 추가
|
|
23
|
+
6. 디버그 로그 정리
|
|
24
|
+
7. 테스트 worktree 및 브랜치 삭제
|
|
25
|
+
|
|
26
|
+
### Modified Files
|
|
27
|
+
- `src/services/ptyService.ts` - PTY 스폰 재시도 로직 추가
|
|
28
|
+
- `src/services/worktreeService.ts` - `git worktree prune` 추가
|
|
29
|
+
- `src/services/agentService.ts` - `stopAndRemoveWorktree`, `stopAllAndRemoveWorktrees` 메서드 추가
|
|
30
|
+
- `src/hooks/useAgentRunner.ts` - 에이전트 시작 지연 추가, 삭제 함수 추가
|
|
31
|
+
- `src/hooks/useKeyboardNav.ts` - `d`/`D` 키 바인딩 추가
|
|
32
|
+
- `src/components/Layout/Footer.tsx` - 삭제 키 힌트 추가
|
|
33
|
+
|
|
34
|
+
## Technical Context
|
|
35
|
+
|
|
36
|
+
### Key Concepts
|
|
37
|
+
- **Ink**: React 기반 터미널 UI 프레임워크
|
|
38
|
+
- **node-pty**: PTY (pseudo-terminal) 관리
|
|
39
|
+
- **simple-git**: Git 작업 래퍼
|
|
40
|
+
- **Zustand**: 상태 관리
|
|
41
|
+
- **Git Worktree**: 동일 저장소에서 병렬 작업 디렉토리 생성
|
|
42
|
+
|
|
43
|
+
### Important Changes
|
|
44
|
+
|
|
45
|
+
**src/services/ptyService.ts**
|
|
46
|
+
```typescript
|
|
47
|
+
// PTY 스폰 재시도 로직 (posix_spawnp 실패 방지)
|
|
48
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
49
|
+
try {
|
|
50
|
+
ptyProcess = pty.spawn(...);
|
|
51
|
+
break;
|
|
52
|
+
} catch (error) {
|
|
53
|
+
// 100ms, 200ms 지수 백오프 대기 후 재시도
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**src/hooks/useAgentRunner.ts**
|
|
59
|
+
```typescript
|
|
60
|
+
// 에이전트 시작 사이 150ms 지연 (리소스 할당 시간 확보)
|
|
61
|
+
if (i > 0) {
|
|
62
|
+
await delay(150);
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**src/services/worktreeService.ts**
|
|
67
|
+
```typescript
|
|
68
|
+
// Worktree 삭제 후 orphan 참조 정리
|
|
69
|
+
await this.git.raw(['worktree', 'prune']);
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Resolved Issues
|
|
73
|
+
|
|
74
|
+
| 이슈 | 원인 | 해결책 |
|
|
75
|
+
|-----|------|-------|
|
|
76
|
+
| `cannot delete branch used by worktree` | `git worktree remove` 실패 후 `.git/worktrees/` 참조 잔존 | `git worktree prune` 추가 |
|
|
77
|
+
| `posix_spawnp failed` | macOS ARM64에서 빠른 연속 PTY 스폰 시 리소스 할당 실패 | 재시도 로직 + 스폰 간 지연 |
|
|
78
|
+
|
|
79
|
+
## Next Steps
|
|
80
|
+
|
|
81
|
+
### 테스트 필요
|
|
82
|
+
- `npm run dev` 실행 후 3개 이상 에이전트 병렬 시작 테스트
|
|
83
|
+
- `d`/`D` 키로 worktree 삭제 기능 테스트
|
|
84
|
+
|
|
85
|
+
### 키보드 바인딩 (running 단계)
|
|
86
|
+
| 키 | 기능 |
|
|
87
|
+
|---|---|
|
|
88
|
+
| `d` | 현재 선택된 에이전트 중지 + worktree 삭제 |
|
|
89
|
+
| `D` | 모든 에이전트 중지 + 모든 worktree 삭제 |
|
|
90
|
+
| `Enter` | 입력 모드 |
|
|
91
|
+
| `Ctrl+B` | 브로드캐스트 모드 |
|
|
92
|
+
| `q` | 종료 (worktree 유지) |
|
|
93
|
+
|
|
94
|
+
### Git Worktree 삭제 순서
|
|
95
|
+
```bash
|
|
96
|
+
git worktree remove <path> --force
|
|
97
|
+
git worktree prune
|
|
98
|
+
git branch -D <branch-name>
|
|
99
|
+
```
|
package/AGENTS.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Repository Guidelines
|
|
2
|
+
|
|
3
|
+
## Project Structure & Module Organization
|
|
4
|
+
- `src/` contains the TypeScript + Ink UI app. Key areas: `components/` (UI), `hooks/` (React hooks), `services/` (Git/agent/PTY logic), `stores/` (Zustand state), `utils/`, `constants/`, and `types/`.
|
|
5
|
+
- `src/App.tsx` wires the UI; `src/index.tsx` is the CLI entry that renders the Ink app.
|
|
6
|
+
- `bin/hjWorktree.js` is the executable shim configured in `package.json`.
|
|
7
|
+
- `dist/` is the compiled output from `tsc` (do not edit by hand).
|
|
8
|
+
|
|
9
|
+
## Build, Test, and Development Commands
|
|
10
|
+
- `npm run dev` runs the CLI in development using `tsx` (fast TypeScript execution).
|
|
11
|
+
- `npm run build` compiles TypeScript to `dist/` via `tsc`.
|
|
12
|
+
- `npm run start` runs the compiled CLI from `dist/`.
|
|
13
|
+
- `npm run prepublishOnly` builds before publishing.
|
|
14
|
+
|
|
15
|
+
## Coding Style & Naming Conventions
|
|
16
|
+
- TypeScript + React (Ink) with ES modules; keep local imports using `.js` extensions (for ESM output).
|
|
17
|
+
- Use 2-space indentation, semicolons, and single quotes, matching existing files.
|
|
18
|
+
- Naming patterns: React components in `PascalCase` under `src/components/`; hooks `useThing.ts`; services `*Service.ts`; Zustand store `useAppStore.ts`.
|
|
19
|
+
|
|
20
|
+
## Testing Guidelines
|
|
21
|
+
- No automated test suite is configured yet. If you add tests, introduce a `test` script in `package.json` and document the framework and file pattern (for example, `*.test.ts`).
|
|
22
|
+
|
|
23
|
+
## Commit & Pull Request Guidelines
|
|
24
|
+
- Recent history favors conventional-style prefixes (for example `feat:`, `docs:`, `rebrand:`). Some older commits are terse; new commits should be descriptive and use a clear prefix when possible.
|
|
25
|
+
- PRs should include a concise description, how you verified changes (commands run), and any user-visible CLI output changes (paste a short snippet when helpful).
|
|
26
|
+
|
|
27
|
+
## Configuration Notes
|
|
28
|
+
- Requires Node.js `>=20` (see `package.json`).
|
|
29
|
+
- Keep `dist/` in sync by running `npm run build` before releases.
|
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
hjWorktree CLI is a web-based tool that uses git worktree to run multiple AI coding agents (Codex CLI, Claude Code, Gemini CLI) in parallel. Built with React, xterm.js, Socket.IO, node-pty, simple-git, and Zustand.
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm i -g hjworktree-cli # Install globally
|
|
13
|
+
cd /path/to/project # Navigate to your project
|
|
14
|
+
hjWorktree # Start web UI (opens browser automatically)
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Commands
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm run dev # Run development mode (server + web)
|
|
21
|
+
npm run dev:server # Run server only (tsx watch)
|
|
22
|
+
npm run dev:web # Run web dev server only (Vite)
|
|
23
|
+
npm run build # Build server + web for production
|
|
24
|
+
npm run start # Run production server
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Architecture
|
|
28
|
+
|
|
29
|
+
### Directory Structure
|
|
30
|
+
```
|
|
31
|
+
hjWorktree-cli/
|
|
32
|
+
├── bin/cli.js # CLI entry point (starts server + opens browser)
|
|
33
|
+
├── server/ # Backend (Express + Socket.IO)
|
|
34
|
+
│ ├── index.ts # Server entry point
|
|
35
|
+
│ ├── socketHandlers.ts # Terminal PTY via Socket.IO
|
|
36
|
+
│ ├── routes/api.ts # REST API (branches, worktrees)
|
|
37
|
+
│ └── services/ # Git and worktree services
|
|
38
|
+
├── web/ # Frontend (React + xterm.js)
|
|
39
|
+
│ ├── src/App.tsx
|
|
40
|
+
│ ├── src/components/ # Setup and Terminal components
|
|
41
|
+
│ ├── src/hooks/ # useSocket hook
|
|
42
|
+
│ └── src/stores/ # Zustand state management
|
|
43
|
+
├── shared/ # Shared types and constants
|
|
44
|
+
└── dist/ # Production build output
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Backend (server/)
|
|
48
|
+
- **index.ts** - Express server with Socket.IO for real-time terminal communication
|
|
49
|
+
- **socketHandlers.ts** - PTY session management (create, input, resize, kill)
|
|
50
|
+
- **routes/api.ts** - REST API for branches and worktrees CRUD
|
|
51
|
+
- **services/gitService.ts** - Git operations via simple-git
|
|
52
|
+
- **services/worktreeService.ts** - Worktree CRUD with rollback on failure
|
|
53
|
+
|
|
54
|
+
### Frontend (web/)
|
|
55
|
+
- **components/Setup/** - Branch selector, agent selector, worktree count
|
|
56
|
+
- **components/Terminal/** - xterm.js terminal with FitAddon
|
|
57
|
+
- **hooks/useSocket.ts** - Socket.IO client singleton
|
|
58
|
+
- **stores/useAppStore.ts** - Zustand store for app state
|
|
59
|
+
|
|
60
|
+
### Shared (shared/)
|
|
61
|
+
- **types/index.ts** - TypeScript types shared between frontend and backend
|
|
62
|
+
- **constants.ts** - AI agents configuration, port, app info
|
|
63
|
+
|
|
64
|
+
## Key Technical Details
|
|
65
|
+
|
|
66
|
+
### Terminal Communication
|
|
67
|
+
- xterm.js on frontend connects via Socket.IO to node-pty on backend
|
|
68
|
+
- Events: `terminal:create`, `terminal:input`, `terminal:output`, `terminal:resize`, `terminal:kill`
|
|
69
|
+
- ResizeObserver + FitAddon for responsive terminal sizing
|
|
70
|
+
|
|
71
|
+
### Worktree Cleanup
|
|
72
|
+
When removing worktrees, always run `git worktree prune` after `git worktree remove --force` to clear orphan references in `.git/worktrees/`, otherwise branch deletion fails.
|
|
73
|
+
|
|
74
|
+
### API Endpoints
|
|
75
|
+
| Method | Endpoint | Description |
|
|
76
|
+
|--------|----------|-------------|
|
|
77
|
+
| GET | /api/info | Project info (cwd, current branch) |
|
|
78
|
+
| GET | /api/branches | List all branches |
|
|
79
|
+
| POST | /api/worktrees | Create multiple worktrees |
|
|
80
|
+
| DELETE | /api/worktrees/:name | Delete single worktree |
|
|
81
|
+
| DELETE | /api/worktrees | Delete all worktrees |
|
|
82
|
+
|
|
83
|
+
## Code Style
|
|
84
|
+
|
|
85
|
+
- TypeScript with ESM
|
|
86
|
+
- Import local files with `.js` extension (ESM output)
|
|
87
|
+
- 2-space indentation, semicolons, single quotes
|
|
88
|
+
- Components: PascalCase, Hooks: `useThing.ts`, Services: `*Service.ts`
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { spawn, execSync } from 'child_process';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import fs from 'fs';
|
|
7
|
+
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = path.dirname(__filename);
|
|
10
|
+
|
|
11
|
+
const PORT = process.env.PORT || 3847;
|
|
12
|
+
const CWD = process.cwd();
|
|
13
|
+
|
|
14
|
+
// Check if it's a git repository
|
|
15
|
+
try {
|
|
16
|
+
execSync('git status', { cwd: CWD, stdio: 'ignore' });
|
|
17
|
+
} catch {
|
|
18
|
+
console.error('Error: Current directory is not a git repository.');
|
|
19
|
+
console.error('Please run hjWorktree from within a git repository.');
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Find the server entry point
|
|
24
|
+
let serverPath = path.join(__dirname, '../dist/server/index.js');
|
|
25
|
+
|
|
26
|
+
// In development, use tsx with the source file
|
|
27
|
+
if (!fs.existsSync(serverPath)) {
|
|
28
|
+
serverPath = path.join(__dirname, '../server/index.ts');
|
|
29
|
+
|
|
30
|
+
if (!fs.existsSync(serverPath)) {
|
|
31
|
+
console.error('Error: Server entry point not found.');
|
|
32
|
+
console.error('Please run "npm run build" first.');
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
console.log(`Starting hjWorktree CLI...`);
|
|
38
|
+
console.log(`Working directory: ${CWD}`);
|
|
39
|
+
console.log(`Server port: ${PORT}`);
|
|
40
|
+
|
|
41
|
+
// Start the server
|
|
42
|
+
const serverArgs = serverPath.endsWith('.ts')
|
|
43
|
+
? ['--import', 'tsx', serverPath]
|
|
44
|
+
: [serverPath];
|
|
45
|
+
|
|
46
|
+
const server = spawn('node', serverArgs, {
|
|
47
|
+
env: {
|
|
48
|
+
...process.env,
|
|
49
|
+
PORT: String(PORT),
|
|
50
|
+
CWD: CWD,
|
|
51
|
+
},
|
|
52
|
+
stdio: 'inherit',
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Open browser after a delay
|
|
56
|
+
setTimeout(async () => {
|
|
57
|
+
try {
|
|
58
|
+
const open = (await import('open')).default;
|
|
59
|
+
await open(`http://localhost:${PORT}`);
|
|
60
|
+
console.log(`\nBrowser opened at http://localhost:${PORT}`);
|
|
61
|
+
} catch (error) {
|
|
62
|
+
console.log(`\nOpen http://localhost:${PORT} in your browser.`);
|
|
63
|
+
}
|
|
64
|
+
}, 1500);
|
|
65
|
+
|
|
66
|
+
// Handle process signals
|
|
67
|
+
process.on('SIGINT', () => {
|
|
68
|
+
console.log('\nShutting down...');
|
|
69
|
+
server.kill('SIGINT');
|
|
70
|
+
process.exit(0);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
process.on('SIGTERM', () => {
|
|
74
|
+
server.kill('SIGTERM');
|
|
75
|
+
process.exit(0);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
server.on('error', (error) => {
|
|
79
|
+
console.error('Server error:', error);
|
|
80
|
+
process.exit(1);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
server.on('exit', (code) => {
|
|
84
|
+
process.exit(code || 0);
|
|
85
|
+
});
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Server } from 'socket.io';
|
|
2
|
+
declare const app: import("express-serve-static-core").Express;
|
|
3
|
+
declare const httpServer: import("http").Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse>;
|
|
4
|
+
declare const io: Server<import("socket.io").DefaultEventsMap, import("socket.io").DefaultEventsMap, import("socket.io").DefaultEventsMap, any>;
|
|
5
|
+
export { app, httpServer, io };
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../server/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAWnC,QAAA,MAAM,GAAG,6CAAY,CAAC;AACtB,QAAA,MAAM,UAAU,oGAAoB,CAAC;AACrC,QAAA,MAAM,EAAE,+HAKN,CAAC;AAsDH,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import { createServer } from 'http';
|
|
3
|
+
import { Server } from 'socket.io';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
6
|
+
import cors from 'cors';
|
|
7
|
+
import { setupSocketHandlers, killAllSessions } from './socketHandlers.js';
|
|
8
|
+
import { apiRouter } from './routes/api.js';
|
|
9
|
+
import { DEFAULT_PORT, APP_NAME, APP_VERSION } from '../shared/constants.js';
|
|
10
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
+
const __dirname = path.dirname(__filename);
|
|
12
|
+
const app = express();
|
|
13
|
+
const httpServer = createServer(app);
|
|
14
|
+
const io = new Server(httpServer, {
|
|
15
|
+
cors: {
|
|
16
|
+
origin: '*',
|
|
17
|
+
methods: ['GET', 'POST']
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
const PORT = parseInt(process.env.PORT || String(DEFAULT_PORT), 10);
|
|
21
|
+
const CWD = process.env.CWD || process.cwd();
|
|
22
|
+
// Middleware
|
|
23
|
+
app.use(cors());
|
|
24
|
+
app.use(express.json());
|
|
25
|
+
// Serve static files from the web build directory
|
|
26
|
+
const webDir = path.join(__dirname, '../web');
|
|
27
|
+
app.use(express.static(webDir));
|
|
28
|
+
// API routes
|
|
29
|
+
app.use('/api', apiRouter(CWD));
|
|
30
|
+
// Socket.IO handlers
|
|
31
|
+
setupSocketHandlers(io, CWD);
|
|
32
|
+
// Fallback to index.html for SPA routing
|
|
33
|
+
app.get('*', (req, res) => {
|
|
34
|
+
res.sendFile(path.join(webDir, 'index.html'));
|
|
35
|
+
});
|
|
36
|
+
// Graceful shutdown
|
|
37
|
+
process.on('SIGINT', () => {
|
|
38
|
+
console.log('\nShutting down...');
|
|
39
|
+
killAllSessions();
|
|
40
|
+
process.exit(0);
|
|
41
|
+
});
|
|
42
|
+
process.on('SIGTERM', () => {
|
|
43
|
+
console.log('\nShutting down...');
|
|
44
|
+
killAllSessions();
|
|
45
|
+
process.exit(0);
|
|
46
|
+
});
|
|
47
|
+
// Start server
|
|
48
|
+
httpServer.listen(PORT, () => {
|
|
49
|
+
console.log(`
|
|
50
|
+
╔════════════════════════════════════════════╗
|
|
51
|
+
║ ║
|
|
52
|
+
║ ${APP_NAME} v${APP_VERSION} ║
|
|
53
|
+
║ ║
|
|
54
|
+
║ Server running at: ║
|
|
55
|
+
║ http://localhost:${PORT} ║
|
|
56
|
+
║ ║
|
|
57
|
+
║ Working directory: ║
|
|
58
|
+
║ ${CWD.substring(0, 38)}${CWD.length > 38 ? '...' : ''}
|
|
59
|
+
║ ║
|
|
60
|
+
╚════════════════════════════════════════════╝
|
|
61
|
+
`);
|
|
62
|
+
});
|
|
63
|
+
export { app, httpServer, io };
|
|
64
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../server/routes/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAqB,MAAM,SAAS,CAAC;AAKpD,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAsG7C"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import { GitService } from '../services/gitService.js';
|
|
3
|
+
import { WorktreeService } from '../services/worktreeService.js';
|
|
4
|
+
export function apiRouter(cwd) {
|
|
5
|
+
const router = Router();
|
|
6
|
+
const gitService = new GitService(cwd);
|
|
7
|
+
const worktreeService = new WorktreeService(cwd);
|
|
8
|
+
// Get project info
|
|
9
|
+
router.get('/info', async (req, res) => {
|
|
10
|
+
try {
|
|
11
|
+
const isGitRepo = await gitService.isGitRepository();
|
|
12
|
+
const currentBranch = isGitRepo ? await gitService.getCurrentBranch() : null;
|
|
13
|
+
res.json({
|
|
14
|
+
cwd,
|
|
15
|
+
isGitRepository: isGitRepo,
|
|
16
|
+
currentBranch,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
res.status(500).json({
|
|
21
|
+
error: error instanceof Error ? error.message : 'Unknown error'
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
// Get branches
|
|
26
|
+
router.get('/branches', async (req, res) => {
|
|
27
|
+
try {
|
|
28
|
+
// Fetch latest from remote first
|
|
29
|
+
await gitService.fetch();
|
|
30
|
+
const branches = await gitService.getBranches();
|
|
31
|
+
res.json(branches);
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
res.status(500).json({
|
|
35
|
+
error: error instanceof Error ? error.message : 'Unknown error'
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
// Get worktrees
|
|
40
|
+
router.get('/worktrees', async (req, res) => {
|
|
41
|
+
try {
|
|
42
|
+
const worktrees = await worktreeService.listWorktrees();
|
|
43
|
+
res.json(worktrees);
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
res.status(500).json({
|
|
47
|
+
error: error instanceof Error ? error.message : 'Unknown error'
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
// Create worktrees
|
|
52
|
+
router.post('/worktrees', async (req, res) => {
|
|
53
|
+
try {
|
|
54
|
+
const { branch, count } = req.body;
|
|
55
|
+
if (!branch || !count || count < 1) {
|
|
56
|
+
res.status(400).json({ error: 'Invalid request: branch and count are required' });
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const worktrees = await worktreeService.createMultipleWorktrees(branch, count);
|
|
60
|
+
res.json({ worktrees });
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
res.status(500).json({
|
|
64
|
+
error: error instanceof Error ? error.message : 'Unknown error'
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
// Delete a worktree
|
|
69
|
+
router.delete('/worktrees/:name', async (req, res) => {
|
|
70
|
+
try {
|
|
71
|
+
const { name } = req.params;
|
|
72
|
+
const worktrees = await worktreeService.listWorktrees();
|
|
73
|
+
const worktree = worktrees.find(wt => wt.name === name);
|
|
74
|
+
if (!worktree) {
|
|
75
|
+
res.status(404).json({ error: 'Worktree not found' });
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
await worktreeService.removeWorktree(worktree.path);
|
|
79
|
+
res.json({ success: true });
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
res.status(500).json({
|
|
83
|
+
error: error instanceof Error ? error.message : 'Unknown error'
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
// Delete all worktrees
|
|
88
|
+
router.delete('/worktrees', async (req, res) => {
|
|
89
|
+
try {
|
|
90
|
+
await worktreeService.removeAllWorktrees();
|
|
91
|
+
res.json({ success: true });
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
res.status(500).json({
|
|
95
|
+
error: error instanceof Error ? error.message : 'Unknown error'
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
return router;
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../../server/routes/api.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Branch } from '../../shared/types/index.js';
|
|
2
|
+
export declare class GitService {
|
|
3
|
+
private git;
|
|
4
|
+
private cwd;
|
|
5
|
+
constructor(cwd?: string);
|
|
6
|
+
isGitRepository(): Promise<boolean>;
|
|
7
|
+
getBranches(): Promise<Branch[]>;
|
|
8
|
+
getCurrentBranch(): Promise<string>;
|
|
9
|
+
fetch(): Promise<void>;
|
|
10
|
+
getCwd(): string;
|
|
11
|
+
}
|
|
12
|
+
export declare function getGitService(cwd?: string): GitService;
|
|
13
|
+
//# sourceMappingURL=gitService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gitService.d.ts","sourceRoot":"","sources":["../../../server/services/gitService.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAG1D,qBAAa,UAAU;IACrB,OAAO,CAAC,GAAG,CAAY;IACvB,OAAO,CAAC,GAAG,CAAS;gBAER,GAAG,GAAE,MAAsB;IAKjC,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC;IASnC,WAAW,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IA0ChC,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC;IAKnC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ5B,MAAM,IAAI,MAAM;CAGjB;AAKD,wBAAgB,aAAa,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,UAAU,CAKtD"}
|