# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
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.
## Development Commands
### Building
```bash
cargo build
```
### Testing
```bash
# Run all tests (must use single thread)
cargo test -- --test-threads 1
# Run specific test
cargo test <test_name> -- --test-threads 1
```
### Linting & Formatting
```bash
# Format code (requires nightly toolchain)
cargo +nightly fmt
# Check formatting
cargo +nightly fmt --check
# Run clippy
cargo clippy --all-targets
```
### Running the Binary
```bash
# 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 -- -v
```
The binary name is `scell` (defined in Cargo.toml).
## Architecture
### Core Pipeline: Blueprint → Image → Container → Shell
1. **Parser** (`src/scell/parser/`): Parses `scell.cue` files into `SCellFile` and `TargetStmt` structures
2. **Compiler** (`src/scell/compile/`): Resolves target references recursively, building a chain of `Link`s (Root + Nodes) to form an `SCell`
3. **Image Builder** (`src/scell/image.rs`): Generates a Dockerfile and tar artifact from the `SCell` link chain
4. **BuildKit** (`src/buildkit/`): Uses Bollard (Docker client) to build images and manage containers
5. **PTY** (`src/pty.rs`): Attaches an interactive shell session to the running container
### Key Data Structures
- **`SCell`** (`src/scell/mod.rs`): The compiled representation of a Shell-Cell, containing:
- `links: Vec<Link>` - Chain from entry point down to base image
- `shell: ShellStmt` - The shell binary path (e.g., `/bin/bash`)
- `hang: String` - Command to keep container alive
- `config: Option<ConfigStmt>` - Runtime configuration (mounts, etc.)
- **`Link`**: Either a `Root(ImageDef)` (base Docker image) or a `Node` (target with workspace, copy, build instructions)
- **Target Resolution**: Starting from entry point (`main` by default), the compiler follows `from` statements recursively:
- `from: debian:bookworm` → Root image
- `from: path/to/dir+target_name` → Reference to another target (potentially in another `scell.cue`)
- **Build Order**: Targets are parsed from entry→root, but Dockerfile generation happens in reverse (root→entry)
### Target Instructions (Blueprint Syntax)
Executed in strict order during image building:
1. `workspace` - Sets working directory (like `WORKDIR`)
2. `from` - Base image or target reference (like `FROM`)
3. `copy` - Copies files into image (like `COPY`)
4. `env` - Sets environment variables (like `ENV`), format: `KEY=VALUE`
5. `build` - Runs commands during build (like `RUN`)
Special instructions (only first encountered is used):
- `shell` - Defines shell binary for interactive sessions
- `hang` - Keeps container alive (becomes `ENTRYPOINT`)
- `config` - Runtime configuration (mounts, etc.)
### Error Handling
The project uses a custom error system (`src/error/`):
- **`UserError`**: Errors caused by user input (bad config, missing files, etc.) - show clean messages
- **`Report`**: Accumulates multiple errors before returning
- Traits: `WrapUserError`, `OptionUserError` - Convert stdlib errors to UserError
- Verbose mode (`-v`) shows full backtraces for non-user errors
### Container Naming
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 name
- `scell-location`: Absolute path to the `scell.cue` file
## Linting Rules
This project has **strict linting** (see Cargo.toml lints):
- `unwrap_used`, `expect_used`, `panic`, `todo`, `unimplemented`, `unreachable` are all **denied**
- Use `?` and proper error handling instead
- `indexing_slicing` is denied - use `.get()` instead
- Clippy pedantic is enabled at deny level
- Missing docs in public items triggers warnings (but private items are allowed)
## Important Patterns
### Home Directory
```rust
// Use the provided helper
scell_home_dir() // Returns ~/.scell/
```
### Blueprint Location
The CLI accepts a directory path, not a file path. It always looks for `scell.cue` in that directory.
### Docker Integration
All Docker operations go through `BuildKitD` (`src/buildkit/mod.rs`), which wraps the Bollard client. The project uses async/await with Tokio runtime.
## Testing
Tests use `test-case` crate for parameterized tests. Compilation tests are in `src/scell/compile/tests/` with subdirectories:
- `ok/` - Valid blueprints that should compile successfully
- `err/` - Invalid blueprints that should produce specific errors
**Critical**: Tests MUST run with `--test-threads 1` due to Docker state dependencies.