c215d68c81
- git mv docs/v2/*.md docs/ (11 planning documents) - Remove empty docs/v2/ directory - Update all references: AGENTS.md, CHANGELOG.md, README.md, ARCHITECTURE.md - Fix outdated repo tree in ARCHITECTURE.md to match actual structure
340 lines
15 KiB
Markdown
340 lines
15 KiB
Markdown
# 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/PROGRESS.md`) — find the first `[ ]` item
|
|
2. **Read the relevant spec doc** — for the current task:
|
|
- REST API endpoints -> `docs/API.md`
|
|
- UI components -> `docs/UI_COMPONENTS.md`
|
|
- Data models -> `docs/DATA_MODELS.md`
|
|
- Visual reference -> `docs/UI_TERMIUS_REFERENCE.md`
|
|
- Performance notes -> `docs/PERFORMANCE.md`
|
|
- Build pipeline -> `docs/BUILD_SYSTEM.md`
|
|
3. **Read `docs/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/PROGRESS.md` | Always (first) — know where to continue |
|
|
| `docs/ARCHITECTURE.md` | Understanding the system |
|
|
| `docs/API.md` | Implementing REST endpoints or WebSocket handlers |
|
|
| `docs/DATA_MODELS.md` | Creating/modifying Go structs or JSON schemas |
|
|
| `docs/UI_COMPONENTS.md` | Building React components |
|
|
| `docs/UI_TERMIUS_REFERENCE.md` | Designing UI layout, colors, typography |
|
|
| `docs/SPRINT_PLAN.md` | Detailed file-by-file task instructions |
|
|
| `docs/BUILD_SYSTEM.md` | Setting up build pipeline |
|
|
| `docs/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.
|