# HQ Terminal — Implementation Plan Reference spec: `.hq/2026-06-09-spec-hq-terminal.md` ## Phase 1: Project Scaffold Set up the new workspace with tooling, dependencies, and basic structure. ### Steps 1. **Create workspace** at `~/dev/hqt/` with `uv init --lib --name hqt` 2. **Configure pyproject.toml**: - Python ≥ 3.12 - Dependencies: `textual>=2.0`, `sqlalchemy>=2.0`, `click>=8.0` - Dev dependencies: `pytest`, `pytest-asyncio`, `ruff` - Entry point: `[project.scripts] hqt = "hqt.cli:main"` 3. **Create package structure** per spec: `src/hqt/` with all subdirectories 4. **Create `.hq/PROJECT.md`** for the new project 5. **Verify**: `uv run hqt --help` produces output ## Phase 2: Database Layer SQLite models, engine, and schema management. ### Steps 1. **`src/hqt/config.py`** — Settings dataclass with paths: - `db_path`: `~/.local/share/hqt/hqt.db` - `config_dir`: `~/.config/hqt/` - `skills_dir`: `~/.config/hqt/skills/` - `tmux_path`: `tmux` - `tui_session_name`: `hqt-main` 2. **`src/hqt/db/models.py`** — SQLAlchemy models: `Project`, `Harness`, `Session`, `McpServer`, `ProjectMcpServer`, `ProjectSkill` 3. **`src/hqt/db/session.py`** — Engine factory, session factory, `ensure_db()` (creates dir + tables) 4. **`src/hqt/db/migrate.py`** — Additive migration helper (add missing columns) 5. **Tests**: model creation, ensure_db on fresh + existing databases 6. **Verify**: `uv run pytest tests/test_db.py -q` passes ## Phase 3: TmuxRunner The async tmux command abstraction. Largely ported from HQ. ### Steps 1. **`src/hqt/tmux/runner.py`** — Port `TmuxRunner` from HQ: - `new_session(name, cwd, command, width, height)` - `has_session(name) -> bool` - `kill_session(name)` - `send_text(name, text)` - `send_enter(name)` - `capture_pane(name) -> str` - `switch_client(target)` ← NEW (not in HQ) - `list_sessions() -> list[str]` ← NEW 2. **`src/hqt/tmux/manager.py`** — Higher-level session lifecycle: - `spawn_session(session: Session, config: SpawnConfig) -> None` - `resume_session(session: Session, config: SpawnConfig) -> None` - `kill_session(session: Session) -> None` - `attach_session(session: Session) -> None` (switch-client) - `is_alive(session: Session) -> bool` - `poll_all_sessions(sessions: list[Session]) -> dict[int, bool]` 3. **Tests**: mock `_exec` function, verify command construction 4. **Verify**: `uv run pytest tests/test_tmux.py -q` passes ## Phase 4: Harness Abstraction Layer The configurator protocol and concrete implementations. ### Steps 1. **`src/hqt/harnesses/base.py`** — `HarnessConfigurator` protocol, `SpawnConfig`, `HarnessIdentity` dataclasses 2. **`src/hqt/harnesses/claude.py`** — Claude Code configurator: - UUID generation via `uuid5` - Spawn: `claude --session-id {uuid} --model {model}` - Resume: `claude --resume {uuid}` - MCP: write project `.mcp.json` - Skills: write/append `CLAUDE.md` - Ready/busy regexes from terminal profiles 3. **`src/hqt/harnesses/kiro.py`** — Kiro CLI configurator (stub for now): - Basic spawn command - MCP: Kiro-managed (no injection in v1) 4. **`src/hqt/harnesses/aider.py`** — Aider configurator: - Spawn: `aider --model {model} --restore-chat-history` - Skills: `--read {skill_file}` flags - No MCP support 5. **`src/hqt/harnesses/generic.py`** — Fallback for unknown harnesses: - Env-var based config only 6. **`src/hqt/harnesses/registry.py`** — Discover available harnesses (`shutil.which`), return configurator instances 7. **Tests**: each configurator produces correct SpawnConfig for given inputs 8. **Verify**: `uv run pytest tests/test_harnesses.py -q` passes ## Phase 5: Skills & MCP Services Skill registry and MCP server management. ### Steps 1. **`src/hqt/skills/registry.py`** — Port from HQ: scan `skills_dir`, parse frontmatter, return `Skill` objects 2. **`src/hqt/skills/injection.py`** — Port from HQ: `wrap_prompt_with_skills()` 3. **`src/hqt/mcp/service.py`** — CRUD for MCP servers and project bindings (DB operations) 4. **`src/hqt/projects/service.py`** — Project CRUD: add, list, archive, git status reading 5. **Tests**: skill discovery with fixture directory, MCP CRUD, project CRUD 6. **Verify**: `uv run pytest tests/test_skills.py tests/test_mcp.py tests/test_projects.py -q` passes ## Phase 6: Session Service (Orchestration Core) The service that ties together DB, tmux, and harness configurators. ### Steps 1. **`src/hqt/sessions/service.py`** — Session lifecycle: - `create_session(project_id, harness_name, nickname, model, skill_names, mcp_ids) -> Session` - Generates harness UUID via configurator - Builds SpawnConfig - Calls tmux manager to spawn - Persists session row - `resume_session(session_id) -> None` - Loads session from DB - Builds resume SpawnConfig with stored UUID - Calls tmux manager to spawn - `stop_session(session_id) -> None` - Kills tmux session - Updates DB (last_activity_at) - `delete_session(session_id) -> None` - Kills tmux if alive - Removes DB row - `attach_session(session_id) -> None` - Calls tmux switch-client - `list_sessions(project_id) -> list[SessionInfo]` - Joins DB data with tmux liveness 2. **Tests**: mock tmux manager, verify session lifecycle 3. **Verify**: `uv run pytest tests/test_sessions.py -q` passes ## Phase 7: Textual TUI The user interface. ### Steps 1. **`src/hqt/tui/app.py`** — Textual `App` subclass: - Bindings: q=quit, n=new session, a=add project, /=filter - Compose: Header, ProjectList, SessionList, Footer - Timer: poll tmux liveness every 3s 2. **`src/hqt/tui/widgets/project_list.py`** — ListView of projects: - Shows name, path, branch - Selection updates session list - Keybindings: Enter=select, a=add, d=archive 3. **`src/hqt/tui/widgets/session_list.py`** — ListView of sessions for selected project: - Shows harness icon, nickname, alive/dead status - Keybindings: Enter=attach, n=new, d=delete, r=rename, R=resume (if dead) 4. **`src/hqt/tui/screens/new_session.py`** — Modal screen: - Harness selector (dropdown) - Nickname input - Model selector (populated from configurator.supported_models) - Skills multi-select - MCP servers multi-select - Create / Cancel buttons 5. **`src/hqt/tui/screens/add_project.py`** — Modal: - Path input (with directory completion if feasible, or paste) - Name override (optional) 6. **`src/hqt/tui/styles.tcss`** — Textual CSS for layout 7. **Integration test**: App mounts, projects display, key bindings respond 8. **Verify**: `uv run pytest tests/test_tui.py -q` passes (headless Textual testing) ## Phase 8: CLI Entry Point & tmux Bootstrap Wire everything together. ### Steps 1. **`src/hqt/cli.py`** — Click CLI: - `hqt` (default) — bootstrap into tmux + launch TUI - `hqt list` — print projects/sessions table - `hqt attach ` — switch to session - `hqt new ` — create session non-interactively - `hqt doctor` — check tmux, harness availability 2. **`src/hqt/__main__.py`** — `python -m hqt` support 3. **tmux bootstrap logic**: ```python def bootstrap(): if not in_tmux(): # Create hqt-main session with TUI as the command exec tmux new-session -s hqt-main "hqt --inside-tmux" else: # Already in tmux, just run the TUI run_tui() ``` 4. **First-run setup**: suggest tmux keybinding, create config dir/skills dir 5. **Verify**: `hqt doctor` works, `hqt` launches TUI inside tmux ## Phase 9: Integration Testing & Polish ### Steps 1. **End-to-end test**: create project → create session → verify tmux session exists → attach → kill → verify dead 2. **Handle edge cases**: - tmux not installed → clear error - Harness not found → show in UI, disable create - DB locked → retry pattern - Session name collision → fail gracefully 3. **README.md** with quick start 4. **Verify**: full test suite passes, manual smoke test with claude-code ## Dependency Graph ``` Phase 1 (scaffold) │ ├── Phase 2 (database) │ │ │ ├── Phase 5 (skills + MCP) │ │ │ │ │ └──────┐ │ │ │ │ └── Phase 6 (session service) ◄── Phase 4 (harness abstraction) │ │ ├── Phase 3 (tmux runner) ──────────────┘ │ │ │ ▼ └── Phase 7 (TUI) ◄──────────── Phase 6 │ ▼ Phase 8 (CLI + bootstrap) │ ▼ Phase 9 (integration + polish) ``` ## Estimated Effort | Phase | Complexity | Approx. LOC | |-------|-----------|-------------| | 1. Scaffold | Low | ~50 (config) | | 2. Database | Low | ~150 | | 3. TmuxRunner | Low | ~120 (mostly port) | | 4. Harness abstraction | Medium | ~300 | | 5. Skills + MCP | Low | ~150 (mostly port) | | 6. Session service | Medium | ~200 | | 7. TUI | Medium-High | ~400 | | 8. CLI + bootstrap | Low | ~100 | | 9. Integration | Medium | ~150 | | **Total** | | **~1,620** | ## Implementation Order (sequential for a single agent) 1. Phase 1 → 2. Phase 2 → 3. Phase 3 → 4. Phase 4 → 5. Phase 5 → 6. Phase 6 → 7. Phase 7 → 8. Phase 8 → 9. Phase 9 Each phase produces a working, testable increment. The TUI (Phase 7) is the largest single piece but depends on everything below it being solid.