Skip to content

Commit 9649012

Browse files
jakeyrgclaude
andcommitted
Switch dev sandbox from tmux to zellij
Replaces the tmux-based `min run dev` layout with zellij: a 2-pane session (Claude + interactive shell) plus a banner pane that prints the available `min run <task>` shortcuts. Adds a `fast-rs-debug` task, a sandbox-scoped CLAUDE.md, and expands the README dev section to cover the host/sandbox CLI naming split. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 5608e63 commit 9649012

8 files changed

Lines changed: 136 additions & 28 deletions

File tree

CLAUDE.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
2+
# You are in a Minimal execution environment
3+
4+
You are running in an isolated sandbox/execution-environment specialized for software development. This environment has access to a few specialized tools to help you accomplish your goals.
5+
These tools are all subcommands of the `min` command.
6+
7+
You will NOT be able to mutate the _host_ system with `apt-get`, `sudo pip install` etc, however you
8+
will be able to install additional commands using the `min add <packages>` command.
9+
10+
## Adding packages: `min add <package name>`
11+
12+
This command installs the package with the given name into your environment, letting you use the CLI tools or libraries it encapsulates.
13+
14+
Without any flags, `min add` installs the given package for this session only. If you are sure that it will
15+
always be needed as a build-time (i.e. tools needed during compilation) or runtime dependency (i.e. dynamic
16+
libraries), you can add `--build` or `--runtime` to the invocation to depend on the package permanently.
17+
18+
Help string for `min add`: min add [--session|--build|--runtime|--task <taskname>] <packages>
19+
20+
Examples:
21+
22+
* The `curl` utility is needed: `min add curl`
23+
* This project links against openssl: `min add --runtime openssl`
24+
* This project has a build step requiring the protobuf compiler: `min add --build openssl`
25+
26+
## Finding packages: `min search <search term>`
27+
28+
Performs a text search across all available packages, printing packages that match or partially match the given term. Use this to find the exact names of packages you need.
29+
30+
## Running tasks: `min run <task name>`
31+
32+
This command runs the specified task (declared in this project's `minimal.toml`) in a separate Minimal execution environment, streaming back the output.
33+
34+
Some typical tasks include `build` and `test`.

README.md

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ To compile a slim binary without the TUI:
6868

6969
## Building
7070

71+
From the host:
72+
7173
minimal run build
7274

7375
The release binary lands at `target/release/fastrs`. Or run directly:
@@ -76,15 +78,39 @@ The release binary lands at `target/release/fastrs`. Or run directly:
7678

7779
## Development
7880

79-
`minimal.toml` defines tasks that run inside the [Minimal](https://minimal.dev) sandbox with the toolchain pinned:
81+
This project is set up to build and run inside the [Minimal](https://minimal.dev) sandbox — the toolchain (`rust`, `gcc`, `binutils`, …) is pinned in `minimal.toml`, so no host install is required beyond the `minimal` CLI.
82+
83+
> **CLI naming:** on the host the binary is `minimal`. Once you're inside a sandbox (e.g. via `minimal run dev`) the same tool is exposed as `min`. The examples below use whichever name matches the context.
84+
85+
Tasks are defined in `minimal.toml`. From the host:
8086

81-
minimal run dev # interactive tmux session (Claude + shell)
87+
minimal run dev # interactive zellij dev session (Claude pane + shell pane)
88+
minimal run build # cargo build --release
89+
minimal run run # cargo run --release
90+
minimal run fast-rs-debug # cargo run --release with RUST_LOG=debug
8291
minimal run test # unit tests
8392
minimal run test-live # also run the live integration test against fast.com
8493
minimal run lint # cargo clippy --all-targets -- -D warnings
8594
minimal run fmt # cargo fmt
8695

87-
Without Minimal, the equivalent cargo commands (`cargo build --release`, `cargo test`, `cargo clippy --all-targets -- -D warnings`, `cargo fmt`) work too.
96+
From inside the sandbox shell, drop the `imal`:
97+
98+
min run test
99+
min run lint
100+
# etc.
101+
102+
### `minimal run dev`
103+
104+
Launches a [zellij](https://zellij.dev) layout (`zellij.kdl`) via `scripts/setup-dev.sh` with two panes:
105+
106+
- **left** — Claude Code (`claude --dangerously-skip-permissions`, only safe because the sandbox is ephemeral).
107+
- **right** — a bash shell that first runs `scripts/dev-shell.sh` (a quick cheat sheet of available `min run <task>` shortcuts) and then drops you into an interactive prompt.
108+
109+
The session is named `dev` and is reset on each invocation.
110+
111+
### Without Minimal
112+
113+
The equivalent cargo commands (`cargo build --release`, `cargo test`, `cargo clippy --all-targets -- -D warnings`, `cargo fmt`) work too.
88114

89115
CI runs `cargo test --lib`, `cargo fmt --check`, and `cargo clippy --all-targets -- -D warnings` on Linux/macOS/Windows. Tagged pushes (`v*`) build cross-platform release archives via `.github/workflows/release.yml`.
90116

minimal.toml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,14 @@ exec = "bash --noprofile -l"
2020
[tasks.claude]
2121
packages = ["base", "claude-code"]
2222
exec = "claude --dangerously-skip-permissions"
23+
patches.dir."~/.claude" = "read-write"
24+
patches.file."~/.claude.json" = "read-write"
2325

2426
[tasks.dev]
2527
interactive = true
26-
packages = ["claude-code", "base", "vim", "tmux", "ncurses", "fd", "fzf", "ripgrep", "git", "jq", "rust"]
28+
packages = ["claude-code", "base", "vim", "zellij", "fd", "fzf", "ripgrep", "git", "jq", "rust"]
2729
patches.dir."~/.claude" = "read-write"
30+
patches.file."~/.claude.json" = "read-write"
2831
patches.file."~/.gitconfig" = "read-only"
2932
patches.file."~/.vimrc" = "read-write"
3033
bash = "scripts/setup-dev.sh"
@@ -52,3 +55,7 @@ exec = "cargo fmt"
5255
[tasks.run]
5356
packages = ["base", "rust", "gcc", "binutils"]
5457
exec = "env RUSTFLAGS=-Clinker=gcc CC=gcc cargo run --release"
58+
59+
[tasks.fast-rs-debug]
60+
packages = ["base", "rust", "gcc", "binutils"]
61+
exec = "env RUSTFLAGS=-Clinker=gcc CC=gcc RUST_LOG=debug cargo run --release"

scripts/dev-shell.sh

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/usr/bin/env bash
2+
# Banner pane for `min run dev`. Prints the project label + task shortcuts,
3+
# then sleeps to keep the pane alive (the interactive shell lives in the
4+
# sibling pane below).
5+
6+
if [ -t 1 ]; then
7+
R=$'\e[0m' ; D=$'\e[2m' ; B=$'\e[1m'
8+
CY=$'\e[38;5;87m' # cyan — brand
9+
PK=$'\e[38;5;213m' # pink — section headers
10+
GY=$'\e[38;5;245m' # grey — chrome
11+
GR=$'\e[38;5;120m' # green — accent
12+
YL=$'\e[38;5;221m' # yellow — caution
13+
fi
14+
15+
cat <<EOF
16+
17+
${CY}█▀▀ ▄▀█ █▀ ▀█▀ █▀█ █▀${R} ${GR}${R} ${D}pure-Rust fast.com speed test${R}
18+
${CY}█▀ █▀█ ▄█ █ █▀▄ ▄█${R} ${D}you're inside the${R} ${B}Minimal${R} ${D}sandbox${R}
19+
${GY}────────────────────────────────────────────────────────${R}
20+
21+
${PK}▸ tasks${R} ${D}(each spawns a fresh sub-sandbox)${R}
22+
${B}min run build${R} ${D}cargo build --release${R}
23+
${B}min run run${R} ${D}cargo run --release${R}
24+
${B}min run fast-rs-debug${R} ${D}cargo run --release w/ RUST_LOG=debug${R}
25+
${B}min run test${R} ${D}cargo test${R}
26+
${B}min run test-live${R} ${D}cargo test -- --ignored${R} ${YL}(hits fast.com)${R}
27+
${B}min run lint${R} ${D}cargo clippy --all-targets -- -D warnings${R}
28+
${B}min run fmt${R} ${D}cargo fmt${R}
29+
30+
${PK}▸ sandbox${R}
31+
${B}min add${R} ${GY}<pkg>${R} ${D}install a package for this session${R}
32+
${B}min search${R} ${GY}<term>${R} ${D}find a package by name${R}
33+
34+
${GY}quit zellij: ${R}${B}Ctrl-q${R} ${GY}· detach: ${R}${B}Ctrl-o${R} ${GY}then${R} ${B}d${R}
35+
36+
EOF
37+
38+
exec sleep infinity

scripts/setup-dev.sh

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,15 @@ if [ "${IS_SANDBOX:-}" != "1" ]; then
1010
exit 1
1111
fi
1212

13-
tmux -f tmux.conf new-session -d -s dev
14-
tmux send-keys -t dev 'claude --dangerously-skip-permissions' Enter
15-
tmux split-window -t dev -h 'bash'
16-
tmux select-layout -t dev even-horizontal
17-
tmux select-pane -t dev:0.0
18-
tmux attach-session -t dev
13+
# The sandbox terminfo db has no xterm-ghostty entry, so `clear` (and any
14+
# other terminfo consumer) errors out. Override before zellij starts so
15+
# child panes inherit a known TERM.
16+
export TERM=xterm-256color
17+
18+
# Kill any prior `dev` session so each run starts from a clean layout.
19+
zellij delete-session --force dev 2>/dev/null || true
20+
21+
zellij --config zellij-config.kdl --layout zellij.kdl attach --create dev
22+
23+
# Wipe zellij's "Bye from Zellij!" trailer.
24+
clear

tmux.conf

Lines changed: 0 additions & 18 deletions
This file was deleted.

zellij-config.kdl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
show_startup_tips false
2+
show_release_notes false

zellij.kdl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
layout {
2+
pane split_direction="vertical" {
3+
pane focus=true name="claude" command="claude" {
4+
args "--dangerously-skip-permissions"
5+
}
6+
pane split_direction="horizontal" {
7+
pane size="35%" name="fastrs" command="scripts/dev-shell.sh"
8+
pane name="shell" command="bash" {
9+
args "--noprofile" "-l"
10+
}
11+
}
12+
}
13+
}

0 commit comments

Comments
 (0)