Claude
Skills
Sign in
Back

sandbox:sandbox-config-management

Included with Lifetime
$97 forever

This skill should be used when reading or writing Sandbox.toml configuration files, cloning sandbox configurations from existing projects, merging user preferences with detected settings, validating sandbox configuration compatibility, or managing sandbox metadata and settings. Provides knowledge for Sandbox.toml structure and configuration management.

Writing & Docsscripts

What this skill does


# sandbox-config-management

Read, write, and manage Sandbox.toml configuration files that define sandbox setup and preferences.

## Purpose

This skill provides knowledge for working with `Sandbox.toml` files - the configuration format used to define and share sandbox setups. Handle reading existing configurations, creating new ones, cloning and customizing configurations, and validating compatibility.

## Sandbox.toml Structure

### Complete Example

```toml
[sandbox]
name = "myproject"
location = "/Users/aaronbassett/Sandboxes/aaronbassett/myproject"
created = "2026-01-24T01:30:00Z"
base_image = "ubuntu:24.04"

[source]
type = "github"  # or "local" or "new"
repository = "aaronbassett/myproject"
branch = "main"  # optional

[languages]
rust = "1.93.0"  # or "stable", "nightly"
python = "3.14.2"  # or "current"
nodejs = "current"  # or "lts", "nightly", "18.20.0"

[languages.tools]
rust = ["clippy", "rustfmt", "cargo-dist", "cargo-deny", "cargo-release", "cocogitto"]
python = ["uv", "ruff", "mypy", "black", "pytest"]
nodejs = ["pnpm", "typescript", "ts-node"]

[claude]
marketplaces = [
    "anthropics/claude-plugins-official",
    "aaronbassett/agent-foundry"
]

[claude.plugins]
plugins = [
    "rust-analyzer-lsp@claude-plugins-official",
    "pyright-lsp@claude-plugins-official",
    "typescript-lsp@claude-plugins-official",
    "devs@agent-foundry",
    "git-lovely@agent-foundry",
    "settings-presets@agent-foundry"
]

[network]
ports = [3000, 3001, 3002]  # specific ports
# or
port_range = "3000-3999"  # range

[environment]
# Non-secret environment variables
NODE_ENV = "development"
RUST_BACKTRACE = "1"

[shell]
aliases = true  # use standard eza/git aliases
starship_theme = "red_container"
oh_my_zsh_plugins = ["git", "docker", "rust", "python", "node"]

[tools]
# Additional CLI tools beyond defaults
extra = ["bat", "delta", "hyperfine"]
```

### Field Descriptions

**[sandbox] section:**
- `name`: Project name (required)
- `location`: Absolute path to sandbox directory (required)
- `created`: ISO 8601 timestamp of creation
- `base_image`: Docker base image (default: "ubuntu:24.04")

**[source] section:**
- `type`: "github", "local", or "new" (required)
- `repository`: GitHub repo (owner/name) if type="github"
- `branch`: Git branch (default: "main")

**[languages] section:**
- `rust`, `python`, `nodejs`: Version strings or keywords
- Keywords: "stable"/"current", "lts", "nightly"
- Specific versions: "1.93.0", "3.14.2", "18.20.0"

**[languages.tools] section:**
- Arrays of tool names to install for each language
- Empty array = no additional tools

**[claude] section:**
- `marketplaces`: List of marketplace repos
- `plugins`: List of plugins in "name@marketplace" format

**[network] section:**
- `ports`: Array of specific ports to forward
- `port_range`: String range like "3000-3999"
- Use one or the other, not both

**[environment] section:**
- Key-value pairs for environment variables
- Do not include secrets (use .env file instead)

**[shell] section:**
- `aliases`: Boolean to include standard aliases
- `starship_theme`: Theme identifier
- `oh_my_zsh_plugins`: List of plugin names

**[tools] section:**
- `extra`: Additional tools beyond standard set

## Reading Configurations

### Parse Sandbox.toml

Use `scripts/parse_config.py`:

```bash
python3 scripts/parse_config.py /path/to/sandbox/Sandbox.toml
```

Output: JSON representation of configuration

```python
# In Python code
import tomli

with open("Sandbox.toml", "rb") as f:
    config = tomli.load(f)

# Access fields
project_name = config["sandbox"]["name"]
languages = config.get("languages", {})
rust_version = languages.get("rust")
```

### Validate Configuration

Check for required fields and valid values:

```python
def validate_config(config: dict) -> List[str]:
    """
    Validate Sandbox.toml structure.

    Returns list of validation errors (empty if valid).
    """
    errors = []

    # Required sections
    if "sandbox" not in config:
        errors.append("Missing [sandbox] section")
    else:
        sandbox = config["sandbox"]
        if "name" not in sandbox:
            errors.append("Missing sandbox.name")
        if "location" not in sandbox:
            errors.append("Missing sandbox.location")

    if "source" not in config:
        errors.append("Missing [source] section")
    else:
        source = config["source"]
        if "type" not in source:
            errors.append("Missing source.type")
        elif source["type"] not in ["github", "local", "new"]:
            errors.append(f"Invalid source.type: {source['type']}")

        if source.get("type") == "github" and "repository" not in source:
            errors.append("GitHub source requires repository field")

    # Warn about unknown fields (lenient)
    # Just log warnings, don't error

    return errors
```

Use `scripts/validate_config.py` for validation.

### Read from Existing Sandbox

When user references an existing sandbox:

```
User: "Base this on ~/Sandboxes/aaronbassett/project1"
```

Process:
1. Check if directory exists
2. Look for `Sandbox.toml` in directory root
3. Parse configuration
4. Present configuration to user for customization

```python
existing_config_path = Path("~/Sandboxes/aaronbassett/project1/Sandbox.toml").expanduser()

if not existing_config_path.exists():
    print("No Sandbox.toml found in that directory")
    # Offer to create from scratch
else:
    with open(existing_config_path, "rb") as f:
        existing_config = tomli.load(f)

    # Show user what's in existing config
    print(f"Found sandbox config for: {existing_config['sandbox']['name']}")
    print(f"Languages: {', '.join(existing_config.get('languages', {}).keys())}")
    # etc.
```

## Writing Configurations

### Create New Sandbox.toml

Build configuration from user answers and detected settings:

```python
from datetime import datetime, timezone

config = {
    "sandbox": {
        "name": project_name,
        "location": str(sandbox_location),
        "created": datetime.now(timezone.utc).isoformat(),
        "base_image": base_image or "ubuntu:24.04",
    },
    "source": {
        "type": source_type,  # "github", "local", or "new"
    },
}

# Add repository if GitHub source
if source_type == "github":
    config["source"]["repository"] = repo_name
    config["source"]["branch"] = branch or "main"

# Add detected/specified languages
if languages:
    config["languages"] = languages
    config["languages"]["tools"] = tools_by_language

# Add Claude configuration
if marketplaces or plugins:
    config["claude"] = {}
    if marketplaces:
        config["claude"]["marketplaces"] = marketplaces
    if plugins:
        config["claude"]["plugins"] = plugins

# Add network config
if ports:
    config["network"] = {"ports": ports}
elif port_range:
    config["network"] = {"port_range": port_range}

# Add environment variables (non-secrets only)
if env_vars:
    config["environment"] = env_vars

# Shell configuration
config["shell"] = {
    "aliases": True,
    "starship_theme": "red_container",
    "oh_my_zsh_plugins": ["git", "docker", "rust", "python", "node"],
}
```

### Write to File

```python
import tomli_w  # or toml for writing

output_path = Path(sandbox_location) / "Sandbox.toml"

with open(output_path, "wb") as f:
    tomli_w.dump(config, f)

print(f"Configuration saved to {output_path}")
```

Use `scripts/write_config.py` helper script.

## Cloning Configurations

### Clone and Customize Workflow

When user wants to clone an existing sandbox for a new project:

```
User: "Create a duplicate of ~/Sandboxes/aaronbassett/project1 for myproject2"
```

Workflow:
1. **Read existing config**
2. **Detect new project languages** (if repository provided)
3. **Compare and identify differences**
4. **Ask user about discrepancies**
5. **Merge preferences**
6. **Write new config**

Example:

```python
# Read existing
existing = read_config("~/Sandboxes/aaronbassett/project1/Sandbox.toml")

# Detect new project (

Related in Writing & Docs