This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Shell-Cell (scell) is a lightweight CLI tool that creates instant, isolated, and reproducible containerized development shell sessions. It uses CUE blueprints (scell.cue) to define layered environments (called "targets") that compile into Docker images and run as persistent "shell server" containers.
Key Concept: Unlike standard containers that run a task and exit, Shell-Cell containers use a hang instruction to stay alive as background servers, allowing multiple shell sessions to attach to a warm, ready environment.
cargo build# Run all tests (must use single thread)
cargo test -- --test-threads 1
# Run specific test
cargo test <test_name> -- --test-threads 1# Format code (requires nightly toolchain)
cargo +nightly fmt
# Check formatting
cargo +nightly fmt --check
# Run clippy
cargo clippy --all-targets# Build and run
cargo run
# Run with a specific scell.cue path
cargo run -- /path/to/directory
# List containers
cargo run -- ls
# Stop containers
cargo run -- stop
# Enable verbose mode
cargo run -- -vThe binary name is scell (defined in Cargo.toml).
- Parser (
src/scell/parser/): Parsesscell.cuefiles intoSCellFileandTargetStmtstructures - Compiler (
src/scell/compile/): Resolves target references recursively, building a chain ofLinks (Root + Nodes) to form anSCell - Image Builder (
src/scell/image.rs): Generates a Dockerfile and tar artifact from theSCelllink chain - BuildKit (
src/buildkit/): Uses Bollard (Docker client) to build images and manage containers - PTY (
src/pty.rs): Attaches an interactive shell session to the running container
-
SCell(src/scell/mod.rs): The compiled representation of a Shell-Cell, containing:links: Vec<Link>- Chain from entry point down to base imageshell: ShellStmt- The shell binary path (e.g.,/bin/bash)hang: String- Command to keep container aliveconfig: Option<ConfigStmt>- Runtime configuration (mounts, etc.)
-
Link: Either aRoot(ImageDef)(base Docker image) or aNode(target with workspace, copy, build instructions) -
Target Resolution: Starting from entry point (
mainby default), the compiler followsfromstatements recursively:from: debian:bookworm→ Root imagefrom: path/to/dir+target_name→ Reference to another target (potentially in anotherscell.cue)
-
Build Order: Targets are parsed from entry→root, but Dockerfile generation happens in reverse (root→entry)
Executed in strict order during image building:
workspace- Sets working directory (likeWORKDIR)from- Base image or target reference (likeFROM)copy- Copies files into image (likeCOPY)env- Sets environment variables (likeENV), format:KEY=VALUEbuild- Runs commands during build (likeRUN)
Special instructions (only first encountered is used):
shell- Defines shell binary for interactive sessionshang- Keeps container alive (becomesENTRYPOINT)config- Runtime configuration (mounts, etc.)
The project uses a custom error system (src/error/):
UserError: Errors caused by user input (bad config, missing files, etc.) - show clean messagesReport: Accumulates multiple errors before returning- Traits:
WrapUserError,OptionUserError- Convert stdlib errors to UserError - Verbose mode (
-v) shows full backtraces for non-user errors
Containers are named scell-<hash> where <hash> is a MetroHash64 of the entire SCell structure. This ensures the same blueprint always produces the same container name.
Images are tagged with metadata labels:
scell-name: Target namescell-location: Absolute path to thescell.cuefile
This project has strict linting (see Cargo.toml lints):
unwrap_used,expect_used,panic,todo,unimplemented,unreachableare all denied- Use
?and proper error handling instead indexing_slicingis denied - use.get()instead- Clippy pedantic is enabled at deny level
- Missing docs in public items triggers warnings (but private items are allowed)
// Use the provided helper
scell_home_dir() // Returns ~/.scell/The CLI accepts a directory path, not a file path. It always looks for scell.cue in that directory.
All Docker operations go through BuildKitD (src/buildkit/mod.rs), which wraps the Bollard client. The project uses async/await with Tokio runtime.
Tests use test-case crate for parameterized tests. Compilation tests are in src/scell/compile/tests/ with subdirectories:
ok/- Valid blueprints that should compile successfullyerr/- Invalid blueprints that should produce specific errors
Critical: Tests MUST run with --test-threads 1 due to Docker state dependencies.