spec: update spec

- new "p worker" command wrapping register/workers/default
- tmux session updates
This commit is contained in:
2026-05-20 09:44:33 +02:00
parent 235e99988a
commit 76fe691f0b

143
SPEC.md
View File

@@ -41,7 +41,14 @@ Communication happens over SSH port forwarding — no extra open ports needed.
p -- <command> p -- <command>
``` ```
Sync the current directory to the default worker and run `<command>` on it. Sync the current directory to the default worker and run `<command>` on it.
Attaches to the job's output by default. `Ctrl+C` detaches without killing the job. Attaches to the job's tmux session immediately. `Ctrl+B D` detaches without
killing the job. `Ctrl+C` sends SIGINT to the running process (standard behavior).
When the job finishes, the session stays open and displays:
```
--- Job done [exit 0]. Press any key to detach. ---
```
This lets the user read final output before returning to their shell.
``` ```
p <worker> -- <command> p <worker> -- <command>
@@ -65,7 +72,10 @@ command, status, duration. Style inspired by `docker ps` / `lxc list`.
``` ```
p attach <job-id> p attach <job-id>
``` ```
Re-attach to the console of a running job (via tmux). Supports partial IDs. Re-attach to the tmux session of a running job. Supports partial IDs.
Behaves identically to the initial attach: `Ctrl+B D` detaches, and if the job
has already finished the "press any key" screen is shown.
Only works on **running** jobs. For finished jobs, use `p logs`.
``` ```
p logs <job-id> p logs <job-id>
@@ -90,26 +100,33 @@ p rm <job-id>
Remove a job record and its remote work directory. Refuses to remove a Remove a job record and its remote work directory. Refuses to remove a
running job without `--force`. running job without `--force`.
### Workers ### Worker management
``` ```
p register [<name>] <connection-string> p worker register <connection-string> [-n <name>]
``` ```
Register a worker. The connection string is an SSH target (`user@host`, Register a worker. The connection string is an SSH target (`user@host`,
`user@host:port`, or an SSH config alias). If `<name>` is omitted, the `user@host:port`, or an SSH config alias). If `-n` is omitted, the hostname
hostname is used. The first registered worker becomes the default. is used as the name. The first registered worker becomes the default.
``` ```
p workers p worker ls
``` ```
List registered workers with their name, connection string, and reachability List registered workers with their name and connection string.
status. Pass `--check` / `-c` to also probe reachability over SSH (slow).
``` ```
p default <worker> p worker rm <name>
```
Unregister a worker. Refuses if the worker has running jobs.
```
p worker default <name>
``` ```
Set the default worker. Set the default worker.
---
## Directory Sync ## Directory Sync
- Uses `rsync` over SSH. - Uses `rsync` over SSH.
@@ -121,6 +138,63 @@ Set the default worker.
- No automatic sync-back after job completion. Use `p pull` to retrieve - No automatic sync-back after job completion. Use `p pull` to retrieve
specific artifacts. specific artifacts.
## Attach / Detach Mechanics
Jobs run inside a `tmux` session on the worker. `p` attaches to the session
immediately after starting the job.
### Status bar
The tmux session has a custom status bar showing:
```
p-<short-id> beefy make [running] 0:02:14
```
Fields: job short-ID, worker name, command (truncated), status, elapsed time.
### Key bindings while attached
| Key | Effect |
|---|---|
| `Ctrl+B D` | Detach from session. Job keeps running. |
| `Ctrl+C` | Sends SIGINT to the foreground process (standard terminal behavior). |
### On job completion
When the job's process exits, `run.sh` writes the exit code and then displays:
```
--- Job done [exit 0]. Press any key to detach. ---
```
The tmux session stays open (`remain-on-exit on` for the window) so the user
can scroll through final output. Pressing any key detaches the client and
returns to the local shell. `p` then reads the exit code and prints a summary.
### `p attach` on a finished job
If the job has already finished and the tmux session is still open (user has
not yet pressed a key), `p attach` reconnects to the "press any key" screen.
Once the key is pressed, the session closes. For a fully-closed session, use
`p logs` instead.
> **Worker requirements:** `tmux` and `rsync` must be available on the worker
> (standard on most Linux systems). The `p-agent` binary is auto-uploaded by `p`.
---
## Job Status & Notification
The **p-agent** runs as a lightweight background process on the worker
(started automatically, not a system service). It:
- Manages job launch and tmux session creation
- Tees output to `output.log`
- Writes `exitcode` on completion
- Notifies the client over the SSH reverse tunnel when a job finishes
The client maintains a local job database (`~/.local/share/p/jobs/<uuid>.json`)
mirroring job state. `p ls` reads from this local store (fast, no SSH),
updated in real time while attached, and via agent notifications otherwise.
### Degraded mode (agent unreachable / client was offline)
If the client missed a completion notification, `p ls` marks affected jobs as
`unknown`. The next `p ls` SSH-polls all workers with known-running jobs to
reconcile state.
## Worker-side Layout ## Worker-side Layout
All data lives under `~/.p/` on the worker (no root access required). All data lives under `~/.p/` on the worker (no root access required).
@@ -142,47 +216,13 @@ All data lives under `~/.p/` on the worker (no root access required).
<uuid>/ # rsync'd copy of client CWD for this job <uuid>/ # rsync'd copy of client CWD for this job
``` ```
## Attach / Detach Mechanics
Jobs run inside a `tmux` session on the worker (requirement: `tmux` must be
installed on the worker). Output is simultaneously captured to `output.log`
via `tmux pipe-pane` or a `tee` wrapper.
- `p attach <id>``ssh -t worker "tmux attach -t p-<id>"`
- `Ctrl+C` while attached → sends detach signal to tmux, **not** SIGINT to
the job. The job keeps running.
- `p attach` only works on **running** jobs. For finished jobs, use `p logs`.
> **Note:** `tmux` is the only required dependency on the worker beyond a
> standard POSIX environment. The `p-agent` binary and `rsync` are also
> required; `p` ensures the agent is present automatically. `rsync` must be
> available on the worker (standard on most Linux systems).
## Job Status & Notification
The **p-agent** runs as a lightweight background process on the worker
(started automatically, not a system service). It:
- Manages job launch and tmux session creation
- Tees output to `output.log`
- Writes `exitcode` on completion
- Notifies the client over the SSH reverse tunnel when a job finishes
The client maintains a local job database (`~/.local/share/p/jobs.db`,
SQLite) mirroring job state. `p ls` reads from this local DB (fast, no SSH),
updated in real time while attached, and via agent notifications otherwise.
### Degraded mode (agent unreachable / client was offline)
If the client missed a completion notification, `p ls` marks affected jobs as
`unknown`. Running the next `p ls` SSH-polls all
workers with known-running jobs to reconcile state.
## Configuration ## Configuration
File: `~/.config/p/config.yaml` File: `~/.config/p/config.yaml`
```yaml ```yaml
default_worker = "beefy" default_worker: beefy
workers: workers:
- name: beefy - name: beefy
connection: user@192.168.1.50 connection: user@192.168.1.50
@@ -194,9 +234,10 @@ workers:
``` ```
ID WORKER CWD COMMAND STATUS DURATION ID WORKER CWD COMMAND STATUS DURATION
a3f2 beefy ~/projects/foo make running 0:02:14 -------- ------ --------------- --------------- --------- --------
7c91 beefy ~/projects/bar cargo test done [0] 0:01:03 a3f2b091 beefy ~/projects/foo make running 0:02:14
b004 cloud ~/scripts ./bench.sh done [1] 0:00:47 7c91d302 beefy ~/projects/bar cargo test done [0] 0:01:03
b004f123 cloud ~/scripts ./bench.sh done [1] 0:00:47
``` ```
## Open Questions ## Open Questions
@@ -216,4 +257,8 @@ b004 cloud ~/scripts ./bench.sh done [1] 0:00:47
should prompt to clean up. should prompt to clean up.
- **Non-Linux workers**: tmux availability and path conventions may differ on - **Non-Linux workers**: tmux availability and path conventions may differ on
macOS workers. Out of scope for Phase 1. macOS workers. Out of scope for now.
- **Ctrl+C → detach** (future): it would be nicer if Ctrl+C detached the
session instead of sending SIGINT to the job, matching the spirit of the
tool. This requires per-session tmux key table configuration and is deferred.