<p align="center">
  <picture>
    <source media="(prefers-color-scheme: dark)" srcset="./assets/banner-dark.png">
    <source media="(prefers-color-scheme: light)" srcset="./assets/banner-light.png">
    <img alt="Ghostflow - Set it once. Sync forever." src="./assets/banner-light.png" width="100%">
  </picture>
</p>

<p align="center">
  <a href="https://www.npmjs.com/package/@ghostflow/cli"><img src="https://img.shields.io/npm/v/@ghostflow/cli.svg" alt="npm version"></a>
  <a href="https://github.com/ryannono/ghostflow/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License"></a>
  <img src="https://img.shields.io/badge/macOS-12+-blue.svg" alt="macOS 12+">
  <img src="https://img.shields.io/badge/TypeScript-Ready-blue.svg" alt="TypeScript">
</p>

---

The primary user interface for Ghostflow. Provides 9 CLI commands for daemon lifecycle and flow management, plus an interactive terminal UI with real-time status and keyboard navigation.

## Quick Start

```bash
# Install globally
npm install -g @ghostflow/cli

# Add a repository and start syncing
ghostflow add ~/Documents/Obsidian/MyVault --name notes --remote origin --branch main
ghostflow start

# Check status
ghostflow status
```

Launch without arguments to open the interactive TUI:

```bash
ghostflow
```

## Commands

| Command | Description |
|---------|-------------|
| `ghostflow` | Launch interactive TUI dashboard |
| `ghostflow start` | Start the daemon |
| `ghostflow stop` | Stop the daemon |
| `ghostflow restart` | Restart the daemon |
| `ghostflow status` | Show daemon health and statistics |
| `ghostflow list` | List all configured repositories |
| `ghostflow add <path>` | Add a repository to sync |
| `ghostflow remove <name>` | Remove a repository |
| `ghostflow sync [name]` | Force immediate sync |
| `ghostflow migrate` | Migrate config format |

### Command Options

```bash
# Add a flow
ghostflow add <path> [options]
  -n, --name <name>       Display name for the flow
  -r, --remote <remote>   Git remote (default: origin)
  -b, --branch <branch>   Git branch (default: main)

# List flows
ghostflow list [options]
  --compact              Compact output
  --json                 JSON output
  --paths                Show paths only

# Check status
ghostflow status [options]
  --compact              Compact output
  --json                 JSON output
```

## Interactive TUI

Launch without arguments to open the interactive dashboard:

```
┌─────────────────────────────────────────────────────────────────┐
│ Ghostflow                                          ● Connected  │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│ 3 flows · All synced                                            │
│                                                                 │
│ ▸ obsidian ✓                               2m ago ●●●●●●●●●●●●  │
│   ~/Documents/Obsidian/Vault                                    │
│   [S] Sync  [P] Pause  [R] Remove                               │
│                                                                 │
│   dotfiles ✓                               5m ago ●●●●●●●●●●●●  │
│   ~/.dotfiles                                                   │
│                                                                 │
│   work-notes ‖ PAUSED                             ○○○○○○○○○○○○  │
│   ~/Projects/notes                                              │
│                                                                 │
├─────────────────────────────────────────────────────────────────┤
│ [↑↓] Navigate   [A] Add   [Q] Quit                              │
└─────────────────────────────────────────────────────────────────┘
```

The TUI provides:

- **Real-time flow status** with color-coded badges (✓ synced, ↻ syncing, ✗ error, ‖ paused)
- **Health bars** showing sync history as circles (● success, ○ inactive, ◐ warning, ✕ failed)
- **Inline actions** on selected flow (Sync, Pause/Resume, Remove)
- **Keyboard navigation** using arrow keys or vim-style `j`/`k`
- **Auto-start** daemon if not running

### TUI Keyboard Shortcuts

| Key | Action |
|-----|--------|
| `j` / `↓` | Move selection down |
| `k` / `↑` | Move selection up |
| `s` | Sync selected flow |
| `p` | Pause/resume selected flow |
| `a` | Add new flow |
| `r` | Remove selected flow |
| `q` | Quit |

## Architecture

```
ghostflow (no args)  →  Interactive TUI (Ink + React 19)
ghostflow <command>  →  CLI command (@effect/cli)
        │
        └─── Shared MainLive Layer (Effect-TS)
                    │
        ┌───────────┴───────────┐
        │                       │
   GhostflowClient        LaunchdService
   (daemon comms)         (macOS lifecycle)
```

The CLI uses a dual-mode architecture:

- **Without arguments**: Launches the Ink-based TUI with XState navigation
- **With subcommand**: Executes the specified command via @effect/cli

Both paths share the same Effect layer for daemon communication and service access.

### Key Dependencies

| Package | Purpose |
|---------|---------|
| `@effect/cli` | Type-safe command parsing and help generation |
| `effect` | Functional runtime, error handling, dependency injection |
| `ink` (React 19) | Terminal UI rendering and component lifecycle |
| `xstate` | Type-safe navigation state machine |
| `@tanstack/react-query` | TUI async state management |
| `@ghostflow/client` | Daemon communication (Effect API) |
| `@ghostflow/ui-core` | Shared React hooks (`useFlows`, `useSyncFlow`) |

## Configuration

Configuration lives at `~/.ghostflow/config.json`:

```json
{
  "version": 1,
  "flows": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "path": "/Users/you/Documents/Obsidian/Vault",
      "name": "obsidian",
      "remote": "origin",
      "branch": "main",
      "enabled": true
    }
  ],
  "daemon": {
    "pullIntervalSeconds": 300,
    "debounceIntervalSeconds": 2
  }
}
```

### Environment Variables

| Variable | Description | Default |
|----------|-------------|---------|
| `GHOSTFLOW_SOCKET_PATH` | Unix socket path | `/tmp/ghostflow.sock` |
| `GHOSTFLOW_CONFIG_DIR` | Config directory | `~/.ghostflow` |
| `GHOSTFLOW_LOG_LEVEL` | Logging verbosity | `info` |

## Troubleshooting

### Daemon not running

```bash
ghostflow status        # Check status
ghostflow start         # Start daemon
tail -f ~/Library/Logs/ghostflow/daemon.log  # View logs
```

### Flow in error state

```bash
ghostflow list          # Check flow status
ghostflow sync <name>   # Force sync to retry
ghostflow restart       # Restart daemon
```

### Common error codes

| Code | Meaning |
|------|---------|
| E1001 | Socket connection failed |
| E2001 | Daemon not running |
| E2002 | Flow quarantined (merge conflict) |
| E3001 | Git authentication failed |

## Development

### Prerequisites

- Node.js 18+
- pnpm 8+
- TypeScript 5.9+

### Scripts

```bash
# Build
pnpm build

# Type check
pnpm check

# Run tests
pnpm test

# Watch tests
pnpm test:watch

# Start locally
pnpm start
# or
./bin/ghostflow.js
```

### Project Structure

```
packages/cli/
├── src/
│   ├── main.ts              # Entry point (CLI vs TUI routing)
│   ├── commands/            # 9 CLI commands
│   │   ├── status.ts
│   │   ├── start.ts
│   │   ├── stop.ts
│   │   ├── restart.ts
│   │   ├── sync.ts
│   │   ├── list.ts
│   │   ├── add.ts
│   │   ├── remove.ts
│   │   └── migrate.ts
│   ├── tui/                 # Interactive terminal UI
│   │   ├── App.tsx          # Root component
│   │   ├── screens/         # DashboardScreen, ConfirmDialog
│   │   ├── components/      # FlowList, StatusBadge, KeyHints
│   │   └── machines/        # XState navigation
│   ├── layers/              # Effect dependency layers
│   ├── formatters/          # Output formatting
│   └── constants/           # ANSI colors
├── bin/
│   └── ghostflow.js         # Entry script
└── tests/
```

See [ARCHITECTURE.md](./ARCHITECTURE.md) for detailed technical documentation.

## License

MIT
