Repository guidance for coding agents and maintainers.
Engineering issues and PRDs live in this repository's GitHub Issues. See docs/agents/issue-tracker.md.
Triage uses the canonical needs-triage, needs-info, ready-for-agent, ready-for-human, and wontfix roles. See docs/agents/triage-labels.md.
Squarebox uses a single repository context in CONTEXT.md, with decisions in docs/adr/. See docs/agents/domain.md.
Read CONTEXT.md before changing behavior. The important state split is:
- Workspace: host project tree mounted at
/workspace. - Managed home: named volume mounted at
/home/dev; survives Box replacement. - Box filesystem: disposable image/container state; selected Box-tier packages must be reconciled after replacement.
- Selection: desired optional tools under
/workspace/.squarebox. - Observed state: binaries/configuration actually usable in the current Box.
- Install identity:
<SQUAREBOX_DIR>/.squarebox/install-state, recording runtime, paths, resource ownership, source revision, and image identity. Release pulls use an immutable digest; source builds use a local image ID/ref. - Candidate/Release: one source SHA bound to one multi-architecture image
digest and matched assets in
release.json.
Relevant architecture decisions are in docs/adr/. Do not reintroduce raw-tag
stable discovery, inferred test passes, default reconstruction during uninstall,
or installation after a failed artifact-verification stage.
set -euo pipefail
mapfile -t test_files < <(
find tests -maxdepth 1 -type f -name 'test-*.sh' -perm -u+x | sort
)
test "${#test_files[@]}" -gt 0
for test_file in "${test_files[@]}"; do "$test_file"; done
docker build --build-arg SQUAREBOX_VERSION=dev -t squarebox:test .
docker run --rm \
-v "$PWD/scripts:/workspace/scripts:ro" \
squarebox:test bash -c 'scripts/e2e-test.sh smoke'scripts/e2e-test.sh all also provisions optional network-backed tools. The
Candidate workflow builds one digest, tests/scans it, collects assertion
Evidence, and promotes that exact digest only after every required ID in
scripts/e2e-required.tsv passes.
install.sh and install.ps1 resolve published Releases through GitHub release
metadata and validate release.json. Stable uses /releases/latest; an
explicit tag uses the corresponding published release; edge builds main.
Only the v1.0 compatibility path may lack a manifest.
Publishable versions are vMAJOR.MINOR.PATCH[-prerelease]; build metadata is
excluded so the GitHub Release and OCI aliases share one unambiguous identity.
Both adapters persist effective settings. Rebuild functions locate adjacent
state and reuse paths/runtime/volume/UID/GID/build/channel/SSH-mount choices.
Uninstallers parse that state, verify resource labels, and refuse unrelated
fixed-name resources. Writers emit FORMAT=2; readers also accept FORMAT=1,
which lacks MOUNT_SSH (read as 0). See ADR 0010 before adding a field.
On Windows, the format has an aligned closed field set but native
PowerShell and Git Bash path/profile values are adapter-native; only the creating
adapter may consume that state. Pre-v1.1 installs need explicit adoption; an
adopted unlabeled volume also needs force before purge.
The private Git identity at .squarebox/identity/git contains name/email only.
Never mount, chown, or copy the host's real ~/.config/git.
Compose uses SQUAREBOX_IMAGE_REF, explicit container/volume names, and
ownership labels. Dev Containers mount the cloned repository at /workspace,
which matches Selection state and setup assumptions.
setup.sh supports interactive full/section reruns, saved noninteractive
Selections, and --reconcile-box for entrypoint repair. A persistent
setup-complete marker is not proof that Box-tier packages exist.
Key rules:
- Preserve old Selection on prompt cancellation; intentional empty selection is distinct.
- Commit Selection/aliases from successful observed installs, not requested values.
- Keep Bash, Zsh, Fish, and PowerShell derived configuration synchronized after section reruns.
- Respect explicit user configuration during migrations (for example tmux mouse off).
- Runtime APT must work with the read-only timezone mount and show actionable failures.
sqrbx-learnwas removed in v1.3. Any return must follow the ROADMAP learn-mode redesign: opt-in, with no command logging without informed consent.
GitHub authentication uses the normal Managed-home ~/.config/gh plus
~/.squarebox-gh-skip; legacy Workspace markers are migrated.
Supported assistant keys include claude, copilot, gemini, codex,
opencode, pi, and omp. Copilot is @github/copilot, binary copilot,
and needs Node 22 or newer. SDKs are managed by mise. Editors include micro,
edit, fresh, Helix (hx), and Neovim/LazyVim.
scripts/lib/tools.yaml owns release-asset metadata, Tool tier, verification
policy, and Docker ARG mapping. Observed version probes remain adapter functions
in scripts/squarebox-update.sh. The awk reader avoids requiring yq to install
yq. Gum is the sole OCI-sourced exception: Dockerfile pins its exact upstream
multi-architecture digest and asserts the reviewed version/commit, while
tests/test-gum-image-policy.sh rejects mutable or unreviewed references.
scripts/lib/tool-lib.sh is the deep artifact-install module. Its interface
must remain fail-closed across metadata validation, download, verification,
extraction, staging, atomic destination promotion, post-install hooks, and
cleanup. Image-tier artifacts require Squarebox's pinned sha256 manifest.
Setup-tier GitHub artifacts require the digest attached to the exact release
asset by GitHub; absent, malformed, duplicate, or mismatched digests fail closed.
Runtime system-binary promotion uses narrowly matched sudo command forms with
staged dotfiles in /usr/local/bin. Keep the implementation and Dockerfile
sudoers patterns synchronized and validate sudoers during image build.
scripts/update-versions.sh generates checksums and Dockerfile pins as one
transaction. sqrbx-update --apply updates installed tools only; an explicitly
named absent tool requests installation. Aggregate failures return nonzero and
diagnostic logs must survive long enough for the user to inspect them.
The image source for managed Bash/Starship files lives under
/usr/local/lib/squarebox/dotfiles. Entrypoint refresh defeats stale
Managed-home volume copies. Bind mounts remain host-managed and are skipped;
a symlink destination is rejected with a visible startup failure. Never follow
a persistent-home symlink as root.
Bash is default. Experimental Zsh/Fish/PowerShell are selected with markers in
the Managed home and must initialize Starship, Zoxide, the fzf/ff command
path, aliases, and mise. The packaged Ctrl+R/Ctrl+T/Alt+C/** bindings are a
Bash-only contract.
The Box is not a hostile-code sandbox. Passwordless dpkg/install and related
package operations provide effective container-root authority. Document them as
operational controls, not a security barrier. See SECURITY.md for mount,
artifact, signing, and reporting details.
PowerShell 7 is the supported native Windows adapter. Use
CurrentUserAllHosts-compatible integration and validate the final Box start.
It does not forward SSH_AUTH_SOCK and mounts the native user's .ssh
directory read-only only on explicit opt-in (-MountSsh or
SQUAREBOX_MOUNT_SSH=1, persisted as MOUNT_SSH). Both adapters default to no
.ssh directory mount; the Bash adapter's agent forwarding mounts only
config/known_hosts. Git Bash uses the separate Bash adapter and owns its
MSYS shell integration and agent-socket translation. Keep the shared state field
names and semantic intent aligned, but fail closed rather than cross-consuming
adapter-native lifecycle state.
Rootless Podman maps the host identity to dev with
keep-id:uid=1000,gid=1000 and leaves host labels unchanged via
label=disable. Changes need automated Ubuntu coverage and manual Fedora
enforcing UAT.