8000 docs(guide): lift the building, dev-shell, agents, tasks, and packages guides by norrietaylor · Pull Request #942 · gominimal/minimal · GitHub
[go: up one dir, main page]

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions docs/guide/agents.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
description: Run AI coding agents like Claude Code inside an isolated session with declared tools and host credentials.
---

# Agent shell

Minimal can sandbox AI coding agents the same way it sandboxes your dev tools: an agent runs inside a [session](./dev-shell.md), with access to your source code and only the tools and host state you declare.

## Example: Claude Code

This documentation site is itself built and maintained using Claude Code inside a Minimal session. Add the agent's package to the project's `[session]` block:

```toml
[session]
packages = ["claude-code", "base"]
```

Then activate the session and run the agent inside it:

```shell
$ min activate --attach .
$ claude
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have some issues with TERM not being set atm, do we want to say TERM=xterm claude --dangerously-skip-permissions or something equally verbose for now?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Evan has said he will pull envs over. Unless that becomes risky lets keep it this way

```

Claude Code launches inside the session with your project's source code and a read-only system containing the `claude-code` binary and core utilities from `base`. The session has no additional access to anything on your host system unless you explicitly declare it.

Note that sessions are driven interactively: attaching needs a terminal, and the non-interactive `min attach -c` channel accepts only `min run <task>` invocations. Launch the agent from inside an attached shell as shown above, rather than scripting it from the host.

## Adding more tools

Agents often need additional tools to be effective. Add packages to the `[session]` block just like any other:

```toml
[session]
packages = ["claude-code", "base", "git", "curl"]
```

## Passing through host credentials

Use `patches` to give the agent access to host files it needs, like authentication state. Each patch maps a host `source` to a `dest` under the session user's home directory:

```toml
[session]
packages = ["claude-code", "base", "git"]
patches = [
{ source = "~/.gitconfig", dest = "~/.gitconfig" },
{ source = "~/.ssh", dest = "~/.ssh" },
]
```

Environment variables can be inherited from the host as well, under `[session.vars]`:

```toml
[session.vars]
ANTHROPIC_API_KEY = { inherit = true }
```
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved

Anything you pass through is available to the agent and to any code it runs: a
patched `~/.ssh` means the agent can use your SSH keys, and an inherited
`ANTHROPIC_API_KEY` is readable by every process in the session. Pass through
the minimum the agent needs, and prefer scoped or short-lived credentials over
long-lived ones. Activation helps you hold this line: each value inherited from
your environment and each file patch is gated against your user policy, and
anything your policy cannot decide is surfaced for approval before it enters
the session.

## Why sandbox agents?

Running an AI agent in a Minimal session means it can only access the tools and files you declare. It cannot install arbitrary software, read unrelated files, or modify your system. This is the same isolation model that Minimal applies to builds and dev shells, applied to agents.
72 changes: 72 additions & 0 deletions docs/guide/building.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
---
description: Run builds and tests in sandboxed environments using stacks. Covers extra dependencies, test commands, and build state persistence.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to get this one in as-is, but hopefully with SOPs coming in hot we can switch this to entirely be using sessions / min

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup the goal is to remove mip from these docs

---

# Building

Minimal builds your code reproducibly inside a sandbox, using a [stack](../concepts/stacks.md) to wire up the right tools and build commands for your language or build system.

A build is a **one-shot** command that runs in its own fresh sandbox and exits, driven by the `mip` CLI (Linux-only; on macOS, work inside a [dev session](./dev-shell.md) instead). That is different from an interactive dev session, which is a long-lived environment you attach to with `min` for interactive development.

## Running a build

```shell
$ mip build
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix the Markdownlint MD014 warnings.

These command examples use $ prompts without showing output. Remove the prompts or add representative output so the documentation passes commands-show-output.

Also applies to: 49-50, 58-58

🧰 Tools
🪛 markdownlint-cli2 (0.23.0)

[warning] 14-14: Dollar signs used before commands without showing output

(MD014, commands-show-output)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/guide/building.md` at line 14, Update the command examples in
building.md, including the mip build examples and the additional referenced
blocks, to satisfy Markdownlint MD014: remove the leading $ prompts from
commands that show no output, or add representative output where prompts should
remain. Keep the examples clear and consistent.

Source: Linters/SAST tools

```

This is shorthand for `mip run build`. The stack configured in your `minimal.toml` determines what happens. For example, a Rust stack runs `cargo build --release`, while a pnpm stack runs roughly `pnpm install && pnpm build`.

## How stacks work

When you declare a stack, it provides:

- **Build packages**: compilers, build tools, and other dependencies needed during compilation
- **Runtime packages**: libraries needed wherever the built software runs
- **Build commands**: the default commands executed by `mip build`
- **Environment variables**: compiler flags, paths, and other configuration

```toml
[stack]
use = "go"
```

With just this configuration, `mip build` will run `go build` with the Go compiler and all necessary toolchain packages available in the sandbox.

## Adding extra dependencies

Most projects need additional dependencies beyond what the stack provides. Declare them in the `[stack]` section:

```toml
[stack]
use = "rust"
build_packages = ["protobuf", "perl"]
runtime_packages = ["openssl"]
```

Or add them with the CLI:

```shell
$ min add --build protobuf
$ min add --runtime openssl
```

## Running tests

Similarly to `mip build`, you can run your test suite with:

```shell
$ mip test
```

This is shorthand for `mip run test`, and runs the `test` task from your `minimal.toml`; define one with `[tasks.test]`. Stacks provide a default `build` task only.

## Persisting build state

By default, each task invocation starts from a clean state. To cache build artifacts across runs (like `node_modules` or `target/`), set a `state_key`:

```toml
[defaults]
state_key = "dev"
```

Tasks sharing the same `state_key` share cached state, so your builds don't start from scratch every time.
95 changes: 95 additions & 0 deletions docs/guide/dev-shell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
---
description: Enter an isolated interactive development session with only your declared tools. Covers customization, host file access, and environment variables.
---

# Dev shell

Your dev shell in Minimal is a **session**: a long-lived, isolated development environment for a project, driven by the `min` CLI. It gives you an interactive shell with only the tools you declare, isolated from your host system. Use it for everyday development, running ad-hoc commands, debugging, or working interactively with your project's toolchain.

## Launch a shell

From your project directory, activate a session and attach to it in one step:

```shell
$ min activate --attach .
```

This creates a session for the project and drops you into its interactive shell. The path argument defaults to the current directory, so `min activate --attach` on its own works too.

Your project files are uploaded into the session's workspace, so the shell starts with a copy of your project. Edits you make inside stay in the session; bring them back to the host by pushing them out with `git push min://<session>` (or by committing inside the session and pulling from it).

## What's in the session?

A session's tools come from the project's `[session]` block in `minimal.toml`. List the packages every contributor should have when working on this codebase:

```toml
[session]
packages = ["git", "curl", "ripgrep"]
```

Inside the session you have access to your project's source code and these declared tools (plus any [loadouts](../concepts/loadouts.md) you apply and the packages the project's stack declares), but nothing else from the host system. The session cannot globally install software, read unrelated files, or modify your system. Every developer working on the project gets the same isolated environment.

## Customizing your session

### Add more tools

Add packages to the project's `[session]` block so everyone picks them up:

```toml
[session]
packages = ["git", "curl", "ripgrep", "jq", "nano"]
```

If you need a package mid-session, without editing config by hand or restarting your shell, run `min add` from inside the running session:

```shell
$ min add nano
```

This installs the tool into the running session and records it in the project's `[session]` `packages` list, so the next activation gets it too. See the [`min` in-sandbox commands](../reference/sandbox-operations.md#add) for the full helper reference.

### Access host files

By default, only your project directory is available inside the session. To bring specific host files or directories in, declare `patches` in the `[session]` block. Each patch names a `source` on the host and a `dest` under the session user's home directory:

```toml
[session]
packages = ["git"]
patches = [
{ source = "~/.gitconfig", dest = "~/.gitconfig" },
{ source = "~/.ssh", dest = "~/.ssh" },
]
```

### Set environment variables

The session starts with a clean environment; host environment variables are not passed through by default. Set variables explicitly, or inherit them from the host, under `[session.vars]`:

```toml
[session.vars]
EDITOR = "nano"
AWS_PROFILE = { inherit = true }
```

A string value like `EDITOR = "nano"` defines a fixed variable. Using `{ inherit = true }` passes through the value from your host environment, which is useful for credentials or configuration that varies per developer.

### Run setup on activation

To run setup steps when a session comes up, declare lifecycle hooks in the `[session]` block:

```toml
[[session.lifecycle_hooks]]
on_activate = { type = "inline", value = "cargo fetch >/dev/null 2>&1 || true" }
```

## Session lifecycle

Exit the shell to detach; the session keeps running in the background. To reattach, list, or tear down sessions:

```shell
$ min attach # reattach to a session (resolves from the current directory)
$ min ls # list sessions
$ min destroy <session> # terminate a session by name or id (or --all)
```

For running one-shot commands in their own sandbox rather than an interactive session, see [Tasks](./tasks.md).
66 changes: 66 additions & 0 deletions docs/guide/packages.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
description: Add build, runtime, session, and task-specific package dependencies using the min and mip CLIs or minimal.toml.
---

# Packages

Minimal makes it easy to add tools and dependencies to your project. Where a package lives depends on when you need it: building your code, running it, developing interactively, or inside a specific task.

## Build and runtime dependencies

Build and runtime dependencies belong to your build plane and are managed with `min add`:

```shell
# Add as a build dependency (needed to compile your code)
$ min add --build protobuf

# Add as a runtime dependency (needed wherever your code runs)
$ min add --runtime openssl
```

Each command updates your `minimal.toml` automatically.

**Build dependencies** are packages needed during compilation but not at runtime. They are declared in the `[stack]` section:

```toml
[stack]
use = "rust"
build_packages = ["protobuf", "perl"]
```

**Runtime dependencies** are packages that must be present wherever the built software runs:

```toml
[stack]
use = "rust"
runtime_packages = ["openssl"]
```

## Session tools

Tools you want available while developing interactively go in the project's `[session]` block, not the build plane. Every contributor's [dev session](./dev-shell.md) picks them up:

```toml
[session]
packages = ["git", "ripgrep", "jq"]
```

To add a tool to a running session without editing config, run `min add <package>` from inside the session shell.

## Task-specific packages

Packages can also be scoped to individual [tasks](../reference/tasks.md), where they are only available when that task runs. Add them with `min add --task <name>`:

```shell
$ min add --task lint ruff
```

```toml
[tasks.lint]
packages = ["python", "ruff"]
exec = "ruff check ."
```

## Available packages

The [Minimal Public Package Registry](https://github.com/gominimal/pkgs/tree/main/packages) contains hundreds of packages including compilers, interpreters, build tools, and common CLI utilities.
64 changes: 64 additions & 0 deletions docs/guide/tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
---
description: Define named tasks in minimal.toml that run commands in sandboxed environments with specific packages and env vars.
---

# Tasks

Tasks define commands that run in a [sandbox](../concepts/sandboxing.md) with exactly your declared dependencies. Every developer on your team runs the same task in the same environment.

A task is a **one-shot** command that runs in its own fresh sandbox and exits, driven by the `mip` CLI (Linux-only; inside a session, `min run <name>` runs the same tasks on any platform). That makes it different from an interactive [dev session](./dev-shell.md), which is a long-lived environment you attach to with `min`. Reach for a task to run builds, tests, linters, and deploys; reach for a session for interactive development.

## Defining a task

Tasks are defined in your `minimal.toml` and run with `mip run <name>`:

```toml
[tasks.lint]
packages = ["python", "ruff"]
exec = "ruff check ."

[tasks.greet]
bash = "echo Hello from $(uname -s) && date"
```

```shell
$ mip run greet
Hello from Linux
Tue Mar 17 12:00:00 UTC 2026
```

Use `exec` for a single command, or `bash` for shell scripts.

## Environment variables

Set environment variables directly, or inherit them from the host:

```toml
[tasks.deploy]
packages = ["railway"]
exec = "railway up"
env_vars.RAILS_ENV = "production"
env_vars.GITHUB_TOKEN = { inherit = true }
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
```

`inherit = true` copies the value from your host environment into the task's
sandbox, where every command the task runs can read it — including scripts the
repository itself provides. Inherit sparingly, and prefer scoped, short-lived
tokens over long-lived ambient credentials.

## Mapping host files

Use `patches` to give a task access to specific files or directories on the host:

```toml
[tasks.deploy]
packages = ["railway"]
exec = "railway up"
patches.dir."~/.config/railway" = "read-only"
```

Map host files `read-only` unless the task genuinely needs to write them: a
`read-write` mapping lets anything the task runs modify those host files in
place.

See the [tasks reference](../reference/tasks.md) for the full schema.
0