# Hostkeeper V2 — Progress Tracker > **Purpose**: Enable seamless continuation of development by any agent/LLM across sessions. > **How to use**: Read this file first. Find the first unchecked `[ ]` item. That's where you continue. > **Last Updated**: 2026-06-29 > **Status**: Planning complete, implementation not started. --- ## 1. Overview Hostkeeper V2 is a Termius-like cross-platform SSH/SFTP management GUI application. | Item | Value | |------|-------| | **Goal** | Build a free, open-source Termius alternative with full feature parity | | **Desktop** | GoFiber backend + React/xterm.js UI + Electron wrapper | | **Mobile** | Go mobile library + WebView wrapper (Android/iOS) | | **Backend language** | Go 1.26 | | **HTTP framework** | GoFiber v2 (fasthttp-based) | | **Frontend** | React 19, TypeScript, xterm.js, Zustand, Vite | | **Desktop wrapper** | Electron (electron-builder) | | **Mobile wrapper** | gomobile + WebView | | **V1 (existing)** | CLI/TUI SSH/SFTP manager — 105 tests, all passing. Frozen. | --- ## 2. Current Status Summary | Item | Status | |------|--------| | Planning documents | DONE | | Sprint 0 — Scaffolding | NOT STARTED | | Sprint 1 — Foundation | NOT STARTED | | Sprint 2 — Core Features | NOT STARTED | | Sprint 3 — SFTP + Polish | NOT STARTED | | Sprint 4 — Advanced | NOT STARTED | | Sprint 5 — Platform Polish | NOT STARTED | --- ## 3. Sprint Checklist ### Sprint 0 — Project Scaffolding (Day 0) - [ ] Create `app/backend/` directory with Go module (`go mod init`) - [ ] Install GoFiber v2 + dependencies in `go.mod` - [ ] Create `app/backend/main.go` — minimal fiber server (port 0 for random) - [ ] Create `app/frontend/` with Vite + React + TypeScript - [ ] Create `app/electron/` with Electron shell - [ ] Electron spawns Go backend as child process on startup - [ ] Electron loads web UI from localhost (Go serve frontend dist) - [ ] Create `app/backend/middleware/` — CORS, logging, recover, compress - [ ] Create `app/backend/bridge/` directory (placeholder handlers) - [ ] Create `app/backend/ws/` directory (placeholder handlers) - [ ] Build script: `scripts/build.sh` — Go build → frontend build → Electron package - [ ] Verify: `npm run dev` opens Electron window with "Hostkeeper V2" title - [ ] Verify: Go server responds at `localhost:PORT/api/health` ### Sprint 1 — Foundation (Day 1-5) #### Day 1-2: Data API Layer - [ ] `app/backend/bridge/hosts.go` — GET /api/hosts (list, filter, search) - [ ] `app/backend/bridge/hosts.go` — POST /api/hosts (create) - [ ] `app/backend/bridge/hosts.go` — GET /api/hosts/:id (detail) - [ ] `app/backend/bridge/hosts.go` — PUT /api/hosts/:id (update) - [ ] `app/backend/bridge/hosts.go` — DELETE /api/hosts/:id (delete) - [ ] `app/backend/bridge/hosts.go` — PATCH /api/hosts/:id/favorite (toggle) - [ ] `app/backend/bridge/keys.go` — GET /api/keys (list, no private key) - [ ] `app/backend/bridge/keys.go` — POST /api/keys (import) - [ ] `app/backend/bridge/keys.go` — POST /api/keys/generate (generate new) - [ ] `app/backend/bridge/keys.go` — DELETE /api/keys/:id (delete) - [ ] `app/backend/bridge/snippets.go` — GET /api/snippets (list) - [ ] `app/backend/bridge/snippets.go` — POST /api/snippets (create) - [ ] `app/backend/bridge/snippets.go` — PUT /api/snippets/:id (update) - [ ] `app/backend/bridge/snippets.go` — DELETE /api/snippets/:id (delete) - [ ] JSON error responses: `{ "error": "message" }` with proper HTTP codes - [ ] Verify: `curl -X POST http://localhost:PORT/api/hosts` returns 201 #### Day 3: Groups + Config API - [ ] `app/backend/bridge/groups.go` — GET /api/groups (tree structure) - [ ] `app/backend/bridge/groups.go` — POST /api/groups (create) - [ ] `app/backend/bridge/groups.go` — PUT /api/groups/:id (update) - [ ] `app/backend/bridge/groups.go` — DELETE /api/groups/:id (delete) - [ ] `app/backend/bridge/groups.go` — PUT /api/groups/:id/move (reparent) - [ ] `app/backend/bridge/config.go` — GET /api/config (app config) - [ ] `app/backend/bridge/config.go` — PUT /api/config (update config) - [ ] `app/backend/bridge/config.go` — POST /api/config/unlock (vault unlock) - [ ] `app/backend/bridge/config.go` — POST /api/config/lock (vault lock) - [ ] `app/backend/bridge/config.go` — GET /api/config/status (vault status) - [ ] Verify: Full CRUD cycle via curl for all endpoints #### Day 4: Web UI Scaffold - [ ] React Router setup — routes for all screens (placeholder) - [ ] Layout component — Sidebar + TabBar + MainContent + StatusBar - [ ] Sidebar component — GroupTree (recursive), SearchBar, QuickActions - [ ] Theme system — CSS variables (dark, light, high-contrast) - [ ] API client layer — fetch wrapper + error handling + retry logic - [ ] State management — Zustand stores (hosts, keys, snippets, ui, terminal) - [ ] Keyboard shortcuts — Cmd+N new host, Cmd+K search, Cmd+D dark mode - [ ] Verify: Navigation between screens works #### Day 5: Host List Screen - [ ] HostList screen — HostCard components (grid + list view toggle) - [ ] GroupTree — collapsible, recursive, drag-and-drop (host -> group) - [ ] Search — filter by name, hostname, tag - [ ] Tag filter bar — chips for each tag, click to filter - [ ] Favorite toggle — star icon, filter favorites only - [ ] Context menu — right-click: connect, edit, delete, duplicate - [ ] Empty state — illustration + "Add your first host" CTA - [ ] Loading skeleton states - [ ] Verify: Host appears in list, can search, can filter, can favorite ### Sprint 2 — Core Features (Day 6-10) #### Day 6-7: Host Form + CRUD UI - [ ] HostForm screen — add mode + edit mode - [ ] Basic info fields — name, hostname, port, username - [ ] Auth section — type selector (password/key/agent) - [ ] Password field — show/hide toggle, strength indicator - [ ] Key picker — dropdown from stored keys - [ ] TagsInput — type + Enter to add, backspace to remove, autocomplete - [ ] GroupPicker — tree picker component - [ ] Advanced settings — proxy, jump host, keepalive interval - [ ] Validation — required fields, hostname regex, port range 1-65535 - [ ] Error display — inline validation + toast notifications - [ ] Keyboard shortcuts — Cmd+S save, Esc cancel, Tab next field - [ ] Verify: Create host -> appears in list -> edit -> update -> delete #### Day 8-10: SSH Terminal (MOST CRITICAL) - [ ] **Go: WebSocket handler** `app/backend/ws/terminal.go` - [ ] Accept WS connection with host_id + cols + rows query params - [ ] Lookup host from storage by ID - [ ] Create `ssh.Client` using `pkg/ssh` (reuse existing) - [ ] Request PTY with xterm-256color - [ ] Stream SSH stdout -> WS binary frames (`c.WriteMessage`) - [ ] Receive WS frames -> SSH stdin (`session.Stdin.Write`) - [ ] Handle resize messages — JSON control frames - [ ] Handle disconnect gracefully - [ ] Buffer management (channel-based backpressure) - [ ] Configurable idle timeout (default 300s) - [ ] Connection pool (reuse SSH connections for same host) - [ ] **React: XTermWrapper component** - [ ] xterm.js instance initialization with addons (fit, web-links, search) - [ ] WebSocket connection management - [ ] Keyboard input -> WS send (binary frames) - [ ] ResizeObserver -> WS send resize message - [ ] Fit addon — auto fit to container - [ ] Web links addon — clickable URLs - [ ] Search addon — Ctrl+F search in terminal - [ ] Copy/paste — Cmd+C/V, right-click menu - [ ] Connection status indicator (connecting, connected, disconnected, error) - [ ] Reconnect button on disconnect - [ ] **React: TabBar + Tab management** - [ ] Add tab -> connect to host - [ ] Close tab -> disconnect SSH session - [ ] Reorder tabs via drag - [ ] Tab status dot (green=connected, red=error, gray=disconnected) - [ ] Tab title = host name - [ ] Max 20 tabs limit with warning - [ ] **Snippet panel** (slide-in from right) - [ ] List snippets for current host - [ ] Click snippet -> inject command to terminal - [ ] Edit/delete from panel - [ ] Verify: Connect to host -> terminal works -> type commands -> disconnect -> reconnect ### Sprint 3 — SFTP + Polish (Day 11-15) #### Day 11-12: SFTP Browser - [ ] **Go: SFTP REST handlers** `app/backend/bridge/sftp.go` - [ ] GET /api/sftp/ls — list directory (host_id, path) - [ ] POST /api/sftp/upload — multipart upload with progress - [ ] GET /api/sftp/download — file download stream - [ ] POST /api/sftp/mkdir — create directory - [ ] POST /api/sftp/rm — delete file/directory - [ ] POST /api/sftp/rename — rename/move - [ ] POST /api/sftp/chmod — change permissions - [ ] **React: SFTPScreen** - [ ] LocalPane + RemotePane (dual pane split view) - [ ] File list table — name, size, date, permissions (sortable) - [ ] Navigation — cd, back, forward, path breadcrumb - [ ] Upload/download with progress bars - [ ] Transfer queue — multiple files, cancel, retry - [ ] Drag & drop from desktop to upload - [ ] Context menu — download, delete, rename, chmod, mkdir - [ ] Keyboard shortcuts — Delete, F2 rename, Ctrl+C/V copy/move - [ ] Verify: Browse remote files -> upload -> download -> delete -> rename #### Day 13: Security + Vault - [ ] Vault unlock screen — password prompt on app start - [ ] Lock/unlock flow — auto-lock after inactivity (configurable: 1/5/15/30 min) - [ ] Password change screen - [ ] Known hosts dialog — first connect show fingerprint -> accept/reject - [ ] Key passphrase prompt — when using encrypted private key - [ ] Verify: Start app -> vault locked -> enter password -> unlock -> auto-lock #### Day 14: Settings Screen - [ ] Appearance tab — theme switcher, font selection, font size, background opacity - [ ] Terminal tab — scrollback (100-10000), cursor style, cursor blink, bell, copy-on-select - [ ] Connection tab — default timeout, keepalive interval, auto-reconnect - [ ] Vault tab — change password, auto-lock timer, lock on sleep - [ ] General tab — data directory, export/import buttons, about/version - [ ] Verify: Change settings -> restart -> settings persist #### Day 15: Mobile Setup - [ ] React Native project with WebView - [ ] Go mobile compilation script (gomobile bind) - [ ] Android minimal app — WebView + gomobile .aar - [ ] iOS minimal app — WKWebView + gomobile .xcframework - [ ] Responsive CSS for mobile (touch-friendly targets) - [ ] Verify: App runs on Android emulator ### Sprint 4 — Advanced Features (Day 16-20) #### Day 16-17: Port Forwarding - [ ] Model PortForward in Go + storage - [ ] Go: Local forwarding — ssh.Listen -> local listener -> tunnel - [ ] Go: Remote forwarding — ssh.Request remote forward - [ ] Go: Dynamic forwarding — SOCKS5 proxy via SSH - [ ] Status tracking — running/stopped/error - [ ] React: PortForwardScreen — list, add form, start/stop toggles - [ ] Verify: Set local forward -> `curl localhost:PORT` -> hits remote #### Day 18: Import/Export - [ ] Go: Import from `~/.ssh/config` — parse host, hostname, port, user, identity - [ ] Go: Import from CSV — columns: name, hostname, port, username, group, tags - [ ] Go: Export all data — encrypted JSON with all entities - [ ] React: Import/Export UI — drag & drop, progress, preview, confirm - [ ] Verify: Export -> delete all -> import -> all data restored #### Day 19-20: Jump Hosts + Proxy - [ ] Go: Jump host chain — SSH via intermediate hosts - [ ] Go: Multi-hop support — host -> jump1 -> jump2 -> target - [ ] Go: SOCKS5 proxy before SSH - [ ] Go: HTTP CONNECT proxy - [ ] React: Advanced connection settings — jump host selector, proxy config - [ ] Verify: Connect via jump host -> terminal works ### Sprint 5 — Platform Polish (Day 21-25) #### Day 21-22: Desktop Enhancements - [ ] Electron native menu bar — File, Edit, View, Window, Help - [ ] System tray icon — quick actions, recent hosts - [ ] Global keyboard shortcuts — Cmd+` toggle, Cmd+N new host - [ ] Window state persistence — position, size, maximized - [ ] Auto-update via electron-updater - [ ] OS Keychain integration — macOS Keychain, Windows Credential Manager, Linux Secret Service - [ ] Verify: Install .dmg -> app appears -> open -> works #### Day 23: Performance Optimization - [ ] Go: Connection pooling for SSH sessions - [ ] Go: Memory optimization — buffer pools, goroutine limits - [ ] WebSocket: permessage-deflate compression - [ ] React: Virtual scrolling for host list (1000+ hosts) - [ ] React: Lazy loading screens (code splitting) - [ ] React: Memoization (React.memo, useMemo, useCallback) - [ ] xterm.js: WebGL renderer (preferred) with Canvas fallback - [ ] Verify: 1000 hosts in list -> smooth scrolling -> no lag #### Day 24-25: Mobile Polish - [ ] Android: gomobile bind -> .aar - [ ] Android: WebView app with touch-optimized UI - [ ] iOS: gomobile bind -> .xcframework - [ ] iOS: WKWebView app - [ ] Mobile: Custom keyboard toolbar (Tab, Ctrl, Esc, arrows) - [ ] Mobile: Gesture navigation (swipe to switch tabs) - [ ] Mobile: Landscape/portrait handling - [ ] Mobile: Bluetooth keyboard support - [ ] Mobile: Background connection handling - [ ] Verify: Install APK on Android -> connect SSH -> terminal works --- ## 4. Known Issues | # | Issue | Severity | Status | |---|-------|----------|--------| | (none) | — | — | — | --- ## 5. Last Session Notes | Date | What was done | Commits | |------|---------------|---------| | 2026-06-29 | V2 planning documents created (9 files) | — | --- ## 6. How to Continue ### For a new AI agent: 1. **Read this file** (`docs/v2/PROGRESS.md`) — find the first `[ ]` item 2. **Read the relevant spec doc** — for the current task: - REST API endpoints -> `docs/v2/API.md` - UI components -> `docs/v2/UI_COMPONENTS.md` - Data models -> `docs/v2/DATA_MODELS.md` - Visual reference -> `docs/v2/UI_TERMIUS_REFERENCE.md` - Performance notes -> `docs/v2/PERFORMANCE.md` - Build pipeline -> `docs/v2/BUILD_SYSTEM.md` 3. **Read `docs/v2/ARCHITECTURE.md`** — understand the system 4. **Implement** in `app/backend/` (Go) or `app/frontend/` (React) 5. **Test** — run `go test ./app/backend/...` and `npm test` in `app/frontend/` 6. **Update this file** — mark `[x]` the completed task, update "Last Session Notes" ### For a returning AI agent: 1. **Read this file** — check "Last Session Notes" for context 2. **Check git log** — `git log --oneline -10` for recent commits 3. **Find the first `[ ]`** — that's where you continue 4. **Update this file** when done --- ## 7. Reference Documents Index | Document | When to read | |----------|-------------| | `docs/v2/PROGRESS.md` | Always (first) — know where to continue | | `docs/v2/ARCHITECTURE.md` | Understanding the system | | `docs/v2/API.md` | Implementing REST endpoints or WebSocket handlers | | `docs/v2/DATA_MODELS.md` | Creating/modifying Go structs or JSON schemas | | `docs/v2/UI_COMPONENTS.md` | Building React components | | `docs/v2/UI_TERMIUS_REFERENCE.md` | Designing UI layout, colors, typography | | `docs/v2/SPRINT_PLAN.md` | Detailed file-by-file task instructions | | `docs/v2/BUILD_SYSTEM.md` | Setting up build pipeline | | `docs/v2/PERFORMANCE.md` | Tuning for speed and stability | --- ## 8. Git History Reference | Commit | Description | |--------|-------------| | (V2 commits will be listed here) | — | --- **IMPORTANT**: This file MUST be updated after every development session to ensure continuity.