feat: make nix develop the default toolchain path

User ruling: agents must work inside nix develop (or direnv) for this repo.
Bare system cargo that fails edition2024 is a misconfigured session.

Changes:

1. scripts/agent-bootstrap.sh:
   - Added section 0: seed nix flake inputs automatically
   - Cargo warm now runs inside 'nix develop --command'
   - Added --skip-nix-seed flag for environments that don't need it
   - Updated environment notes to emphasize nix-first

2. .cursor/environment.json:
   - Removed --skip-cargo-warm (full nix-backed warm now default)

3. AGENTS.md:
   - Added 'Toolchain' row to multi-stack table (nix develop required)
   - Added 'Toolchain Requirement' subsection with usage examples
   - Updated local agents guidance to use 'direnv allow'

4. context/cloud-agents.md:
   - Bootstrap now lists nix-seed as step 1
   - 'What does not work' table updated: bare system cargo now listed as
     failing; nix develop works after bootstrap
   - Updated nix section to reflect automatic seeding

Previous soft gap: nix-seed was a manual footnote; now it runs in bootstrap.

Co-authored-by: Ed Langley <fiddlerwoaroof@users.noreply.github.com>
This commit is contained in:
Cursor Agent
2026-09-25 19:20:34 +00:00
parent 8dcbfbfc77
commit 106d4fd3ac
4 changed files with 88 additions and 34 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
{ {
"name": "Improvise", "name": "Improvise",
"install": "./scripts/agent-bootstrap.sh --skip-cargo-warm", "install": "./scripts/agent-bootstrap.sh",
"start": "nix-daemon &" "start": "nix-daemon &"
} }
+19 -3
View File
@@ -34,18 +34,34 @@ potentially others. All stacks share the same operational setup:
| Component | Location | Notes | | Component | Location | Notes |
|---|---|---| |---|---|---|
| Toolchain | `nix develop` / `direnv` | **Required.** Rust from flake, wasm target, beads pin, trealla |
| Skills | `.agents/skills/` | Canonical source; `.claude/skills/` and `.cursor/skills/` symlink here | | Skills | `.agents/skills/` | Canonical source; `.claude/skills/` and `.cursor/skills/` symlink here |
| Session bootstrap | `scripts/agent-bootstrap.sh` | Stack-agnostic; installs bd, syncs tracker, warms cargo | | Session bootstrap | `scripts/agent-bootstrap.sh` | Seeds nix inputs, installs bd, syncs tracker, warms cargo |
| Knowledge base | `scripts/kb` | **All stacks use this**, not Prolog MCP | | Knowledge base | `scripts/kb` | **All stacks use this**, not Prolog MCP |
| Issue tracker | `bd` CLI | Synced from Dolt remote at session start | | Issue tracker | `bd` CLI | Synced from Dolt remote at session start |
### Toolchain Requirement
**Agents must work inside `nix develop` (or direnv) for this repo.** Bare system cargo that
fails `edition2024` or missing wasm target is a misconfigured session. The bootstrap seeds
nix flake inputs automatically (GitHub tarballs are blocked in cloud), so `nix develop`
should work after install completes.
Run commands inside the dev shell:
```bash
nix develop --command cargo test
nix develop --command cargo build --workspace
```
Or enter an interactive shell: `nix develop`
**Claude Code**: `.claude/hooks/session-start.sh` calls the bootstrap automatically. **Claude Code**: `.claude/hooks/session-start.sh` calls the bootstrap automatically.
**Cursor cloud**: `.cursor/environment.json` runs the bootstrap via `install`. Skills are **Cursor cloud**: `.cursor/environment.json` runs the bootstrap via `install`. Skills are
discovered from `.cursor/skills/` (symlinks to `.agents/skills/`). discovered from `.cursor/skills/` (symlinks to `.agents/skills/`).
**Local agents**: Run `scripts/agent-bootstrap.sh` manually, or use `direnv` / `nix develop` **Local agents**: Run `scripts/agent-bootstrap.sh` manually, or use `direnv allow` for
for the full dev shell which includes `bd` from the flake pin. automatic dev shell activation.
See `context/cloud-agents.md` for environment-specific notes (nix, network, etc.). See `context/cloud-agents.md` for environment-specific notes (nix, network, etc.).
+18 -13
View File
@@ -7,10 +7,14 @@ Cursor cloud agents, and similar setups. Local checkouts are unaffected.
All agent stacks use the same bootstrap script: `scripts/agent-bootstrap.sh`. It: All agent stacks use the same bootstrap script: `scripts/agent-bootstrap.sh`. It:
1. Verifies the `bd` version matches the flake.nix pin 1. **Seeds nix flake inputs** (GitHub tarballs are blocked; seeds over git instead)
2. Installs `bd` if missing 2. Verifies the `bd` version matches the flake.nix pin
3. Syncs the Dolt issue tracker from the git remote 3. Installs `bd` if missing
4. Optionally warms the cargo build 4. Syncs the Dolt issue tracker from the git remote
5. Warms the cargo build **inside `nix develop`**
**After bootstrap, `nix develop` works.** This is the required toolchain — bare system
cargo that fails `edition2024` or missing wasm target is a misconfigured session.
**Claude Code**: `.claude/hooks/session-start.sh` calls the bootstrap automatically when **Claude Code**: `.claude/hooks/session-start.sh` calls the bootstrap automatically when
`CLAUDE_CODE_REMOTE=true`. `CLAUDE_CODE_REMOTE=true`.
@@ -75,7 +79,8 @@ same if you need to re-sync by hand; never run it in the working tree.
| Thing | Status | Use instead | | Thing | Status | Use instead |
|---|---|---| |---|---|---|
| `nix develop` **unseeded** | Fails: flake inputs are GitHub **tarballs**, which are not served here | Run `scripts/nix-seed-flake-inputs.sh` first — see below. Or just use the preinstalled `cargo`/`rustc`, the same stable toolchain the flake pins | | `nix develop` **without bootstrap** | Fails: flake inputs are GitHub **tarballs**, which are blocked | Bootstrap seeds inputs automatically; if it failed, run `scripts/nix-seed-flake-inputs.sh` manually |
| Bare system cargo | Fails: `edition2024`, missing wasm target | **Always use `nix develop`** — this is the required toolchain |
| `bd dolt push` | Fails: 403 outbound | Nothing; bead status changes stay local. Say so rather than implying the tracker was updated | | `bd dolt push` | Fails: 403 outbound | Nothing; bead status changes stay local. Say so rather than implying the tracker was updated |
| `git+ssh://` Dolt remote in `config.yaml` | No ssh client in the container | `git+https://<origin>`, which the hook passes explicitly | | `git+ssh://` Dolt remote in `config.yaml` | No ssh client in the container | `git+https://<origin>`, which the hook passes explicitly |
| `git push`, GitHub API | **Work normally** | — | | `git push`, GitHub API | **Work normally** | — |
@@ -85,13 +90,13 @@ starting by hand). Reads of public GitHub repos over the git protocol work —
it is specifically the `/archive/*.tar.gz` and `codeload` endpoints that are it is specifically the `/archive/*.tar.gz` and `codeload` endpoints that are
refused. refused.
### Making `nix develop` work ### How nix develop works after bootstrap
`scripts/nix-seed-flake-inputs.sh` makes the devShell work **without touching The bootstrap runs `scripts/nix-seed-flake-inputs.sh` automatically, which seeds
`flake.nix` or `flake.lock`**. Verified end to end: `rustc 1.98.1`, `cargo`, the flake inputs over git **without touching `flake.nix` or `flake.lock`**.
`crate2nix` in the shell, `git status` clean. After bootstrap, `nix develop` should work. If it fails, check `/tmp/nix-seed.log`.
Why it is needed, and why the obvious fixes are not available: Why the seeding is needed:
- Nix's `github:` fetcher wants a tarball. GitHub traffic **bypasses the - Nix's `github:` fetcher wants a tarball. GitHub traffic **bypasses the
environment's domain allowlist entirely** and goes through a proxy that environment's domain allowlist entirely** and goes through a proxy that
@@ -120,9 +125,9 @@ around it — a mismatch fails loudly. Do not instead rewrite the lock's nodes
to `git` type: carrying the old `narHash` onto a different fetcher is exactly to `git` type: carrying the old `narHash` onto a different fetcher is exactly
the claim the lock exists to make. the claim the lock exists to make.
It is not in the session-start hook because it is expensive (minutes, plus The bootstrap runs this automatically. It takes a few minutes and several GB of
several GB of store once the devShell builds) and most work does not need the store once the devShell builds. If bootstrap reported a seed failure, check
devShell. Run it when you do. `/tmp/nix-seed.log` and re-run `scripts/nix-seed-flake-inputs.sh` manually.
Two alternatives if per-container seeding is unattractive: push the inputs to Two alternatives if per-container seeding is unattractive: push the inputs to
a binary cache with `nix flake archive` and point sessions at it with a binary cache with `nix flake archive` and point sessions at it with
+50 -17
View File
@@ -3,24 +3,30 @@
# #
# This script prepares any coding agent (Claude Code, Cursor, etc.) to work # This script prepares any coding agent (Claude Code, Cursor, etc.) to work
# on this repo. It handles: # on this repo. It handles:
# 1. bd (beads) installation and pin verification # 1. Nix flake input seeding (so `nix develop` works in cloud environments)
# 2. Issue tracker sync from the Dolt remote # 2. bd (beads) installation and pin verification
# 3. Optional cargo workspace warming # 3. Issue tracker sync from the Dolt remote
# 4. Optional cargo workspace warming (inside nix develop)
# #
# Usage: # Usage:
# scripts/agent-bootstrap.sh [--skip-cargo-warm] # scripts/agent-bootstrap.sh [--skip-cargo-warm] [--skip-nix-seed]
# #
# The script is idempotent and safe to re-run. Nothing here writes to tracked # The script is idempotent and safe to re-run. Nothing here writes to tracked
# files, stages anything, or creates a commit. # files, stages anything, or creates a commit.
# #
# IMPORTANT: This repo requires `nix develop` (or direnv) for builds/tests.
# Bare system cargo that fails edition2024 is a misconfigured session.
#
# See also: `.claude/hooks/session-start.sh` (Claude Code wrapper), # See also: `.claude/hooks/session-start.sh` (Claude Code wrapper),
# `.cursor/environment.json` (Cursor cloud config) # `.cursor/environment.json` (Cursor cloud config)
set -uo pipefail set -uo pipefail
SKIP_CARGO_WARM=0 SKIP_CARGO_WARM=0
SKIP_NIX_SEED=0
while [[ $# -gt 0 ]]; do while [[ $# -gt 0 ]]; do
case "$1" in case "$1" in
--skip-cargo-warm) SKIP_CARGO_WARM=1; shift ;; --skip-cargo-warm) SKIP_CARGO_WARM=1; shift ;;
--skip-nix-seed) SKIP_NIX_SEED=1; shift ;;
*) shift ;; *) shift ;;
esac esac
done done
@@ -30,7 +36,27 @@ cd "$ROOT" || exit 0
log() { printf '[agent-bootstrap] %s\n' "$*"; } log() { printf '[agent-bootstrap] %s\n' "$*"; }
# ── 0. The bd on PATH must be the bd flake.nix pins ──────────────────────── # ── 0. Seed nix flake inputs (required for cloud environments) ─────────────
# GitHub tarball endpoints are blocked in cloud containers. This seeds the
# flake inputs over git so `nix develop` can build the dev shell.
if [ "$SKIP_NIX_SEED" -eq 0 ] && command -v nix >/dev/null 2>&1; then
# Set SSL cert for proxy environments
if [ -z "${NIX_SSL_CERT_FILE:-}" ] && [ -r /root/.ccr/ca-bundle.crt ]; then
export NIX_SSL_CERT_FILE=/root/.ccr/ca-bundle.crt
fi
if [ -f "$ROOT/scripts/nix-seed-flake-inputs.sh" ]; then
log "seeding nix flake inputs (GitHub tarballs blocked in cloud)…"
if "$ROOT/scripts/nix-seed-flake-inputs.sh" >/tmp/nix-seed.log 2>&1; then
log "flake inputs seeded"
else
log "WARNING: nix-seed-flake-inputs.sh failed; see /tmp/nix-seed.log"
log " 'nix develop' may fail. Check network/proxy settings."
fi
fi
fi
# ── 1. The bd on PATH must be the bd flake.nix pins ────────────────────────
beads_pin() { beads_pin() {
sed -n 's|.*beads\.url[[:space:]]*=[[:space:]]*"github:[^/]*/[^/]*/v\{0,1\}\([^"]*\)".*|\1|p' \ sed -n 's|.*beads\.url[[:space:]]*=[[:space:]]*"github:[^/]*/[^/]*/v\{0,1\}\([^"]*\)".*|\1|p' \
flake.nix 2>/dev/null | head -1 flake.nix 2>/dev/null | head -1
@@ -123,7 +149,7 @@ install_tracker() {
return 1 return 1
} }
# ── 1. bd on PATH ────────────────────────────────────────────────────────── # ── 2. bd on PATH ──────────────────────────────────────────────────────────
export PATH="$PATH:/root/go/bin:$HOME/go/bin" export PATH="$PATH:/root/go/bin:$HOME/go/bin"
BD_INSTALLER_REF=f45b249ce6b40ba62aecc03949e6371e8f7c79d8 # tag v1.3.0 BD_INSTALLER_REF=f45b249ce6b40ba62aecc03949e6371e8f7c79d8 # tag v1.3.0
@@ -153,7 +179,7 @@ if [ "$pin_status" -eq 0 ]; then
assert_bd_pin || pin_status=2 assert_bd_pin || pin_status=2
fi fi
# ── 2. Sync the issue tracker from the Dolt remote ───────────────────────── # ── 3. Sync the issue tracker from the Dolt remote ─────────────────────────
if command -v bd >/dev/null 2>&1; then if command -v bd >/dev/null 2>&1; then
DB_NAME="$(jq -r '.dolt_database // "improvise"' .beads/metadata.json 2>/dev/null || echo improvise)" DB_NAME="$(jq -r '.dolt_database // "improvise"' .beads/metadata.json 2>/dev/null || echo improvise)"
ORIGIN="$(git remote get-url origin 2>/dev/null || true)" ORIGIN="$(git remote get-url origin 2>/dev/null || true)"
@@ -196,27 +222,34 @@ if command -v bd >/dev/null 2>&1; then
fi fi
fi fi
# ── 3. Warm the build (optional) ─────────────────────────────────────────── # ── 4. Warm the build inside nix develop (optional) ────────────────────────
if [ "$SKIP_CARGO_WARM" -eq 0 ] && command -v cargo >/dev/null 2>&1; then # Uses nix develop to ensure the correct toolchain (rust from flake, wasm target, etc.)
log "warming cargo build…" if [ "$SKIP_CARGO_WARM" -eq 0 ] && command -v nix >/dev/null 2>&1; then
if cargo build --workspace --tests >/tmp/cargo-warm.log 2>&1; then log "warming cargo build inside nix develop…"
log "workspace built" NIX_FLAGS=(--extra-experimental-features 'nix-command flakes')
if nix "${NIX_FLAGS[@]}" develop --command cargo build --workspace --tests >/tmp/cargo-warm.log 2>&1; then
log "workspace built (nix develop toolchain)"
else else
log "WARNING: cargo build failed; see /tmp/cargo-warm.log" log "WARNING: cargo build failed; see /tmp/cargo-warm.log"
log " This may indicate nix-seed failed or flake inputs are missing."
fi fi
elif [ "$SKIP_CARGO_WARM" -eq 0 ]; then
log "WARNING: nix not available; skipping cargo warm"
log " Install nix or use a container with nix for this repo."
fi fi
# ── 4. Environment notes ─────────────────────────────────────────────────── # ── 5. Environment notes ───────────────────────────────────────────────────
cat <<'NOTES' cat <<'NOTES'
[agent-bootstrap] Environment notes (see context/cloud-agents.md): [agent-bootstrap] Environment notes (see context/cloud-agents.md):
• Use the preinstalled cargo toolchain for ordinary work. `nix develop` • This repo REQUIRES `nix develop` (or direnv) for builds and tests.
also works, but only after scripts/nix-seed-flake-inputs.sh — GitHub Bare system cargo that fails edition2024 is a misconfigured session.
tarballs are not served here, so the locked inputs are seeded over git. • The bootstrap seeded flake inputs over git (GitHub tarballs are blocked
in cloud). If nix develop still fails, check /tmp/nix-seed.log.
• `bd dolt push` is blocked outbound (403). Bead status changes stay local. • `bd dolt push` is blocked outbound (403). Bead status changes stay local.
• Never run a bare `bd init` in this repo: it rewrites AGENTS.md, CLAUDE.md • Never run a bare `bd init` in this repo: it rewrites AGENTS.md, CLAUDE.md
and .claude/settings.json, and commits. Use --skip-agents --skip-hooks. and .claude/settings.json, and commits. Use --skip-agents --skip-hooks.
• `bd dolt push <remote>` ignores its argument and pushes to origin.
• Use `scripts/kb` for knowledge base operations, not Prolog MCP. • Use `scripts/kb` for knowledge base operations, not Prolog MCP.
• Run commands inside `nix develop` or prefix with `nix develop --command`.
NOTES NOTES
exit "$pin_status" exit "$pin_status"