@microck/raft 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +13 -4
  2. package/deploy/build-image.py +4 -2
  3. package/deploy/verify-controls.py +5 -5
  4. package/deploy/verify-features.py +35 -2
  5. package/deploy/verify-jobs.py +264 -0
  6. package/deploy/verify-limits.py +20 -2
  7. package/deploy/verify-live.py +12 -3
  8. package/deploy/verify-output.py +208 -0
  9. package/deploy/verify-release.py +33 -4
  10. package/deploy/verify-run.py +571 -0
  11. package/deploy/verify-self-update.py +9 -1
  12. package/deploy/verify-sync.py +122 -0
  13. package/docs/benchmarks/read-latency-2026-10-29.json +70 -0
  14. package/docs/boat-capabilities.md +60 -7
  15. package/docs/boat-parity-design.md +1 -0
  16. package/docs/boot-performance.mdx +21 -0
  17. package/docs/contract.md +76 -2
  18. package/docs/first-box.mdx +22 -19
  19. package/docs/guides/background-jobs.mdx +38 -31
  20. package/docs/guides/backup-recovery.mdx +3 -2
  21. package/docs/guides/ci-jobs.mdx +209 -0
  22. package/docs/guides/files.mdx +2 -2
  23. package/docs/guides/index.mdx +31 -0
  24. package/docs/guides/long-running-services.mdx +1 -1
  25. package/docs/guides/meta.json +7 -2
  26. package/docs/guides/project-setup.mdx +1 -1
  27. package/docs/guides/scripting-ci.mdx +28 -9
  28. package/docs/guides/snapshots-forks.mdx +3 -1
  29. package/docs/guides/upgrades.mdx +7 -7
  30. package/docs/index.mdx +26 -28
  31. package/docs/maintainers/index.mdx +18 -0
  32. package/docs/maintainers/meta.json +12 -0
  33. package/docs/meta.json +5 -9
  34. package/docs/operations.mdx +7 -0
  35. package/docs/publishing.md +14 -4
  36. package/docs/reference/capacity.mdx +2 -1
  37. package/docs/reference/cli.md +85 -19
  38. package/docs/reference/meta.json +3 -1
  39. package/docs/releases/0.2.0.md +1 -0
  40. package/docs/releases/0.2.1.md +1 -0
  41. package/docs/releases/0.3.0.md +1 -0
  42. package/docs/releases/0.4.0.md +1 -0
  43. package/docs/releases/0.5.0.md +1 -0
  44. package/docs/releases/0.6.0.md +1 -0
  45. package/docs/releases/0.7.0.md +23 -0
  46. package/docs/releases/index.mdx +21 -0
  47. package/docs/releases/meta.json +15 -0
  48. package/docs/requirements.mdx +1 -1
  49. package/docs/reviews/docs-audit-2026-10-24.md +92 -0
  50. package/docs/reviews/performance-audit-2026-10-29.md +90 -0
  51. package/docs/site-development.md +1 -0
  52. package/docs/verification.mdx +21 -3
  53. package/package.json +3 -1
  54. package/raft.py +380 -179
  55. package/raft_files.py +13 -1
  56. package/raft_jobs.py +390 -0
  57. package/raft_output.py +166 -0
  58. package/raft_run.py +330 -0
  59. package/skills/raft-cli/SKILL.md +78 -197
@@ -9,7 +9,8 @@ Raft exports portable workspace archives and restores them onto compatible hosts
9
9
 
10
10
  ## Target workspace handle
11
11
 
12
- Commands in this guide require a stopped workspace:
12
+ Use a **persistent** workspace. Stop it before backup; stopping a disposable box
13
+ deletes it and its snapshots, so copy files out instead.
13
14
 
14
15
  ```sh title="CONTROLLER: Select and stop target workspace"
15
16
  raft list
@@ -35,7 +36,7 @@ Backup archives contain the entire guest filesystem, including credentials, SSH
35
36
 
36
37
  Raft enforces safeguards during export:
37
38
 
38
- - **Private permissions**: Destination mode must be `0600`. Group and world permissions must be zero before export begins.
39
+ - **Private permissions**: Raft creates the staged archive with mode `0600` and publishes it privately. Choose a new destination path; do not pre-create the file.
39
40
  - **Atomic link publication**: After export and `fsync`, Raft publishes the archive using `os.link(archive.name, destination)`. Hard-link support is checked at final publication rather than preflight; export can succeed while publication fails if the filesystem lacks hard-link support.
40
41
  - **No overwriting**: The destination file must not already exist.
41
42
  - **Lifecycle lock**: Export holds `/run/lock/raft-incus.lock`. Expiry checks for other containers on the host are delayed while the lock is held.
@@ -0,0 +1,209 @@
1
+ ---
2
+ title: Disposable CI jobs
3
+ description: Run trusted builds in temporary Raft boxes, collect results, and clean up with a bounded lifetime.
4
+ ---
5
+
6
+ # Disposable CI jobs
7
+
8
+ `raft run` runs one foreground command in a fresh disposable box. It creates the
9
+ box, waits for command readiness, optionally uploads source, streams command
10
+ output, collects requested result directories, and attempts ownership-checked
11
+ cleanup even after failure or cancellation. It does not register a GitHub
12
+ self-hosted runner or replace your CI scheduler.
13
+
14
+ <Callout type="warn" title="Unreleased: requires the 0.7.0 development code">
15
+ The published release is 0.6.0, which does not include `raft run`. As checked on
16
+ 2026-10-24, no 0.7.0 npm package or GitHub release assets are available. Use the
17
+ [stable scripting workflow](./scripting-ci.mdx) unless you intend to test a reviewed
18
+ source revision. Do not install a nonexistent 0.7.0 package.
19
+ </Callout>
20
+
21
+ For development, run `python3 /path/to/raft.py run` from the reviewed checkout.
22
+ The CI example below pins the full source commit instead of an unpublished tag.
23
+
24
+ ## Trust boundary
25
+
26
+ Use dedicated hosts and trusted jobs only. The controller's SSH identity has
27
+ passwordless sudo and controls the host; it is not a scoped, per-job CI token.
28
+ Boxes are unprivileged Incus containers sharing the host kernel, not separate
29
+ kernel VMs. Do not expose this identity to unreviewed pull requests, fork jobs,
30
+ or a `pull_request_target` workflow that checks out attacker-controlled code.
31
+
32
+ Raft does not install or register a runner, configure repository secrets, forward
33
+ your SSH agent, copy controller environment variables, or buy cloud capacity.
34
+ The operator must approve and configure existing host access separately. Never
35
+ copy a host private key or a GitHub token into the guest.
36
+
37
+ ## One command
38
+
39
+ ```sh title="CONTROLLER: Git working tree"
40
+ RAFT_NO_UPDATE_CHECK=1 raft run \
41
+ --location lab --timeout 600 --cpu 2 --memory 4GiB \
42
+ --purpose "Project tests" --owner "Local CI" --next "Delete after collection" \
43
+ --push . --pull /workspace/project/reports ./ci-reports \
44
+ -- bash -lc 'set -euo pipefail; mkdir -p reports; npm ci; npm test 2>&1 | tee reports/test.log'
45
+ ```
46
+
47
+ The controller needs Linux, Python 3.11.8+, OpenSSH, Git for `--push`, a configured
48
+ Raft location, verified SSH host keys, batch authentication, and the current host
49
+ expiry worker. Ordinary image/host sizing and note policies still apply. `run`
50
+ always forces disposable behavior, regardless of controller lifetime defaults.
51
+ It never retries the payload command.
52
+
53
+ - stdout/stderr stream the payload; lifecycle messages and elapsed time go to
54
+ stderr. There is no cost estimate or JSON result protocol.
55
+ - `--timeout` is one total deadline for Git filtering, creation, readiness, upload
56
+ and execution, not a fresh timeout for each step. Default: 600 seconds; range:
57
+ 1 to 2,591,880 seconds.
58
+ - `--push` includes tracked and unignored untracked files from the chosen Git
59
+ working tree, including working-tree edits. It excludes `.git` at every level
60
+ and refuses submodules. Tracked files remain included even if ignored later:
61
+ this is not a secret scanner. Deleted tracked files are absent.
62
+ - `--push-all` explicitly copies the complete directory, including hidden and
63
+ ignored files and Git metadata. Inspect it for credentials first. This is the
64
+ opt-in alternative for non-Git or explicitly staged trees; it is not a silent
65
+ fallback when Git fails.
66
+ - Uploads default to `/workspace/project`; without an upload, commands default
67
+ to `/workspace`. `--cwd` overrides this. An upload destination must not exist,
68
+ and its parent must already exist. Raft never merges into a stale checkout.
69
+ - Repeat `--pull GUEST_DIRECTORY NEW_LOCAL_DIRECTORY` to collect directories,
70
+ including after a failing payload. Local parents must exist; destinations
71
+ must be new, including no existing symlinks. Files can be placed in a result
72
+ directory. Collection happens before deletion, with a shared 30-second grace.
73
+ A failed pull does not stop later pulls unless that grace has expired.
74
+ - Exit status preserves a failing payload, including signal-style statuses.
75
+ Job timeout returns 124, Ctrl-C 130, SIGTERM 143. Setup/collection/cleanup
76
+ failure returns 1 when there is no earlier failing status. A successful
77
+ payload is not reported successful when cleanup cannot be confirmed.
78
+
79
+ The host receives a unique ownership marker and a fixed expiry of timeout + 120
80
+ seconds as part of creation, before startup. Cleanup checks ownership under the
81
+ host lifecycle lock and has a separate 30-second grace. Repeated cancellation is
82
+ ignored during these bounded collection/cleanup attempts. No lease renewal or
83
+ `--keep` mode is implemented.
84
+
85
+ If creation was not acknowledged, cleanup first records that run's cancellation
86
+ under the same host lifecycle lock. Creation checks that record before allocating,
87
+ so a queued SSH request cannot start the box after cleanup has confirmed absence.
88
+ These empty per-run records live in the root-only `/run/raft-ci-cancelled`
89
+ directory, use no-follow operations, and remain until host reboot, when queued
90
+ processes also disappear. Ordinary acknowledged runs leave no cancellation file.
91
+
92
+ If the controller is killed before cleanup, SSH is lost, or cleanup fails, inspect
93
+ the exact handle printed on stderr. A disconnected create may still finish when
94
+ cancellation could not be recorded. The disposable expiry worker is a backstop,
95
+ not a guarantee of instantaneous deletion: an unreachable host, stopped worker or
96
+ held lifecycle lock can delay it. Do not blindly rerun an uncertain job or assume
97
+ its side effects were rolled back.
98
+
99
+ ## Prepared templates instead of shared mutable caches
100
+
101
+ Prepare dependencies and tool versions in a persistent base box, stop it, then
102
+ create a named snapshot. See [project setup](./project-setup.mdx) and
103
+ [snapshots](./snapshots-forks.mdx). Keep the source box and snapshot available:
104
+
105
+ ```sh title="CONTROLLER: Use an existing trusted snapshot"
106
+ raft run --from lab:rf-REPLACE_WITH_BASE_ID/ci-base --timeout 900 \
107
+ --purpose "Cached build" --owner "CI" --next "Delete after tests" \
108
+ --push . -- bash -lc 'npm ci --prefer-offline && npm test'
109
+ ```
110
+
111
+ The template stays on its source host and retains its size unless explicitly
112
+ overridden. Put reusable caches outside the upload destination, which must be
113
+ new. Each job gets an independent copy; its mutations do not update the template
114
+ or another job's cache. Refresh templates deliberately when dependencies change.
115
+
116
+ Raft snapshots retain filesystem contents, including credentials and Docker
117
+ storage. They do not save process memory. Inspect and sanitize the base before
118
+ sharing it with jobs. Do not assume Boat's selective snapshot/cache rules apply
119
+ to Raft's whole-filesystem copies.
120
+
121
+ ## GitHub Actions orchestration example
122
+
123
+ The following is an example for a separate trusted project, not a change to
124
+ Raft's own runner fleet. An ordinary `ubuntu-latest` job invokes Raft over SSH.
125
+ Before using it, an operator must approve storing a dedicated CI host key as
126
+ `RAFT_SSH_KEY`, verified host-key lines as `RAFT_KNOWN_HOSTS`, and the location
127
+ inventory JSON as `RAFT_INVENTORY`. The inventory's SSH target must use that key
128
+ and its image fingerprint must be pinned. Never generate trust with an unchecked
129
+ `ssh-keyscan` or disable host-key checking. Restrict access to these secrets.
130
+
131
+ The example pins development commit `7d678bb079a9b2dcde4e2eb9e4cd0468d00f50f3` in a
132
+ separate Python environment. Review that code and its unreleased status
133
+ before use; do not silently replace it with a moving branch.
134
+
135
+ ```yaml title="EXAMPLE: .github/workflows/trusted-build.yml"
136
+ name: Trusted Raft build
137
+ on:
138
+ push:
139
+ branches: [main]
140
+ workflow_dispatch:
141
+ permissions:
142
+ contents: read
143
+ jobs:
144
+ test:
145
+ runs-on: ubuntu-latest
146
+ timeout-minutes: 20
147
+ env:
148
+ RAFT_NO_UPDATE_CHECK: '1'
149
+ steps:
150
+ - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262
151
+ with:
152
+ persist-credentials: false
153
+ - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065
154
+ with:
155
+ python-version: '3.14'
156
+ - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
157
+ with:
158
+ node-version: '24'
159
+ - name: Install reviewed development controller
160
+ run: |
161
+ python -m venv "$RUNNER_TEMP/raft-cli"
162
+ "$RUNNER_TEMP/raft-cli/bin/pip" install "git+https://github.com/Microck/raft.git@7d678bb079a9b2dcde4e2eb9e4cd0468d00f50f3"
163
+ echo "$RUNNER_TEMP/raft-cli/bin" >> "$GITHUB_PATH"
164
+ - name: Configure approved existing access
165
+ env:
166
+ SSH_KEY: ${{ secrets.RAFT_SSH_KEY }}
167
+ KNOWN_HOSTS: ${{ secrets.RAFT_KNOWN_HOSTS }}
168
+ INVENTORY: ${{ secrets.RAFT_INVENTORY }}
169
+ run: |
170
+ umask 077
171
+ mkdir -p ~/.ssh ~/.config/raft
172
+ printf '%s\n' "$SSH_KEY" > ~/.ssh/id_ed25519
173
+ printf '%s\n' "$KNOWN_HOSTS" > ~/.ssh/known_hosts
174
+ printf '%s\n' "$INVENTORY" > ~/.config/raft/incus.json
175
+ printf 'Host *\n BatchMode yes\n StrictHostKeyChecking yes\n IdentitiesOnly yes\n' > ~/.ssh/config
176
+ - name: Run remote tests and collect logs
177
+ run: |
178
+ raft run --location ci --timeout 900 --cpu 2 --memory 4GiB \
179
+ --purpose "Trusted project tests" --owner "GitHub Actions" --next "Delete after tests" \
180
+ --push . --pull /workspace/project/reports ./ci-reports \
181
+ -- bash -lc 'set -euo pipefail; mkdir -p reports; npm ci; npm test 2>&1 | tee reports/test.log'
182
+ - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
183
+ if: always()
184
+ with:
185
+ name: test-reports
186
+ path: ci-reports/
187
+ if-no-files-found: warn
188
+ ```
189
+
190
+ No checkout credential is needed in the guest. The secret files are outside the
191
+ uploaded tree, and `.git` is excluded. Set a CI job limit longer than Raft's
192
+ command deadline plus collection and cleanup grace. A forcibly terminated CI
193
+ runner cannot perform final cleanup; check the host expiry service and inventory.
194
+
195
+ ## Comparison and cost
196
+
197
+ [Boat's CI guide](https://docs.boat.dev/ci) uses the same broad pattern: an existing
198
+ CI job orchestrates a disposable remote workspace. Boat also provides a managed
199
+ `run` command, scoped API keys, renewable leases and a different VM/snapshot
200
+ model. Raft implements a fixed lifetime on operator-owned Incus hosts and uses
201
+ host-level SSH access; these are meaningful differences, not interchangeable
202
+ security or billing guarantees.
203
+
204
+ There is no universal “10x cheaper” claim for Raft. Compare the complete host,
205
+ storage, idle capacity, operations and orchestration-runner cost. Standard
206
+ GitHub-hosted runners are already free for public repositories; remote capacity
207
+ can still help with specific hardware, prepared environments or isolation from
208
+ other trusted jobs. See [Boat pricing](https://docs.boat.dev/pricing) and
209
+ [GitHub Actions billing](https://docs.github.com/en/billing/concepts/product-billing/github-actions).
@@ -5,11 +5,11 @@ description: Transfer files between your controller machine and running Raft wor
5
5
 
6
6
  # File transfer
7
7
 
8
- Upload and download individual files between your local controller and running workspaces over verified host SSH and Incus instance APIs.
8
+ Upload and download individual files between your controller and a box over verified host SSH and Incus instance APIs.
9
9
 
10
10
  ## Target workspace handle
11
11
 
12
- Commands in this guide target a running workspace. Select one from `raft list` (see [First working box](../first-box.mdx)):
12
+ Use a running box for all examples below. Individual-file transfers also work while stopped; recursive directory transfers require a running box. Select one from `raft list` (see [First working box](../first-box.mdx)):
13
13
 
14
14
  ```sh title="CONTROLLER: Select running workspace"
15
15
  raft list
@@ -0,0 +1,31 @@
1
+ ---
2
+ title: Task guides
3
+ description: Pick a workflow after setting up your first Raft host.
4
+ ---
5
+
6
+ # Task guides
7
+
8
+ Start with [your first box](../first-box.mdx) if you have not run a command yet.
9
+ Commands run on the controller unless a block is labeled **HOST**.
10
+
11
+ ## Develop
12
+
13
+ - [Project setup and templates](./project-setup.mdx): upload a project and reuse dependencies.
14
+ - [Docker](./docker.mdx): build images and manage guest disk use.
15
+ - [File transfer](./files.mdx): copy individual files or directory trees.
16
+ - [Desktop and private services](./desktop-services.mdx): open a browser, desktop or local tunnel.
17
+
18
+ ## Automate
19
+
20
+ - [Background jobs](./background-jobs.mdx): detach, inspect logs and cancel.
21
+ - [Lifetime and persistent services](./long-running-services.mdx): set deadlines and restart services after resume.
22
+ - [Scripting and CI](./scripting-ci.mdx): parse output and handle failures.
23
+ - [Disposable CI jobs — unreleased 0.7.0](./ci-jobs.mdx): run and clean up one temporary build.
24
+
25
+ ## Operate
26
+
27
+ - [Snapshots and forks](./snapshots-forks.mdx): save disk state or make a same-host copy.
28
+ - [Backup and recovery](./backup-recovery.mdx): move a whole box to a compatible host.
29
+ - [Defaults and policies](./config-policy.mdx): set creation defaults and retention rules.
30
+ - [Upgrades](./upgrades.mdx): update the CLI, host worker and image separately.
31
+ - [Troubleshooting](./troubleshooting.mdx): start from a symptom.
@@ -11,7 +11,7 @@ terminal, and detached jobs do not extend that deadline automatically.
11
11
  ## Choose a lifetime and retention policy
12
12
 
13
13
  ```sh title="CONTROLLER: Create a persistent box"
14
- box=$(raft new --location lab --ttl 3600)
14
+ box=$(raft new --location lab --ttl 3600 --persistent)
15
15
  ```
16
16
 
17
17
  TTL is in seconds: 60 to 2,592,000 (30 days), with a creation default of 600.
@@ -3,16 +3,21 @@
3
3
  "collapsible": true,
4
4
  "defaultOpen": false,
5
5
  "pages": [
6
+ "index",
7
+ "---Develop---",
6
8
  "project-setup",
7
9
  "docker",
8
10
  "files",
11
+ "desktop-services",
12
+ "---Automate---",
9
13
  "background-jobs",
10
14
  "long-running-services",
11
15
  "scripting-ci",
12
- "config-policy",
13
- "desktop-services",
16
+ "ci-jobs",
17
+ "---Operate---",
14
18
  "snapshots-forks",
15
19
  "backup-recovery",
20
+ "config-policy",
16
21
  "upgrades",
17
22
  "troubleshooting"
18
23
  ]
@@ -15,7 +15,7 @@ service. Commands run as guest root in `/workspace` unless you choose another us
15
15
  Create a persistent box after [host setup](../operations.mdx):
16
16
 
17
17
  ```sh title="CONTROLLER: Create a project box"
18
- box=$(raft new --location lab --ttl 3600)
18
+ box=$(raft new --location lab --ttl 3600 --persistent)
19
19
  ```
20
20
 
21
21
  Upload a local project, excluding credentials and files you do not want copied.
@@ -11,9 +11,28 @@ authentication, and hosts with passwordless sudo. No Raft HTTP API, SDK, or API
11
11
  exists. Give access only to trusted jobs: the configured SSH account has host sudo
12
12
  and controls all boxes on that host.
13
13
 
14
+ For one-shot builds, [`raft run`](./ci-jobs.mdx) combines allocation, source upload,
15
+ foreground execution, artifact collection and disposable cleanup. It is an
16
+ orchestration command, not a registered CI runner. The manual lifecycle examples
17
+ below remain useful for persistent debugging workflows.
18
+
14
19
  ## Output formats
15
20
 
16
- Raft does not have a global `--json` option. Parse each command's actual format:
21
+ The development CLI supports `raft --json COMMAND ...` for JSON Lines output.
22
+ Each event has a `type`: `data` carries a structured `value`; `stdout` and
23
+ `stderr` carry base64-encoded bytes in `data`; `error` carries `code` and
24
+ `message`; the final `exit` carries the process exit `code`. Decode stream events
25
+ in order within each channel. Chunks need not end at line boundaries. This keeps
26
+ binary output intact and streams long-running command output without buffering
27
+ it all. Interactive `ssh`, `forward` and `desktop` reject JSON mode before acting.
28
+ Help/version work without configuration. JSON mode suppresses release notices.
29
+
30
+ ```sh
31
+ raft --json list --location lab | jq 'select(.type == "data") | .value'
32
+ raft --json exec "$BOX" -- sh -c 'echo hello; exit 7'
33
+ ```
34
+
35
+ Without global `--json`, parse each command's format:
17
36
 
18
37
  | Command | stdout |
19
38
  | --- | --- |
@@ -27,9 +46,9 @@ Raft does not have a global `--json` option. Parse each command's actual format:
27
46
  | `config` | One pretty-printed JSON object with `file`, `defaults`, `policy` |
28
47
  | `config set/unset`, `policy` | One line describing the change |
29
48
  | `prune` | JSONL candidates or deleted records with `box`, `action` |
30
- | `status` | systemd `ActiveState`, `SubState`, `ExecMainStatus` property lines |
31
- | `logs` | Guest journal text |
32
- | `exec` | Payload stdout/stderr |
49
+ | `status` | Retained JSON record with `state`, `exitCode`, timestamps and `droppedBytes` |
50
+ | `logs` | First 1 MiB of retained combined output |
51
+ | `exec`, `run` | Payload stdout/stderr; `run` lifecycle diagnostics use stderr |
33
52
  | Other inspection/maintenance commands | Human-readable text or no output |
34
53
 
35
54
  `list` emits nothing when there are no boxes. `stopAt` is the host Unix deadline
@@ -79,10 +98,10 @@ stderr.
79
98
 
80
99
  SSH transport failures may return SSH's status rather than the payload's result.
81
100
  The foreground tunnel replaces the CLI process with SSH and uses SSH's exit code.
82
- A zero exit from `status` means the query succeeded; read `ExecMainStatus` for the
83
- job result and `ActiveState`/`SubState` for whether it finished. Do not interpret a
84
- running job's initial `ExecMainStatus=0` as completion. See
85
- [Background jobs](./background-jobs.mdx).
101
+ A zero exit from `status` means the query succeeded. Wait for a terminal `state`
102
+ and read `exitCode`; running, cancelled and interrupted jobs have no confirmed
103
+ payload exit code. Results remain readable after stop or deletion for seven days.
104
+ See [Background jobs](./background-jobs.mdx).
86
105
 
87
106
  ## Create, wait, run, and stop
88
107
 
@@ -108,7 +127,7 @@ cleanup() {
108
127
  }
109
128
  trap cleanup EXIT
110
129
 
111
- box=$(raft new --location lab --ttl 3600)
130
+ box=$(raft new --location lab --ttl 3600 --persistent)
112
131
  printf 'Created %s\n' "$box" >&2
113
132
  ready=false
114
133
  for attempt in {1..30}; do
@@ -9,7 +9,8 @@ Raft captures filesystem snapshots, rolls back changes, and clones workspaces on
9
9
 
10
10
  ## Target workspace handle
11
11
 
12
- Commands in this guide require a stopped workspace:
12
+ Use a **persistent** workspace and stop it first. Stopping a disposable box deletes
13
+ it and its snapshots; do not use one as the source for this walkthrough.
13
14
 
14
15
  ```sh title="CONTROLLER: Select and stop target workspace"
15
16
  raft list
@@ -66,6 +67,7 @@ raft resume "$box" --ttl 600
66
67
  Forking creates an independent clone on the same host:
67
68
 
68
69
  ```sh title="CONTROLLER: Fork workspace into a new clone"
70
+ raft stop "$box" # Use a persistent box; stop deletes disposable boxes
69
71
  copy=$(raft fork "$box" --ttl 600)
70
72
  echo "Created fork: $copy"
71
73
  ```
@@ -17,7 +17,7 @@ parts of Raft. Updating one does not automatically update the others.
17
17
  ## Choose a release and prepare
18
18
 
19
19
  Review [release notes](https://github.com/Microck/raft/releases) and use matching
20
- CLI and deployment sources. The examples below pin `v0.2.0`; replace that version
20
+ CLI and deployment sources. The examples below pin `v0.6.0`; replace that version
21
21
  consistently when adopting another release.
22
22
 
23
23
  ```sh title="CONTROLLER: Inspect the current installation"
@@ -34,7 +34,7 @@ stopping one. Schedule redeployment when interruptions are acceptable.
34
34
  ## Update the controller
35
35
 
36
36
  `raft self-update` installs the latest release through the channel that
37
- installed the CLI, and `raft self-update --version 0.2.0` installs a chosen
37
+ installed the CLI, and `raft self-update --version 0.6.0` installs a chosen
38
38
  one. `raft self-update --check` only reports. For npm installs, npm checks the
39
39
  registry integrity hash of a package published with provenance. For uv tools,
40
40
  Raft downloads the release wheel and refuses it unless its SHA-256 matches the
@@ -43,7 +43,7 @@ release `SHA256SUMS`. See [`self-update`](../reference/cli.md#self-update).
43
43
  To install a release by hand instead, for an npm installation:
44
44
 
45
45
  ```sh title="CONTROLLER: Install a pinned CLI release"
46
- npm install -g @microck/raft@0.2.0
46
+ npm install -g @microck/raft@0.6.0
47
47
  raft --version
48
48
  ```
49
49
 
@@ -52,7 +52,7 @@ release, verify the checksum, then install it with `uv`:
52
52
 
53
53
  ```sh title="CONTROLLER: Install a verified release wheel instead of npm"
54
54
  sha256sum --ignore-missing -c SHA256SUMS
55
- uv tool install --force ./raft-0.2.0-py3-none-any.whl
55
+ uv tool install --force ./raft-0.6.0-py3-none-any.whl
56
56
  raft --version
57
57
  ```
58
58
 
@@ -71,8 +71,8 @@ reports each host whose worker differs from the new CLI.
71
71
  Obtain a separate checkout of the matching release:
72
72
 
73
73
  ```sh title="CONTROLLER: Obtain and deploy matching host code"
74
- git clone --branch v0.2.0 https://github.com/Microck/raft.git raft-v0.2.0
75
- cd raft-v0.2.0
74
+ git clone --branch v0.6.0 https://github.com/Microck/raft.git raft-v0.6.0
75
+ cd raft-v0.6.0
76
76
  python3 deploy/deploy.py --location lab
77
77
  raft doctor
78
78
  ```
@@ -105,7 +105,7 @@ backup's guest filesystem rather than rebuilding it from the new image.
105
105
  ## Verify the update
106
106
 
107
107
  ```sh title="CONTROLLER: Smoke-check a new persistent box"
108
- box=$(raft new --location lab --ttl 600)
108
+ box=$(raft new --location lab --ttl 600 --persistent)
109
109
  raft exec "$box" -- node --version
110
110
  raft exec "$box" -- docker info
111
111
  raft stop "$box"
package/docs/index.mdx CHANGED
@@ -1,41 +1,39 @@
1
1
  ---
2
2
  title: Overview
3
- description: Persistent Linux workspaces powered by Incus.
3
+ description: Create persistent Linux development boxes on Ubuntu hosts you control.
4
4
  ---
5
5
 
6
6
  # Raft
7
7
 
8
- Raft is an independent, self-hosted open-source alternative to [boat.dev](https://boat.dev).
9
- It provides persistent Linux workspaces on ARM64 and AMD64 hardware,
10
- supporting command execution, Docker, file transfer, snapshots, forks, and desktop access.
11
- Raft is not affiliated with Boat.
8
+ Raft creates **persistent Linux boxes on your own Ubuntu hosts**. Run commands,
9
+ Docker builds and development services; copy files; save snapshots; or open a
10
+ private desktop. A box is an unprivileged Incus container that shares its host's
11
+ kernel, not a virtual machine.
12
12
 
13
- ## Getting started
13
+ ## Start here
14
14
 
15
- Read [System requirements](./requirements.mdx), follow [Installation and host setup](./operations.mdx), and create your [First working box](./first-box.mdx).
15
+ 1. [Check requirements](./requirements.mdx): a Linux controller and a dedicated Ubuntu host.
16
+ 2. [Set up a host](./operations.mdx): install the CLI and run guided onboarding.
17
+ 3. [Create your first box](./first-box.mdx): run a command, stop it and resume it.
16
18
 
17
- ```sh title="CONTROLLER: Create and use a workspace"
18
- box=$(raft new --location lab --ttl 600)
19
+ Already have a configured host? Run these commands on your **controller**
20
+ (the machine where you installed `raft`). Replace `lab` with your location:
21
+
22
+ ```sh
23
+ box=$(raft new --location lab --ttl 600 --persistent)
19
24
  raft exec "$box" -- node --version
20
25
  raft ssh "$box"
21
- raft stop "$box"
22
26
  ```
23
27
 
24
- Stopping a workspace preserves files and packages on disk. Resuming resets its running lifetime.
25
-
26
- ## Task guides
27
-
28
- | Task | Guide |
29
- | :--- | :--- |
30
- | Prepare a project and reuse its installed dependencies | [Project setup and templates](./guides/project-setup.mdx) |
31
- | Run nested containers and build images | [Docker in workspaces](./guides/docker.mdx) |
32
- | Transfer files between controller and workspace | [File transfer](./guides/files.mdx) |
33
- | Run detached commands with systemd logs | [Background jobs](./guides/background-jobs.mdx) |
34
- | Manage deadlines and restart services after resume | [Lifetime and persistent services](./guides/long-running-services.mdx) |
35
- | Automate the CLI and parse its output | [Scripting and CI](./guides/scripting-ci.mdx) |
36
- | Set defaults for new boxes, require box note fields or delete boxes left stopped | [Defaults and host policies](./guides/config-policy.mdx) |
37
- | Forward guest ports or open noVNC desktop | [Desktop and private services](./guides/desktop-services.mdx) |
38
- | Capture disk state or clone workspaces | [Snapshots and forks](./guides/snapshots-forks.mdx) |
39
- | Export portable backups across hosts | [Backup and recovery](./guides/backup-recovery.mdx) |
40
- | Update the CLI, host worker, and workspace image | [Upgrades and image changes](./guides/upgrades.mdx) |
41
- | Inspect host services and diagnose errors | [Troubleshooting](./guides/troubleshooting.mdx) |
28
+ Exit the guest shell, then run `raft stop "$box"` on the controller. Files remain;
29
+ processes stop. Host retention policies can later delete stopped boxes.
30
+
31
+ ## Find a task
32
+
33
+ - [Work with a project](./guides/project-setup.mdx) or [copy files](./guides/files.mdx).
34
+ - [Run Docker](./guides/docker.mdx), [background jobs](./guides/background-jobs.mdx), or [open a desktop](./guides/desktop-services.mdx).
35
+ - [Browse all guides](./guides/index.mdx), [look up a command](./reference/cli.md), or [troubleshoot](./guides/troubleshooting.mdx).
36
+
37
+ Raft is an independent open-source alternative to Boat, not affiliated with it.
38
+ [Compare the trade-offs](./boat-capabilities.md). Setup examples target published
39
+ **0.6.0**; [0.7.0 features](./releases/0.7.0.md) are marked unreleased.
@@ -0,0 +1,18 @@
1
+ ---
2
+ title: Maintain Raft
3
+ description: Design, verification, release and documentation work for Raft contributors.
4
+ ---
5
+
6
+ # Maintain Raft
7
+
8
+ These pages are for changing or releasing Raft, not for creating your first box.
9
+ For everyday use, start with [host setup](../operations.mdx) or the [task guides](../guides/index.mdx).
10
+
11
+ - [Design decisions](../boat-parity-design.md): why Raft uses Incus and host SSH.
12
+ - [Runtime contract](../contract.md): behavior that implementations must preserve.
13
+ - [Verification](../verification.mdx): test commands, evidence and unverified boundaries.
14
+ - [Publishing](../publishing.md): package and image release gates.
15
+ - [Documentation site](../site-development.md): edit, preview and check these docs.
16
+
17
+ Host tests create and delete real workspaces. Read each suite's effects before
18
+ running it, and use dedicated infrastructure you are authorized to change.
@@ -0,0 +1,12 @@
1
+ {
2
+ "title": "Maintainers",
3
+ "collapsible": true,
4
+ "defaultOpen": false,
5
+ "pages": [
6
+ "index",
7
+ "[Design decisions](/docs/boat-parity-design/)",
8
+ "[Verification](/docs/verification/)",
9
+ "[Publishing](/docs/publishing/)",
10
+ "[Documentation site](/docs/site-development/)"
11
+ ]
12
+ }
package/docs/meta.json CHANGED
@@ -2,20 +2,16 @@
2
2
  "title": "Raft",
3
3
  "pages": [
4
4
  "index",
5
- "---Start here---",
5
+ "---Get started---",
6
6
  "requirements",
7
7
  "operations",
8
8
  "first-box",
9
+ "---Use Raft---",
9
10
  "guides",
10
11
  "reference",
11
- "contract",
12
- "---Comparison---",
12
+ "---About---",
13
13
  "boat-capabilities",
14
- "boot-performance",
15
- "---Contributing---",
16
- "boat-parity-design",
17
- "verification",
18
- "publishing",
19
- "site-development"
14
+ "maintainers",
15
+ "releases"
20
16
  ]
21
17
  }
@@ -7,6 +7,8 @@ description: Install the Raft controller CLI, provision a dedicated host, and ac
7
7
 
8
8
  Set up a dedicated Ubuntu host, install the Raft CLI, provision Incus, acquire a workspace image, and verify readiness.
9
9
 
10
+ Examples pin published **0.6.0**. Use matching CLI, deployment scripts and image assets.
11
+
10
12
  Review prerequisites in [System requirements](./requirements.mdx) before starting.
11
13
 
12
14
  ## Guided onboarding
@@ -30,6 +32,9 @@ that instead. See [`host add`](./reference/cli.md#host-add) for image options.
30
32
 
31
33
  ## Manual setup
32
34
 
35
+ <details>
36
+ <summary>Advanced: provision each component yourself instead of using host add</summary>
37
+
33
38
  The steps below are what `raft host add` automates. Follow them to inspect or
34
39
  customize each stage.
35
40
 
@@ -258,6 +263,8 @@ Check that Incus, the network service, and the expiration timer are active. For
258
263
 
259
264
  </Steps>
260
265
 
266
+ </details>
267
+
261
268
  ## Next step
262
269
 
263
270
  Proceed to [First working box](./first-box.mdx) to launch, verify, and manage your first workspace.