You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: replace tmux/ttyd with built-in PTY multiplexer
Replace the tmux + ttyd terminal architecture with a native PTY
multiplexer built into the server binary. This eliminates two external
dependencies and enables a unified WebSocket protocol for terminal
panes across web, mobile, and CLI.
Key changes:
- Add nomadflow-pty crate with PTY actor, pane manager, snapshot
system, and binary WS protocol
- Add multiplexed pane WebSocket route and REST pane endpoints
- Add Unix socket listener for local CLI attach
- Replace WebView-based terminal on mobile with bundled HTML +
typed message protocol bridge
- Migrate web dashboard to xterm.js with shared WS context hook
- Add file tree browser (web + mobile) and syntax highlighting
- Add Basic Auth support with WWW-Authenticate header
- Remove tmux, ttyd, and session picker dependencies
- Add language toggle (en/fr), voice dictation on mobile
- CWD-based agent state tracking (replaces session-ID based)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: README.md
+17-26Lines changed: 17 additions & 26 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,7 +2,7 @@
2
2
3
3
**Code from anywhere — mobile terminal & workflow manager for nomad developers**
4
4
5
-
NomadFlow is an open-source platform that turns your phone into a full development environment. A single Rust binary manages git worktrees, tmux sessions, and a web terminal, while the React Native app lets you seamlessly switch between projects from your pocket.
5
+
NomadFlow is an open-source platform that turns your phone into a full development environment. A single Rust binary manages git worktrees, Rust-native PTY sessions, and a real-time terminal, while the React Native app lets you seamlessly switch between projects from your pocket.
Copy file name to clipboardExpand all lines: docs/content/docs/cli.mdx
+13-7Lines changed: 13 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -19,7 +19,7 @@ nomadflow [OPTIONS] [COMMAND]
19
19
nomadflow
20
20
```
21
21
22
-
Starts the HTTP server in the background, then launches the **TUI wizard**. When the TUI exits, the server is gracefully shut down (ttyd is cleanly stopped, no orphan processes). If the TUI returns a tmux session to attach to, `tmux attach-session` is executed automatically.
22
+
Starts the HTTP server in the background, then launches the **TUI wizard**. When the TUI exits, the server is gracefully shut down. The TUI allows managing PTY sessions and worktrees interactively.
23
23
24
24
### `serve`
25
25
@@ -35,7 +35,7 @@ Runs the HTTP server in the **foreground** with full tracing/logging enabled. Us
35
35
|`--host <address>`| Override the displayed address (IP or domain name) for QR code and URL. |
36
36
|`--port <port>`| Override the API server port (default: from `config.toml`, fallback `8080`). |
37
37
38
-
The server handles **graceful shutdown**: on `Ctrl+C` or `SIGTERM`, it stops accepting new connections, completes in-flight requests, then cleanly stops the ttyd subprocess.
38
+
The server handles **graceful shutdown**: on `Ctrl+C` or `SIGTERM`, it stops accepting new connections, completes in-flight requests, and cleanly shuts down all managed PTY processes.
39
39
40
40
### `start`
41
41
@@ -61,7 +61,7 @@ Stops the background daemon. Reads the PID file, sends `SIGTERM` to trigger grac
61
61
nomadflow web [--port <port>]
62
62
```
63
63
64
-
Starts a lightweight HTTP server that serves the **web dashboard** (static files), then opens it in your default browser. This is a standalone server — no tmux, no ttyd, no auth required.
64
+
Starts a lightweight HTTP server that serves the **web dashboard** (static files), then opens it in your default browser. This is a standalone server — no auth required.
65
65
66
66
| Option | Description |
67
67
|--------|-------------|
@@ -96,33 +96,39 @@ Removes a previously linked repository from NomadFlow. If no name is given, show
96
96
nomadflow --status
97
97
```
98
98
99
-
Displays the current **daemon status** (running/not running, PID) and the **tmux session status** (windows, features), then exits.
99
+
Displays the current **daemon status** (running/not running, PID) and the **active PTY panes** (repo, worktree, agent type), then exits.
100
100
101
101
### `attach`
102
102
103
103
```bash
104
-
nomadflow attach [<window>]
104
+
nomadflow attach [--pane <id>]
105
105
```
106
106
107
-
Attaches to an existing tmux window (no server needed). If a window name is provided (e.g. `omstudio:my-feature`), attaches directly. Otherwise, shows an interactive picker listing all windows with their current process status.
107
+
Attaches to a server-managed PTY pane via a Unix socket. This provides a native terminal experience directly in your CLI.
108
+
109
+
| Option | Description |
110
+
|--------|-------------|
111
+
|`--pane <id>`| (Optional) The numeric ID of the pane to attach to. If omitted, shows an interactive picker. |
108
112
109
113
## TUI wizard
110
114
111
115
When running in default mode, the TUI provides an interactive terminal interface with the following screens:
112
116
117
+
-**Session picker** — quick resume of active PTY sessions
113
118
-**Server list** — manage remote server connections
description: Architecture, git worktrees, tmux sessions, and how they fit together.
3
+
description: Architecture, git worktrees, PTY sessions, and how they fit together.
4
4
---
5
5
6
6
## Architecture
7
7
8
-
NomadFlowCode is built as a Rust workspace with three crates:
8
+
NomadFlowCode is built as a Rust workspace with four core crates:
9
9
10
10
| Crate | Role |
11
11
|-------|------|
12
-
|`nomadflow-core`| Configuration, data models, shell utilities, git/tmux/ttyd services |
13
-
|`nomadflow-server`| Axum HTTP server with auth middleware and WebSocket proxy |
12
+
|`nomadflow-core`| Configuration, data models, shell utilities, git services |
13
+
|`nomadflow-pty`| Binary protocol definitions and PTY handling logic |
14
+
|`nomadflow-server`| Axum HTTP server, authentication, and multiplexed WebSocket |
14
15
|`nomadflow-tui`| Ratatui TUI wizard for interactive setup |
15
16
16
-
All three compile into a single `nomadflow` binary.
17
+
All crates compile into a single `nomadflow` binary.
17
18
18
19
## Git worktrees
19
20
@@ -31,22 +32,22 @@ Instead of switching branches in a single working directory, NomadFlowCode uses
31
32
32
33
This means you can have multiple features checked out simultaneously without stashing or losing state.
33
34
34
-
## Tmux sessions
35
+
## Terminal sessions (PTY)
35
36
36
-
NomadFlowCode manages a single tmux session (default: `nomadflow`). Each feature gets a dedicated tmux window named `{repo}:{feature}` to avoid collisions across repositories.
37
+
NomadFlowCode uses a native Rust PTY multiplexer instead of external tools like tmux. Each terminal session runs as a **PaneActor** managed by a **PaneManager**.
37
38
38
39
When you switch features, the server:
39
40
1. Creates a worktree (if needed)
40
-
2.Creates or selects the tmux window
41
-
3.Changes to the worktree directory
41
+
2.Spawns a PTY process in that worktree directory
42
+
3.Manages the terminal state (ANSI parsing, buffer snapshots) in memory
42
43
43
-
## ttyd and WebSocket proxy
44
+
## Multiplexed WebSocket
44
45
45
-
[ttyd](https://github.com/tsl0922/ttyd) exposes the tmux session as a web terminal on port 7681. The mobile app loads the ttyd HTML page directly for HTTP content.
46
-
47
-
For WebSocket connections, iOS WKWebView does not send Basic Auth headers on WebSocket upgrades. To solve this, the NomadFlowCode server provides a WebSocket proxy at `/terminal/ws` that:
48
-
1. Authenticates via a `token` query parameter
49
-
2. Forwards the WebSocket connection to ttyd with proper Basic Auth headers
46
+
All terminal communication happens over a single WebSocket connection at `/ws/panes`. This protocol supports:
47
+
-**Multiplexing** — multiple terminal panes over one connection
48
+
-**Binary framing** — efficient data transfer with minimal overhead
49
+
-**Buffer snapshots** — instant terminal state resume on reconnection
50
+
-**Real-time resizing** — automatic adjustment to mobile/web screen sizes
50
51
51
52
## Authentication flow
52
53
@@ -56,10 +57,8 @@ Mobile App
56
57
├─ API requests ──► Bearer token in Authorization header
57
58
│ Server validates against auth.secret
58
59
│
59
-
├─ ttyd HTML ──────► Loaded directly (basicAuthCredential in URL)
0 commit comments