diff --git a/README.md b/README.md index 322645a..6a3a677 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,12 @@ Press `Enter` to take control of a task, then `Ctrl-\` to return to the dashboar ![`fleetcom` attach](docs/img/attach.png) +### Custom groups + +Organize related tasks into named groups, even when they run in different directories. + +![`fleetcom` custom-group view](docs/img/groups.png) + ### Resume agent sessions Start `claude`, `codex`, or `grok` normally. When you rerun the task or reload a saved session, `fleetcom` resumes the same conversation automatically. @@ -53,48 +59,35 @@ For normal use, install the published crate from [crates.io](https://crates.io/c cargo install fleetcom ``` -### From source - -From the project root: - -- `cargo install --path .` to install `fleetcom` on `PATH`, or -- `cargo build --release` and run `target/release/fleetcom`. +[Source installation](docs/README.md#installation-from-source) covers builds from a repository clone. ## Usage -| Invocation | Behavior | -| -- | -- | -| `fleetcom` | Connect to the daemon, autostarting it when necessary, and open the dashboard | -| `fleetcom ` | Load a saved session, then open the dashboard | -| `fleetcom --foreground` | Run in-process without a daemon; tasks stop when the client quits | -| `fleetcom --scrollback ` | Set per-task scrollback (default 2,000); read at supervisor start, so a running daemon keeps its value until `--kill` | -| `fleetcom --kill` | Stop the daemon and every task it owns | -| `fleetcom --help` / `--version` | Print usage or version information and exit | +Connect to the daemon, autostarting it when necessary, and open the dashboard by invoking: -The first ordinary invocation starts the daemon when necessary. `--daemon` is an internal mode. +```sh +fleetcom +``` + +The [invocation reference](docs/commands.md#invocation) covers sessions, foreground mode, scrollback, and daemon shutdown. ## Key Commands ### Dashboard -| Key | Command | -| -- | -- | -| ↑ ↓ / `k` `j` | move the selection | -| `Enter` | attach to the selected task | -| `Space` | peek at the selected task | -| `n` | new command in the invocation directory | -| `@` | new command in a directory you pick (with completion) | -| `q` | disconnect; leave the daemon and tasks running | -| `Q` | quit; kill the tasks and stop the daemon | +The dashboard shows two short key hints; `?` opens an expanded key reference: + +```text + ❯ n run · @ dir · / find · s sort + ↑↓ select · enter attach · space peek · ? controls +``` ### Attached -| Key | Command | -| -- | -- | -| `Ctrl-\` | background the task and return to the dashboard | -| anything else | forwarded to the task's PTY | +- `Ctrl-\` backgrounds the task and returns to the dashboard. +- Other supported input is forwarded to the task's PTY. -[`docs/commands.md`](docs/commands.md) covers every key and launch flag, including the routing mechanics. +[`docs/commands.md`](docs/commands.md#dashboard) covers every key and launch flag, including the routing mechanics. ## How it works diff --git a/docs/README.md b/docs/README.md index eace472..8f3abe1 100644 --- a/docs/README.md +++ b/docs/README.md @@ -62,11 +62,11 @@ Run `fleetcom`. The first invocation starts the daemon and opens an empty dashbo ```text fleetcom 0 running · 0 idle · 0 done by state · dir · custom - ❯ n run · @ dir · / find · s sort · w save · o load - ↑↓ select · enter attach · space peek · m tag · g group · R rename · r rerun · X kill · q detach · Q quit + ❯ n run · @ dir · / find · s sort + ↑↓ select · enter attach · space peek · ? controls ``` -Press `n`, enter a command, and press `Enter`. The command runs in its own PTY and appears under Running. Repeat the process for a second command: +The hint rows cover common dashboard actions; `?` opens an expanded key reference. Press `n`, enter a command, and press `Enter`. The command runs in its own PTY and appears under Running. Repeat the process for a second command: ```text fleetcom 2 running · 0 idle · 0 done by state · dir · custom @@ -75,8 +75,8 @@ Press `n`, enter a command, and press `Enter`. The command runs in its own PTY a ✻ cargo watch -x test test result: ok. 42 passed 9s ✻ npm run dev VITE v5.0 ready in 312 ms 4s - ❯ n run · @ dir · / find · s sort · w save · o load - ↑↓ select · enter attach · space peek · m tag · g group · R rename · r rerun · X kill · q detach · Q quit + ❯ n run · @ dir · / find · s sort + ↑↓ select · enter attach · space peek · ? controls ``` Each row is `glyph · tag · command · latest output · age`. The age counts from the task's last meaningful edge: launch while running, last output once idle, exit once completed. `Space` peeks: a read-only box of the selected task's live screen, without leaving the dashboard: diff --git a/docs/commands.md b/docs/commands.md index 29df21e..cb101f7 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -29,15 +29,19 @@ | `/` | Jump the selection to a task by name, command, or group (opens the [find palette](#the--find-palette)) | | `s` | Cycle grouping: by state / by directory / by custom group | | `m` | Tag the selected task "in use" (toggles) | +| `M` | Select the next tagged task in dashboard order, wrapping at the end | | `g` | Assign the selected task to a group (opens the group picker) | | `R` | Rename the selected task: a display name shown in place of the command | | `r` | Rerun a finished task; supported agent tasks use the captured resume command | | `X` | Kill a running task (`TERM`, then `KILL` after 2 s), or remove a finished one | | `w` | Save the current tasks as a session | | `o` | Load a saved session or a recovery snapshot (opens the [session picker](#the-o-session-picker)) | -| `q` (or `Ctrl-C`) | Disconnect; leave the daemon and tasks running | +| `?` | Open the [controls overlay](#the--controls-overlay) | +| `q` (or `Ctrl-C`) | Disconnect from the daemon; under `--foreground`, quit and stop the tasks | | `Q` | Quit; kill the tasks and stop the daemon | +![`fleetcom` controls overlay](img/controls.png) + ### Status glyphs | Glyph | Meaning | @@ -128,6 +132,8 @@ Groups belong to task state: an assignment survives client detach and rerun (`r` `m` toggles the "in use" tag and marks the task with `◆`. In state mode, tagged tasks form the In use section at the top. In custom mode, a tag moves the task to the top of its existing group rather than creating a global section. Within a dir or custom section, tasks sort as tagged, live, then completed; each class then sorts by directory and spawn order. Idle state does not affect row order in these modes, so a quiet task keeps its position and shows `∙`. State mode instead moves quiet tasks from Running to Idle. +`M` cycles the selection through tagged tasks in dashboard order. It wraps after the last tagged task. With no tagged tasks, the selection does not move; with one, the selection moves to that task and stays there. + In custom mode only, a new command inherits the selected task's group, through both `n` and the `@` picker. The spawn prompt shows the destination as `❯ dir ▸ group ▸ command`, each segment present only when it applies: the dir segment for a non-default directory, the group segment when a group will be inherited. State- and dir-mode spawns start unassigned. #### Renaming @@ -142,11 +148,15 @@ The daemon removes control characters, trims surrounding whitespace, and limits `@` opens a bottom panel containing a path field and its matching directories. `Enter` depends on the selected row type: -- Current directory: run the command in that directory (`Enter`). -- Recent directories: ones you've launched in before; `Enter` runs there, `Tab`/`→` browses into them. -- Subdirectories of the current path: `Enter` or `Tab`/`→` descends into one. +- Resolved path: run the command in that directory (`Enter`). Row 0 is always this row, so the list is never empty. +- Current task directories: `Enter` runs there; `Tab`/`→` browses into them. These rows precede subdirectories. +- Subdirectories of the resolved path: `Enter` or `Tab`/`→` descends into one. + +Typing filters both lists under different rules. A subdirectory matches the fragment as a case-insensitive prefix. A current task directory matches a case-insensitive substring of its final path component: `log` finds `~/Documents/Code/Rust/Logria`, while `crab` finds both `crabapple` and `crabstep`. Parent components do not participate, so `doc` does not match every directory under `~/Documents/`. -Typing filters the rows; `Backspace` deletes one character and the matches re-filter; `↑`/`↓` move the highlight; `Esc` cancels. Completion updates on each input, permitting navigation and launch without leaving the dashboard. `←`/`→` move the caret within the typed path (`→` descends only when the caret is at the end), and `Ctrl-A`/`Ctrl-E` (or `Home`/`End`) jump to either end; the same caret keys work in every `fleetcom` text field. +Once the field contains `/`, current task directory rows are omitted; the picker shows the resolved path and its matching subdirectories. Without `/`, a current task directory that is also a matching subdirectory appears once, with the current task row behavior. + +`Backspace` deletes one character and the matches re-filter; `↑`/`↓` move the highlight; `Esc` cancels. Completion updates on each input, permitting navigation and launch without leaving the dashboard. `←`/`→` move the caret within the typed path (`→` descends only when the caret is at the end), and `Ctrl-A`/`Ctrl-E` (or `Home`/`End`) jump to either end; the same caret keys work in every `fleetcom` text field. ## The `/` find palette @@ -178,6 +188,16 @@ The daemon normalizes every group name received from the picker or a [session](s A recovery row reads ` ago · task(s) ·