An open API service indexing awesome lists of open source software.

https://github.com/dong-park/pharos

xterm.js + Tauri로 만든 macOS 터미널 멀티플렉서. Claude Code · Codex 같은 AI 에이전트 세션을 한 창에서 오갑니다.
https://github.com/dong-park/pharos

ai-agent claude-code multiplexer tauri terminal xterm

Last synced: about 18 hours ago
JSON representation

xterm.js + Tauri로 만든 macOS 터미널 멀티플렉서. Claude Code · Codex 같은 AI 에이전트 세션을 한 창에서 오갑니다.

Awesome Lists containing this project

README

          

# Pharos

> **Harbor master for your async agents** — a quiet lighthouse over your terminals, sweeping every session, signaling when one needs you.

Tauri 기반 터미널 멀티플렉서. macOS 네이티브 앱으로 동작하며 **Claude Code / Codex / ssh·tmux** 세션을 하나의 창에서 오가며 쓰도록 설계됨. 터미널 위에 얹히는 조용한 보조 레이어 — Zed·Warp 같은 톤.

## 핵심 개념

```
┌───── TitleBar ─────────────────────────────────────────────┐
│ 워크스페이스 이름 ⎇ branch │
├──────────┬─────────────────────────────────────────────────┤
│ ● ws1 C │ │
│ ● ws2 X │ 터미널 (xterm.js, 분할/탭) │
│ ● ws3 $ │ │
│ ● ws4 ⇢ │ │
│ ├─────────────────────────────────────────────────┤
│ [⌘/ ] │ [C] Claude · ctx 48% · 🔨 BUILD ━━━░ 45% ⌘/ │
└──────────┴─────────────────────────────────────────────────┘
```

- **사이드바**: 워크스페이스 리스트. 각 행에 상태 dot (running/waiting/idle/done), 소스 칩 (C/X/$/⇢/▦), phase, 대기 시간, hairline progress 바.
- **StatusBar**: source · ctx % · dev-flow phase + progress · 응답 대기 카운트.
- **Activity 탭** (⌘Shift+A): 자동 감지 + CLI push 모든 이벤트의 타임라인. 마크다운 복사, kind/text 필터, 이 워크스페이스/전체 토글.

## 자동 감지 (detector)

백그라운드 감지 모듈이 터미널 출력을 감시해 상태를 자동 갱신:

- **State** (1s 주기): 활동 있으면 `running`, 없으면 `idle`. 터미널 tail에 `(y/n)` / `Do you want to proceed?` / Claude 승인 메뉴 보이면 `waiting`.
- **Source** (1s 주기): Claude `⏺ Tool(...)` 시그니처 · Codex 배너 · tmux 마커 · shell 프롬프트 downgrade.

수동 CLI 푸시는 언제든 가능하고 `done` 상태만 detector가 건드리지 않음.

## CLI 자동화 primitives

`pharos` 바이너리로 외부 스크립트/에이전트에서 제어 가능.

```bash
# fleet 요약 — 지금 뭐 돌고 뭐 기다리는지
pharos identify
# { byState: { running:1, waiting:2, idle:3 },
# bySource: { claude:3, shell:2, ssh:1 }, ... }

# 타임라인 — 지난 30분 동안 전 워크스페이스 이벤트
pharos list-events --since 30m --all --limit 50

# 블로킹 대기 — Claude가 작업 마칠 때까지
WS=$(pharos wait --not-state running --timeout 300)
echo "finished: $WS"

# 특정 워크스페이스 승인 프롬프트 대기
pharos wait --state waiting --workspace $WS --timeout 60

# 섹션별 help (50+ 명령)
pharos help state # Atlas 상태 명령만
pharos help timeline # 이벤트 로그
pharos help wait # blocking 사용법
```

전체 명령은 `pharos` 또는 `pharos help `. 섹션: window / workspace / panes / terminal / status / state / timeline / history / memo / notify / theme / log / system / wait.

주요 CLI 카테고리:
- **Status**: `set-status` · `set-progress` · `report-pr` · `report-review` · `report-meta-block`
- **Atlas state**: `report-source` · `set-state` · `report-ctx` / `clear-ctx`
- **Timeline**: `list-events [--kind --since --all --limit]` · `clear-events`
- **History (dev-flow)**: `history add` · `history list` · `history clear`
- **Blocking**: `wait [--state --source --phase --not-* --progress-min --workspace --timeout]`
- **Trust**: `trust-directory` · `untrust-directory` · `check-trust` · `list-trusted`

### 오케스트레이션 예제

dev-flow 여러 세션을 가로질러 동기화:

```bash
# 이 Pharos가 내가 필요한 feature를 지원하는지 확인
pharos version | jq -e '.features | contains(["wait-phase","identify-distributions"])' \
|| { echo "Pharos 구버전 — 업그레이드 필요"; exit 1; }

# fleet 스냅샷 한 눈에
pharos identify | jq '{running: .byState.running, waiting: .byState.waiting, byPhase}'

# 특정 워크스페이스 BUILD → REVIEW 전환까지 블록 (10분 timeout)
WS=$(pharos wait --phase REVIEW --workspace my-feature --timeout 600) \
&& echo "review ready: $WS"

# 다른 워크스페이스에서 Claude가 승인 프롬프트 띄우면 자동으로 yes
while WS=$(pharos wait --state waiting --timeout 3600); do
pharos send --workspace "$WS" -e "yes"
done

# 빌드 75% 넘을 때 배포 준비 시작
pharos wait --phase BUILD --progress-min 0.75 --workspace main --timeout 1200
./prepare-deploy.sh
```

## dev-flow 통합

`/dev-flow` 스킬이 `pharos set-status phase` / `set-progress` / `workspace-memo-append`을 호출하면 사이드바·StatusBar·Activity 탭에 실시간 반영. Spec→Plan→Build→Test→Review→Ship 파이프라인의 각 단계가 시각화됨.

## Blueprint pane — 앱 전체 기획 산출물

솔로 개발자가 **앱 한 개의 기획**(요구사항·기능명세·유저플로우)을 `.blueprint.json` 한 파일로 정리하고, 각 `feature`의 구현을 `/dev`로 zoom-in하는 워크플로. AI 생성·SaaS 협업·외부 공유는 영속적 비목표 — local-first, git-friendly, 사람이 직접 쓰는 구조화된 기획.

`feature[].id`가 `/dev` 호출 단위와 1:1 매핑되도록 설계.

### CLI (offline, daemon 미경유)

```bash
# 빈 골격 생성 (mobile-booking 템플릿)
pharos blueprint init feature-x.blueprint.json --template mobile-booking

# 구조 + cross-reference 검증 (dangling ref · 중복 ID 등)
pharos blueprint validate feature-x.blueprint.json
# 미사용 ID / 고립 screen 같은 lint warning도 error로 승격하려면:
pharos --strict blueprint validate feature-x.blueprint.json

# 마크다운으로 뽑기 (PR description · README 등에 붙여넣기)
pharos blueprint export feature-x.blueprint.json --format md
```

### Pane 안에서 보기

```bash
pharos new-pane --type blueprint \
--file "$PWD/feature-x.blueprint.json" \
--view requirements # requirements | spec | flow
```

좌측 사이드바에 3개 뷰 탭(요구사항 / 기능명세서 / 유저플로우). 각 카드에 다른 항목으로 점프하는 추적성 chip — 예: requirement 카드의 `FEAT-x` chip을 클릭하면 기능명세서 뷰로 이동 + 그 feature 카드 하이라이트.

외부 에디터로 파일을 수정하면 1초 이내 자동 갱신 (mtime polling, 심볼릭 링크는 안전을 위해 거부).

> **경로 제약**: pane이 여는 `.blueprint.json`은 `$HOME` 아래에 있어야 합니다. Tauri webview의 fs scope가 `$HOME/**`로 제한되어 있어 `/tmp` 같은 home 밖 경로는 missing-file 상태로 떨어집니다. CLI(`pharos blueprint init/validate/export`)는 daemon 미경유라 어디서든 동작합니다.

### 최소 JSON 형식

```jsonc
{
"schemaVersion": 2,
"name": "기능 이름",
"requirements": [
{ "id": "REQ-1", "title": "...", "description": "...", "priority": "high", "status": "todo", "progress": 0 }
],
"features": [
{ "id": "FEAT-x", "title": "...", "requirementIds": ["REQ-1"], "parentId": null }
],
"flows": [{
"id": "FLOW-main", "title": "...", "featureIds": ["FEAT-x"],
"steps": [
{ "id": "S1", "description": "...", "screenId": "SCR-home", "featureIds": ["FEAT-x"], "lane": "Search" }
]
}],
"screens": [
{ "id": "SCR-home", "name": "홈", "role": "search-entry", "featureIds": ["FEAT-x"] }
]
}
```

`requirements[]`의 `priority`(`high|med|low`) / `status`(`todo|in-progress|done`) / `progress`(0-100), `features[]`의 `parentId`(트리), `flows[].steps[].lane`(swim-lane 그룹화)은 모두 optional. `schemaVersion: 1` 파일은 더 이상 지원하지 않으며, pane은 `schemaUnsupported` 안내를 표시합니다.

`requirementIds` / `featureIds` / `screenId`는 다른 항목의 `id`를 가리키는 참조 — `validate`가 dangling을 잡습니다.

### 권위 파일

| 용도 | 경로 |
|------|------|
| TS 타입 (가장 권위 있는 모델) | `src/blueprint/types.ts` |
| 실제 예시 파일 | `examples/booking.blueprint.json` |
| JSON Schema 문서 (외부 IDE hint, 런타임 미사용) | `schemas/pharos.blueprint.v2.schema.json` |
| 검증 규칙 구현 | `cli/src/blueprint.rs` `check_blueprint` |

### 비목표

AI 생성 · SaaS 협업/공유 링크 · 비주얼 wireframe view (MVP 제외, 후행) · HTML/PNG export · Figma 식 자유 드래그.

## Android 디버그 패널

`Cmd+Alt+A` — 포커스된 pane 옆에 Android 패널 분할. `adb`(Android SDK platform-tools)가 PATH 또는 `~/Library/Android/sdk/platform-tools`에 있으면 자동 탐지.

디바이스 행 액션:
- **Mirror** — `adb screencap` PNG 폴링 (~4 fps), tap/swipe/text/Back/Home/Recents, 프레임 PNG 저장
- **Embed** — scrcpy 서버로 H.264 스트림을 패널 안에 디코드 (60 fps, WebCodecs). 툴바 `↓ embed-jar` 한 번 눌러서 jar 자동 다운로드
- **scrcpy** — 시스템 `scrcpy` 바이너리를 외부 윈도우로 띄움 (의존성 있을 때)
- **Logs** — 200~5000 라인 스냅샷 + 라이브 테일, 텍스트/우선순위(V/D/I/W/E/F) 필터, 라인 클릭 → 클립보드
- **Apps** — 패키지 검색 + Launch/Stop, "Install APK"로 로컬 .apk 설치
- **Files** — `/sdcard` 트리 탐색 (breadcrumb), Pull/Push, .apk 파일 행에서 디바이스 직접 설치
- **Shell** — `adb shell` 원샷 러너, 히스토리(↑/↓)와 프리셋 (dumpsys/getprop/ps 등)

scrcpy 임베드 사용은 `src-tauri/resources/SCRCPY_SERVER.md` 참조 — 패널 툴바의 `↓ embed-jar` 버튼이 같은 작업을 자동화.

### AVD 부팅 · 성능

디바이스가 하나도 연결돼 있지 않으면 패널이 정의된 AVD 목록을 띄우고, 행 클릭으로 원클릭 부팅(`android_launch_avd`). pharos는 `-gpu`를 넘기지 **않으므로**, 그래픽 가속 모드는 전적으로 AVD `config.ini`의 `hw.gpu.mode`가 결정한다.

> ⚠️ **에뮬레이터가 느리면 GPU부터 의심.** Apple Silicon에서 `hw.gpu.mode = auto`가 host(Metal)를 못 잡고 SwiftShader(소프트웨어 렌더링)로 떨어지면 극심하게 느려진다. `~/.android/avd/.avd/config.ini`에서 `hw.gpu.mode = host`로 못박고(+ `hw.ramSize` 4096 이상), 콜드부트(`-no-snapshot-load`)하면 해결. 부팅 로그의 `gles_mode_selected:host` / `GLES: ... Apple M.. Metal`로 적용을 확인할 수 있다. 한 번 software로 뜬 인스턴스는 끄기 전까지 계속 software이므로, 설정만 바꾸지 말고 반드시 재부팅한다.

## 개발

```bash
yarn install
yarn tauri dev # Tauri 앱 개발 모드
yarn test # TS 유닛 테스트 (vitest)
yarn check # cargo check + tsc --noEmit + vitest

# CLI 빌드 (cli/ crate, workspace member)
cargo build -p pharos-cli --release
# → target/release/pharos (워크스페이스 공통 target, cli/target 아님)
```

### 프로젝트 구조

```
src/
App.tsx detector 부트스트랩, 이벤트 구독
components/
Sidebar.tsx 워크스페이스 리스트 + 인라인 검색 + 컨텍스트 메뉴
TitleBar / StatusBar / MemoPanel(+Activity 탭)
Terminal / SplitView xterm.js 래퍼 + 분할 관리
store/
workspace / pane / status / events / activityView / ...
stateDetector / sourceDetector 폴링 루프
socketHandler.ts CLI ↔ 앱 명령 라우팅
transcriptSearch.ts xterm 버퍼 크로스 워크스페이스 grep

cli/src/main.rs pharos CLI 바이너리 (tokio + Unix socket)
src-tauri/src/ Rust: PTY 스폰, SSH, 소켓 서버
```

### Claude Code SKILLs

본 repo는 글로벌 `~/.claude/{skills,commands}` 로 어떤 파일도 install하지
않는다. pharos에서 codex/claude 시블링 pane으로 작업을 위임하는
`dispatch-pane` SKILL을 포함해 모든 글로벌 SKILL은 별도
[`claude-config`](https://github.com/dong-park/claude-config) repo가 단일
진실원으로 관리한다.

과거에 `scripts/install-claude.sh` 로 글로벌 `~/.claude/` 에 symlink을 만든
사용자는 한 번 정리:

```bash
rm -f ~/.claude/skills/{dev,pharos,dispatch-pane} \
~/.claude/commands/{dev,pharos}.md
```

이후 글로벌 SKILL은 `claude-config` repo의 `install.sh` 로만 가져온다.

### 하네스 동기화 (앱 관리)

최초 설치(`install.sh`) 이후로는 **GUI 앱이 하네스를 직접 동기화**한다. 실행할 때마다
`~/.claude`의 CLAUDE.md 블록·skills/hooks/commands 심링크를 repo 소스와 대조해
버전이 바뀌었으면 자동 재적용한다(마커 안만 건드리고 사용자 콘텐츠는 보존).
**Settings → Harness**에서 컴포넌트(guidelines/pharos/fable/skills/hooks/commands)를
개별로 켜고 끌 수 있다. 하네스 업데이트를 받으려고 `install.sh`를 다시 돌릴 필요 없이
앱만 재시작하면 된다.

## 디자인 레퍼런스

Atlas 핸드오프 (`pharos/project/Pharos Terminal Redesign.html`) 기반. 구현 세부는 [`TODO.md`](./TODO.md)의 "Atlas 디자인 구현 요약" 참조.

## 라이선스

내부 프로젝트. 별도 라이선스 파일 없음.