chore: move V1 plans to v1/docs/plans/ + create root AGENTS.md
- git mv docs/plans/ (V1 planning docs) into v1/docs/plans/ - Create AGENTS.md as AI session checkpoint for seamless continuation - Root now clean: only V2-related files remain
This commit is contained in:
@@ -0,0 +1,847 @@
|
||||
# Hostkeeper: SSH/SFTP Management Tool - Design Document
|
||||
|
||||
**Date:** 2024-06-22
|
||||
**Status:** Design Approved
|
||||
**Version:** 1.0-MVP
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
Hostkeeper is a cross-platform SSH/SFTP management tool written in Go, inspired by Termius but implemented as a CLI tool with progressive TUI enhancement. The goal is to provide secure SSH credential management with cross-device sync capabilities through export/import functionality.
|
||||
|
||||
### Key Design Decisions
|
||||
|
||||
- **Architecture:** TUI-first with native SSH delegation — interactive SSH via `tea.ExecProcess` (zero lag, native terminal), SFTP/browsing via in-process Go
|
||||
- **Interface:** TUI for management + native fullscreen SSH when connecting; CLI for quick tasks and automation
|
||||
- **SSH Strategy:** Delegate to native `ssh` binary via `tea.ExecProcess` (same approach as tamagosh) — eliminates lag from Go buffering, enables full terminal capability
|
||||
- **SFTP Strategy:** Use `github.com/pkg/sftp` via Go (in-process) — file operations don't need real-time echo, so Go integration works well
|
||||
- **Color Theme:** Gruvbox Material Dark Hard palette (`#d4be98`, `#a9b665`, `#e78a4e`, `#504945`) — soft, easy on eyes
|
||||
- **Storage:** JSON/YAML files (Phase 1), encrypted storage (Phase 2)
|
||||
- **Platform:** Cross-platform (Linux, macOS, Windows, Termux/Android)
|
||||
- **Sync:** Manual export/import (Phase 1), cloud sync (future)
|
||||
|
||||
---
|
||||
|
||||
## Project Requirements
|
||||
|
||||
### Must-Have Features (MVP)
|
||||
|
||||
1. **SSH Connection Management**
|
||||
- Username/password authentication
|
||||
- SSH key authentication
|
||||
- Host organization and search
|
||||
- Connection testing
|
||||
|
||||
2. **SFTP File Transfer**
|
||||
- Native SFTP client (Phase 1)
|
||||
- Custom TUI dual-pane browser (Phase 2)
|
||||
|
||||
3. **Credential Management**
|
||||
- Secure local storage
|
||||
- Host metadata (tags, descriptions)
|
||||
- Quick access patterns
|
||||
|
||||
4. **SSH Key Management**
|
||||
- Generate SSH keys
|
||||
- Import existing keys
|
||||
- Export keys for distribution
|
||||
- Key-Host association
|
||||
|
||||
5. **Connection Snippets**
|
||||
- Save common commands
|
||||
- Variable substitution
|
||||
- Per-host snippets
|
||||
|
||||
6. **Export/Import Functionality**
|
||||
- Cross-device credential transfer
|
||||
- Backup and restore
|
||||
- Merge capabilities
|
||||
|
||||
7. **Cross-Platform Support**
|
||||
- Single binary distribution
|
||||
- Termux compatibility
|
||||
- Platform-specific optimizations
|
||||
|
||||
8. **Security**
|
||||
- File permission management
|
||||
- Secure credential storage
|
||||
- Memory protection for sensitive data
|
||||
|
||||
---
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
### High-Level Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ HOSTKEEPER CLI │
|
||||
│ (Single Binary) │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
┌─────────────────────┼─────────────────────┐
|
||||
│ │ │
|
||||
┌───────▼──────────┐ ┌──────▼──────┐ ┌─────────▼────────┐
|
||||
│ Command Layer │ │ TUI Layer │ │ Core Engine │
|
||||
│ │ │ │ │ │
|
||||
│ • connect │ │ • Host List │ │ • SSH Client │
|
||||
│ • list │ │ • SFTP UI │ │ • SFTP Client │
|
||||
│ • sftp │ │ • Key Mgmt │ │ • Key Manager │
|
||||
│ • export │ │ • Snippets │ │ • Encryption │
|
||||
│ • import │ │ • Settings │ │ • Config I/O │
|
||||
│ • add │ │ │ │ │
|
||||
└─────────────────┘ └─────────────┘ └──────────────────┘
|
||||
│ │ │
|
||||
└─────────────────────┼─────────────────────┘
|
||||
│
|
||||
┌─────────▼─────────┐
|
||||
│ Storage Layer │
|
||||
│ │
|
||||
│ • hosts.json │
|
||||
│ • keys.json │
|
||||
│ • snippets.json │
|
||||
│ • config.yaml │
|
||||
└──────────────────┘
|
||||
```
|
||||
|
||||
### Key Design Principles
|
||||
|
||||
1. **Single Source of Truth** - All data stored in JSON files
|
||||
2. **TUI-First** - TUI is the primary interface; CLI commands serve quick tasks and scripting
|
||||
3. **Layered Architecture** - UI → Business Logic → Storage
|
||||
4. **Cross-Platform** - Pure Go, no OS-specific dependencies
|
||||
5. **Encrypt-Ready** - Structure prepared for encryption upgrade
|
||||
6. **Orange Theme** - Distinct orange color palette to visually separate Hostkeeper from the native terminal, signaling the user is inside the application environment
|
||||
|
||||
---
|
||||
|
||||
## Component Details
|
||||
|
||||
### 1. Command Layer (CLI Interface)
|
||||
|
||||
**Framework:** Cobra (standard Go CLI framework)
|
||||
|
||||
**Major Commands:**
|
||||
```bash
|
||||
hostkeeper connect <host> # SSH connection
|
||||
hostkeeper list # List all hosts
|
||||
hostkeeper sftp <host> # SFTP browser
|
||||
hostkeeper add # Add new host
|
||||
hostkeeper edit <host> # Edit host config
|
||||
hostkeeper delete <host> # Delete host
|
||||
hostkeeper export <file> # Export credentials
|
||||
hostkeeper import <file> # Import credentials
|
||||
hostkeeper key generate # Generate SSH key
|
||||
hostkeeper key import <file> # Import existing key
|
||||
hostkeeper snippet add <name> # Add command snippet
|
||||
hostkeeper completion # Shell completion setup
|
||||
```
|
||||
|
||||
**Error Handling:**
|
||||
- Invalid command → Show help message
|
||||
- Missing arguments → Prompt interactive input
|
||||
- Connection errors → User-friendly error messages with hints
|
||||
|
||||
---
|
||||
|
||||
### 2. TUI Layer (Interactive Interface)
|
||||
|
||||
**Framework:** Bubble Tea (event-driven TUI) + Lipgloss (styling)
|
||||
|
||||
**Theme:** Gruvbox Material Dark Hard palette (`#d4be98`, `#a9b665`, `#e78a4e`, `#504945`, `#ea6962`) — soft, warm, easy on eyes over long sessions
|
||||
|
||||
#### Tab System Architecture
|
||||
|
||||
```
|
||||
┌─ Hosts ──── SFTP:server1 ── Keys ── Snippets ────────────────┐
|
||||
│ │
|
||||
│ [content of active tab — host list, SFTP browser, etc.] │
|
||||
│ │
|
||||
├───────────────────────────────────────────────────────────────┤
|
||||
│ Ctrl+Tab:switch Ctrl+Q:close ↑↓:nav Enter:SSH /:search │
|
||||
└───────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Tab Types:**
|
||||
- **HostsTab** — Host list with search, filter, sort, keyboard navigation
|
||||
- **SFTPTab** — Dual-pane (local ↔ remote) file browser with upload/download/delete/rename
|
||||
- **KeysTab** — SSH key management (list, add, edit, delete)
|
||||
- **SnippetsTab** — Command snippets management
|
||||
|
||||
**SSH Connect (NOT a tab — fullscreen native SSH delegation):**
|
||||
- User selects host → presses Enter
|
||||
- TUI exits alt-screen, runs `tea.ExecProcess` → native `ssh` binary takes over terminal directly
|
||||
- Zero lag: native SSH handles PTY, echo, resize, signals — no Go buffering
|
||||
- On SSH exit → TUI resumes, returns to host list
|
||||
- Password auth via `sshpass -e` (SSHPASS env var)
|
||||
- Key auth via `ssh -i <keypath>` (passphrase via SSH_ASKPASS if needed)
|
||||
- User can install `tmux` on server for session persistence (optional)
|
||||
|
||||
**Rationale:** In-process SSH (golang.org/x/crypto/ssh with goroutine I/O) introduces ~6 layers of buffering between keystroke and echo. Delegating to native `ssh` via `tea.ExecProcess` eliminates all Go overhead from the real-time I/O path, giving a native-terminal experience.
|
||||
|
||||
**Keyboard Navigation:**
|
||||
| Key | Action |
|
||||
|-----|--------|
|
||||
| `Ctrl+Tab` / `Shift+Tab` | Cycle tabs forward/backward |
|
||||
| `Ctrl+N` | Add new host |
|
||||
| `Ctrl+E` | Edit selected host |
|
||||
| `Ctrl+F` | Open SFTP browser for selected host |
|
||||
| `Ctrl+K` | SSH Keys management |
|
||||
| `Ctrl+P` | Snippets management |
|
||||
| `Enter` | SSH into selected host (fullscreen native SSH) |
|
||||
| `↑` / `↓` | Navigate lists |
|
||||
| `D` / `Delete` | Delete selected item |
|
||||
| `Ctrl+Q` | Close current tab |
|
||||
| `q` | Quit Hostkeeper |
|
||||
|
||||
---
|
||||
|
||||
### 3. Core Engine (Business Logic)
|
||||
|
||||
#### SSH Client Module
|
||||
|
||||
```go
|
||||
type SSHClient struct {
|
||||
Hostname string
|
||||
Port int
|
||||
AuthMethod AuthMethod // password, key, or both
|
||||
ClientConfig *ssh.ClientConfig
|
||||
}
|
||||
|
||||
func (c *SSHClient) Connect() (*ssh.Client, error)
|
||||
func (c *SSHClient) Execute(cmd string) (string, error)
|
||||
func (c *SSHClient) Close() error
|
||||
```
|
||||
|
||||
#### SFTP Client Module
|
||||
|
||||
```go
|
||||
type SFTPClient struct {
|
||||
SSHClient *SSHClient
|
||||
Client *sftp.Client
|
||||
}
|
||||
|
||||
func (s *SFTPClient) Connect() error
|
||||
func (s *SFTPClient) Upload(local, remote string) error
|
||||
func (s *SFTPClient) Download(remote, local string) error
|
||||
func (s *SFTPClient) List(path string) ([]os.FileInfo, error)
|
||||
```
|
||||
|
||||
#### Key Management Module
|
||||
|
||||
```go
|
||||
type KeyManager struct {
|
||||
StoragePath string
|
||||
}
|
||||
|
||||
func (k *KeyManager) GenerateKey(name string) (*KeyPair, error)
|
||||
func (k *KeyManager) ImportKey(name, keyPath string) error
|
||||
func (k *KeyManager) ExportKey(name, destPath string) error
|
||||
func (k *KeyManager) ListKeys() ([]KeyInfo, error)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. Storage Layer (Data Persistence)
|
||||
|
||||
#### File Structure
|
||||
|
||||
```
|
||||
~/.hostkeeper/
|
||||
├── config.yaml # App configuration
|
||||
├── hosts.json # Saved hosts/connections
|
||||
├── keys.json # SSH keys store
|
||||
├── snippets.json # Command snippets
|
||||
└── exported/ # Exported configurations
|
||||
└── hostkeeper-backup-2024-06-22.json
|
||||
```
|
||||
|
||||
#### Data Structures
|
||||
|
||||
**hosts.json:**
|
||||
```json
|
||||
{
|
||||
"hosts": [
|
||||
{
|
||||
"id": "server1",
|
||||
"name": "Production Server",
|
||||
"hostname": "192.168.1.100",
|
||||
"port": 22,
|
||||
"username": "admin",
|
||||
"auth": {
|
||||
"type": "key",
|
||||
"key_id": "default_key",
|
||||
"password": null
|
||||
},
|
||||
"tags": ["production", "linux"],
|
||||
"created_at": "2024-06-22T10:00:00Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**keys.json:**
|
||||
```json
|
||||
{
|
||||
"keys": [
|
||||
{
|
||||
"id": "default_key",
|
||||
"name": "Default Key",
|
||||
"private_key": "-----BEGIN RSA PRIVATE KEY-----...",
|
||||
"public_key": "ssh-rsa AAAA...",
|
||||
"comment": "Generated by hostkeeper",
|
||||
"created_at": "2024-06-22T10:00:00Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**config.yaml:**
|
||||
```yaml
|
||||
version: "1.0"
|
||||
default_port: 22
|
||||
connection_timeout: 30
|
||||
sftp_timeout: 60
|
||||
log_level: info
|
||||
storage:
|
||||
encrypt: false
|
||||
compression: false
|
||||
terminal:
|
||||
color_scheme: default
|
||||
font_size: medium
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Key User Workflows
|
||||
|
||||
### Workflow 1: Quick SSH Connection (Command-based)
|
||||
|
||||
```bash
|
||||
$ hostkeeper connect production
|
||||
```
|
||||
|
||||
**Flow:**
|
||||
1. CLI parses command → validates host exists
|
||||
2. Core Engine loads host config from `hosts.json`
|
||||
3. Establishes SSH connection with native terminal
|
||||
4. User gets native terminal experience
|
||||
5. On exit: connection cleanup, return to CLI
|
||||
|
||||
**Error Handling:**
|
||||
- Host not found → Show available hosts
|
||||
- Connection failed → User-friendly error with troubleshooting tips
|
||||
- Auth failed → Prompt for password/key selection
|
||||
|
||||
---
|
||||
|
||||
### Workflow 2: Add New Host (Interactive)
|
||||
|
||||
```bash
|
||||
$ hostkeeper add
|
||||
```
|
||||
|
||||
**Interactive Prompts:**
|
||||
```
|
||||
Hostname: staging-server
|
||||
IP Address: 192.168.1.50
|
||||
Port: [22]
|
||||
Username: admin
|
||||
Auth Method: [1] Password [2] SSH Key → 2
|
||||
Tags: staging, linux, development
|
||||
```
|
||||
|
||||
**Flow:**
|
||||
1. Collect host information interactively
|
||||
2. Validate for duplicates
|
||||
3. Generate UUID for host
|
||||
4. Append to `hosts.json`
|
||||
5. Offer connection test
|
||||
|
||||
---
|
||||
|
||||
### Workflow 3: SFTP File Transfer
|
||||
|
||||
#### Phase 1 (MVP) - Native SFTP
|
||||
```bash
|
||||
$ hostkeeper sftp production
|
||||
sftp> put /local/file.txt /remote/path/
|
||||
sftp> get /remote/file.zip /local/backup/
|
||||
sftp> ls -la /var/www/
|
||||
```
|
||||
|
||||
#### Phase 2 - Custom TUI Browser
|
||||
```
|
||||
┌────────────────────┬────────────────────┐
|
||||
│ Local Files │ Remote Files │
|
||||
│ │ │
|
||||
│ 📁 Documents/ │ 📁 /var/www/ │
|
||||
│ 📄 file.txt │ 📄 index.html │
|
||||
│ 📄 backup.zip │ 📄 config.php │
|
||||
│ │ │
|
||||
│ [Upload] [Refresh] │ [Download] [Delete]│
|
||||
└────────────────────┴────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Workflow 4: Export/Import Credentials
|
||||
|
||||
```bash
|
||||
$ hostkeeper export backup-2024-06.json
|
||||
$ hostkeeper import backup-2024-06.json
|
||||
```
|
||||
|
||||
**Export Flow:**
|
||||
1. Read all JSON files
|
||||
2. Combine into single structure
|
||||
3. Phase 1: Plain JSON export
|
||||
4. Phase 2: AES-256 encryption with password
|
||||
5. Write export file with summary
|
||||
|
||||
**Export Structure:**
|
||||
```json
|
||||
{
|
||||
"version": "1.0",
|
||||
"exported_at": "2024-06-22T16:00:00Z",
|
||||
"data": {
|
||||
"hosts": [...],
|
||||
"keys": [...],
|
||||
"snippets": [...],
|
||||
"config": {...}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Import Flow:**
|
||||
1. Validate import file format
|
||||
2. Phase 2: Decrypt with password
|
||||
3. Merge options: replace/merge/skip
|
||||
4. Update local JSON files
|
||||
5. Show import summary
|
||||
|
||||
---
|
||||
|
||||
## Security Architecture
|
||||
|
||||
### Phase 1 Security (MVP)
|
||||
|
||||
**File Security:**
|
||||
- File permissions: 0600 (owner read/write only)
|
||||
- Environment variable protection
|
||||
- No password/key logging in errors
|
||||
- Sensitive data filtering from logs
|
||||
- Plain text storage (Phase 2 encryption)
|
||||
|
||||
**Security Measures:**
|
||||
```go
|
||||
// Proper file permissions
|
||||
func SaveConfig(data []byte, path string) error {
|
||||
err := os.WriteFile(path, data, 0600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Validate permissions
|
||||
info, _ := os.Stat(path)
|
||||
if info.Mode().Perm() != 0600 {
|
||||
os.Chmod(path, 0600)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Phase 2 Security (Enhanced)
|
||||
|
||||
**Encryption Layer:**
|
||||
```go
|
||||
type EncryptionManager struct {
|
||||
MasterPassword []byte
|
||||
Salt []byte
|
||||
}
|
||||
|
||||
func (e *EncryptionManager) EncryptData(data []byte) ([]byte, error) {
|
||||
// PBKDF2 key derivation
|
||||
key := pbkdf2.Key(e.MasterPassword, e.Salt, 100000, 32, sha256.New)
|
||||
|
||||
// AES-256-GCM encryption
|
||||
block, err := aes.NewCipher(key)
|
||||
gcm, err := cipher.NewGCM(block)
|
||||
|
||||
// Encrypt with random nonce
|
||||
nonce := make([]byte, gcm.NonceSize())
|
||||
rand.Read(nonce)
|
||||
|
||||
ciphertext := gcm.Seal(nonce, nonce, data, nil)
|
||||
return ciphertext, nil
|
||||
}
|
||||
```
|
||||
|
||||
**Encrypted Storage Format:**
|
||||
```json
|
||||
{
|
||||
"version": "2.0",
|
||||
"encryption": "AES-256-GCM",
|
||||
"iterations": 100000,
|
||||
"salt": "base64_encoded_salt",
|
||||
"data": "encrypted_base64_data"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Security Best Practices
|
||||
|
||||
**Memory Security:**
|
||||
```go
|
||||
// Clear sensitive data from memory
|
||||
func ClearSensitiveData(data []byte) {
|
||||
for i := range data {
|
||||
data[i] = 0
|
||||
}
|
||||
}
|
||||
defer ClearSensitiveData(password)
|
||||
```
|
||||
|
||||
**Logging Security:**
|
||||
```go
|
||||
// Filter sensitive information
|
||||
func sanitizeSensitiveData(input string) string {
|
||||
sensitivePatterns := []string{
|
||||
`password["']?\s*[:=]\s*["']?[^\s"']+`,
|
||||
`private_key["']?\s*[:=]\s*["']?.+?["']?`,
|
||||
}
|
||||
|
||||
for _, pattern := range sensitivePatterns {
|
||||
re := regexp.MustCompile(pattern)
|
||||
input = re.ReplaceAllString(input, "[REDACTED]")
|
||||
}
|
||||
|
||||
return input
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Error Handling Strategy
|
||||
|
||||
### Connection Error Handling
|
||||
|
||||
```go
|
||||
type ConnectionError struct {
|
||||
Type string // "auth", "network", "timeout", "config"
|
||||
Message string
|
||||
Details string
|
||||
Hints []string
|
||||
}
|
||||
|
||||
func HandleSSHError(err error) *ConnectionError {
|
||||
switch {
|
||||
case strings.Contains(err.Error(), "connection refused"):
|
||||
return &ConnectionError{
|
||||
Type: "network",
|
||||
Message: "Cannot connect to server",
|
||||
Details: err.Error(),
|
||||
Hints: []string{"Check if server is running", "Verify firewall rules"},
|
||||
}
|
||||
|
||||
case strings.Contains(err.Error(), "authentication failed"):
|
||||
return &ConnectionError{
|
||||
Type: "auth",
|
||||
Message: "Authentication failed",
|
||||
Details: err.Error(),
|
||||
Hints: []string{"Verify username/password", "Check SSH key permissions"},
|
||||
}
|
||||
|
||||
// ... additional cases
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Error Display Format:**
|
||||
```
|
||||
❌ Connection Error: Authentication failed
|
||||
|
||||
Details: ssh: handshake failed: ssh: unable to authenticate
|
||||
|
||||
Possible solutions:
|
||||
1. Verify username: admin
|
||||
2. Check SSH key is loaded: hostkeeper key list
|
||||
3. Test connection manually: ssh admin@192.168.1.100
|
||||
|
||||
Use 'hostkeeper edit production' to update credentials
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Critical Error Scenarios
|
||||
|
||||
**Scenario 1: Corrupted Configuration File**
|
||||
```
|
||||
❌ Configuration Error: Invalid hosts.json
|
||||
|
||||
Details: hosts.json contains corrupted data at line 23
|
||||
|
||||
Recovery options:
|
||||
1. Restore from backup: ~/.hostkeeper/hosts.json.backup
|
||||
2. Import from export: hostkeeper import backup.json
|
||||
3. Reset configuration: hostkeeper reset --force (⚠️ This will delete all data)
|
||||
|
||||
Action needed: Configuration is unusable. Please choose recovery option.
|
||||
```
|
||||
|
||||
**Scenario 2: SSH Key Permission Issues**
|
||||
```
|
||||
⚠️ Security Warning: Insecure key permissions
|
||||
|
||||
File: ~/.ssh/id_rsa has permissions 644
|
||||
Recommended: 600 (owner read/write only)
|
||||
|
||||
Auto-fix command:
|
||||
$ chmod 600 ~/.ssh/id_rsa
|
||||
|
||||
Continue anyway? [y/N]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Cross-Platform Strategy
|
||||
|
||||
### Platform Support
|
||||
|
||||
**Primary Platforms:**
|
||||
- Linux (x86_64, ARM)
|
||||
- macOS (x86_64, ARM64)
|
||||
- Windows (x86_64)
|
||||
- Termux/Android (ARM)
|
||||
|
||||
**Build Strategy:**
|
||||
- Go cross-compilation for all platforms
|
||||
- Single binary distribution
|
||||
- Platform-specific optimizations
|
||||
|
||||
**Platform-Specific Handling:**
|
||||
|
||||
**Linux/Unix:**
|
||||
- Standard permission handling
|
||||
- Native terminal integration
|
||||
- System configuration paths
|
||||
|
||||
**macOS:**
|
||||
- Keychain integration (optional)
|
||||
- Proper terminal sizing
|
||||
- macOS-specific paths
|
||||
|
||||
**Windows:**
|
||||
- Windows Terminal support
|
||||
- Path handling (backslash vs forward slash)
|
||||
- Registry integration (optional)
|
||||
|
||||
**Termux/Android:**
|
||||
- File permissions workaround
|
||||
- Storage location adaptation
|
||||
- Terminal limitations handling
|
||||
|
||||
---
|
||||
|
||||
## Technology Stack
|
||||
|
||||
### Core Libraries
|
||||
|
||||
**SSH/SFTP:**
|
||||
- `golang.org/x/crypto/ssh` - SSH protocol implementation
|
||||
- `pkg.sftp.io/ssh` - SFTP client implementation
|
||||
|
||||
**CLI Framework:**
|
||||
- `github.com/spf13/cobra` - Command framework
|
||||
- `github.com/spf13/viper` - Configuration management
|
||||
|
||||
**TUI Framework:**
|
||||
- `github.com/charmbracelet/bubbletea` - TUI framework
|
||||
- `github.com/charmbracelet/lipgloss` - Styling
|
||||
|
||||
**Encryption:**
|
||||
- `crypto/aes` - AES encryption (Phase 2)
|
||||
- `crypto/cipher` - Cipher implementations
|
||||
- `crypto/pbkdf2` - Key derivation
|
||||
|
||||
**Utilities:**
|
||||
- `encoding/json` - JSON handling
|
||||
- `gopkg.in/yaml.v3` - YAML support
|
||||
- `github.com/google/uuid` - UUID generation
|
||||
|
||||
---
|
||||
|
||||
## Implementation Phases
|
||||
|
||||
### Phase 1: MVP Foundation (3-4 weeks)
|
||||
|
||||
**Core Functionality:**
|
||||
- Basic SSH connections (native terminal)
|
||||
- Host management (add, list, edit, delete)
|
||||
- SSH key generation and import
|
||||
- Export/Import (plain JSON)
|
||||
- Native SFTP client
|
||||
- Basic TUI for host management
|
||||
|
||||
**Deliverables:**
|
||||
- Working CLI with core commands
|
||||
- JSON-based storage
|
||||
- Cross-platform binary builds
|
||||
- Basic documentation
|
||||
|
||||
---
|
||||
|
||||
### Phase 2: TUI Overhaul & Enhanced Features (4-6 weeks)
|
||||
|
||||
**Priority 1 — TUI Overhaul (Completed):**
|
||||
- Tab system with Gruvbox Material theme (TabManager, tab bar, keyboard shortcuts)
|
||||
- Native SSH delegation via `tea.ExecProcess` (zero-lag fullscreen SSH, inspired by tamagosh)
|
||||
- TUI forms for add/edit hosts
|
||||
- Dual-pane SFTP browser (local ↔ remote) with upload/download/delete/rename
|
||||
- Key & snippet management in TUI
|
||||
|
||||
**Priority 2 — Security Enhancement:**
|
||||
- AES-256-GCM encryption for secrets file (inspired by tamagosh)
|
||||
- Key passphrase support via SSH_ASKPASS
|
||||
- Known_hosts verification for SFTP connections
|
||||
|
||||
**Priority 3 — UX Polish:**
|
||||
- Configuration profiles
|
||||
- Theme customization
|
||||
- Enhanced error messages in TUI
|
||||
|
||||
---
|
||||
|
||||
### Phase 3: Advanced Features (Future)
|
||||
|
||||
**Cloud Sync:**
|
||||
- User account system
|
||||
- Encrypted cloud storage
|
||||
- Real-time multi-device sync
|
||||
- Conflict resolution
|
||||
|
||||
**Advanced Terminal:**
|
||||
- Custom terminal emulator
|
||||
- Advanced text selection
|
||||
|
||||
**Integration:**
|
||||
- Web UI (optional)
|
||||
- API access
|
||||
- Plugin system
|
||||
- Third-party integrations
|
||||
|
||||
---
|
||||
|
||||
## Development Guidelines
|
||||
|
||||
### Code Quality
|
||||
|
||||
**Standards:**
|
||||
- Follow Go best practices and idioms
|
||||
- Comprehensive error handling
|
||||
- Logging for debugging
|
||||
- Code documentation
|
||||
- Unit tests for critical functions
|
||||
|
||||
**Security Considerations:**
|
||||
- No hardcoded credentials
|
||||
- Input validation and sanitization
|
||||
- Secure default configurations
|
||||
- Regular security audits
|
||||
|
||||
---
|
||||
|
||||
### Testing Strategy
|
||||
|
||||
**Unit Testing:**
|
||||
- Core engine functions
|
||||
- SSH connection logic
|
||||
- Encryption/decryption
|
||||
- Configuration management
|
||||
|
||||
**Integration Testing:**
|
||||
- End-to-end SSH connections
|
||||
- SFTP operations
|
||||
- Export/Import functionality
|
||||
- Cross-platform compatibility
|
||||
|
||||
**Manual Testing:**
|
||||
- Cross-platform testing (Linux, macOS, Windows, Termux)
|
||||
- User experience validation
|
||||
- Performance testing
|
||||
- Security validation
|
||||
|
||||
---
|
||||
|
||||
## Success Criteria
|
||||
|
||||
### MVP Success Metrics
|
||||
|
||||
- ✅ Can establish SSH connections to remote servers
|
||||
- ✅ Can manage multiple hosts with different auth methods
|
||||
- ✅ Can perform SFTP operations (Phase 1: native, Phase 2: TUI)
|
||||
- ✅ Can export/import credentials across devices
|
||||
- ✅ Works on Linux, macOS, Windows, and Termux
|
||||
- ✅ Secure credential storage with proper permissions
|
||||
- ✅ User-friendly error messages and help text
|
||||
|
||||
### Phase 2 Success Metrics
|
||||
|
||||
- ✅ Rich TUI interface for all operations
|
||||
- ✅ Zero-lag SSH via native binary delegation
|
||||
- ✅ Dual-pane SFTP browser (local ↔ remote)
|
||||
- ✅ Shell completion and documentation
|
||||
- ✅ Enhanced user experience with Gruvbox palette
|
||||
|
||||
---
|
||||
|
||||
## Risks and Mitigation
|
||||
|
||||
### Technical Risks
|
||||
|
||||
**Risk:** SSH terminal emulation complexity
|
||||
**Mitigation:** Progressive approach - native terminal first, custom TUI later
|
||||
|
||||
**Risk:** Cross-platform compatibility issues
|
||||
**Mitigation:** Extensive testing on all platforms, Go's cross-compilation
|
||||
|
||||
**Risk:** Performance issues with TUI
|
||||
**Mitigation:** Framework selection (Bubble Tea), performance testing
|
||||
|
||||
### Security Risks
|
||||
|
||||
**Risk:** Credential exposure
|
||||
**Mitigation:** Proper file permissions, memory clearing, secure defaults
|
||||
|
||||
**Risk:** Key management complexity
|
||||
**Mitigation:** Clear user guidance, validation, secure defaults
|
||||
|
||||
**Risk:** Encryption implementation bugs
|
||||
**Mitigation:** Use standard libraries, security audits, testing
|
||||
|
||||
---
|
||||
|
||||
## Conclusion
|
||||
|
||||
Hostkeeper aims to provide a comprehensive SSH/SFTP management solution with cross-platform support and secure credential management. The progressive development approach ensures rapid delivery of core functionality while maintaining a clear path to advanced features.
|
||||
|
||||
The hybrid CLI/TUI approach balances power user needs with accessibility, while the phased implementation allows for iterative improvement based on user feedback.
|
||||
|
||||
---
|
||||
|
||||
**Document Status:** Approved for implementation
|
||||
**Next Steps:** Implementation planning using writing-plans skill
|
||||
|
||||
---
|
||||
|
||||
*Sources:*
|
||||
- [golang.org/x/crypto/ssh](https://pkg.go.dev/golang.org/x/crypto/ssh)
|
||||
- [Cobra CLI Framework](https://github.com/spf13/cobra)
|
||||
- [Bubble Tea TUI Framework](https://github.com/charmbracelet/bubbletea)
|
||||
- [Tamagosh SSH Manager](https://github.com/Candratama/tamagosh)
|
||||
- [Termius SSH Client](https://termius.com/)
|
||||
Reference in New Issue
Block a user