* Commit first run

* Checkpoint

* Checkpoint

* Checkpoint

* Checkpoint

* Checkpoint

* Checkpoint

* Checkpoint

* Checkpoint

* Checkpoint

* Checkpoint

* Checkpoint

* Copy credentials

* Add setupcommands

* Can push from inside the container

* Checkpoint

* Can launch dev server in sandbox

* Checkpoint

* Checkpoint

* Run prettier

* Checkpoint
This commit is contained in:
Onur Solmaz 2025-05-27 00:36:20 +02:00 committed by GitHub
parent 677713106b
commit b44cf1a84e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
39 changed files with 16222 additions and 279 deletions

8
.gitignore vendored
View file

@ -1 +1,9 @@
node_modules/
dist/
.env
.env.local
*.log
.DS_Store
claude-sandbox.config.json
!claude-sandbox.config.example.json
reference-repos/

80
CLAUDE.md Normal file
View file

@ -0,0 +1,80 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Overview
This is the Claude Code Sandbox project - a CLI tool that runs Claude Code instances inside isolated Docker containers with automatic git integration. The tool creates safe sandboxed environments where Claude can execute commands and make code changes without affecting the host system.
## Common Development Commands
### Build and Development
- `npm run build` - Compile TypeScript to JavaScript (output in `dist/`)
- `npm run dev` - Watch mode for TypeScript compilation
- `npm start` - Run the CLI tool
### Testing and Quality
- `npm run lint` - Run ESLint on TypeScript files
- `npm test` - Run Jest tests
### Container Management
- `npm run purge-containers` - Remove all Claude Sandbox containers and images
## Architecture
### Core Components
1. **CLI Entry Point** (`src/cli.ts`)
- Command-line interface using Commander.js
- Handles options parsing and main flow orchestration
2. **Container Management** (`src/container.ts`)
- Docker container lifecycle management using dockerode
- Builds images, creates containers, handles streams
- Manages volume mounts for credentials and workspace
3. **Git Integration** (`src/git-monitor.ts`)
- Monitors git repository for new commits
- Uses simple-git for operations
- Provides real-time notifications of Claude's commits
4. **Credential Discovery** (`src/credentials.ts`)
- Automatically discovers Claude API keys (Anthropic, AWS Bedrock, Google Vertex)
- Discovers GitHub credentials (CLI auth, SSH keys)
- Mounts credentials read-only into containers
5. **Configuration** (`src/config.ts`)
- Loads and validates configuration from `claude-sandbox.config.json`
- Manages Docker settings, environment variables, and Claude parameters
6. **UI Components** (`src/ui.ts`)
- Interactive prompts using inquirer
- Diff display with syntax highlighting
- Commit review interface
### Key Design Decisions
- Claude runs with `--dangerously-skip-permissions` flag (safe within container isolation)
- Git wrapper prevents branch switching to protect main branch
- All credentials are mounted read-only
- Each session creates a new branch (`claude/[timestamp]`)
- Real-time commit monitoring with interactive review
## Configuration
The tool looks for `claude-sandbox.config.json` in the working directory. Key options:
- `dockerImage`: Base image name
- `dockerfile`: Path to custom Dockerfile
- `environment`: Additional environment variables
- `volumes`: Additional volume mounts
- `allowedTools`: Claude tool permissions (default: all)
- `autoPush`/`autoCreatePR`: Git workflow settings

350
README.md Normal file
View file

@ -0,0 +1,350 @@
# Claude Code Sandbox
Run Claude Code as an autonomous agent inside Docker containers with automatic git integration.
## Why Claude Code Sandbox?
The primary goal of Claude Code Sandbox is to enable **full async agentic workflows** by allowing Claude Code to execute without permission prompts. By running Claude in an isolated Docker container with the `--dangerously-skip-permissions` flag, Claude can:
- Execute any command instantly without asking for permission
- Make code changes autonomously
- Run build tools, tests, and development servers
- Create commits and manage git operations
- Work continuously without interrupting the user
This creates a truly autonomous development assistant that can work asynchronously while you focus on other tasks, similar to [OpenAI Codex](https://chatgpt.com/codex) or [Google Jules](https://jules.dev), but running locally on your machine.
## Overview
Claude Code Sandbox allows you to run Claude Code in isolated Docker containers, providing a safe environment for AI-assisted development. It automatically:
- Creates a new git branch for each session
- Monitors for commits made by Claude
- Provides interactive review of changes
- Handles credential forwarding securely
- Enables push/PR creation workflows
- Runs custom setup commands for environment initialization
## Installation
Claude Code Sandbox must be built from source:
```bash
git clone https://github.com/your-repo/claude-code-sandbox.git
cd claude-code-sandbox
npm install
npm run build
npm link # Creates global 'claude-sandbox' command
```
### Prerequisites
- Node.js >= 18.0.0
- Docker
- Git
- Claude Code (`npm install -g @anthropic-ai/claude-code@latest`)
## Usage
### Basic Usage
Simply run in any git repository:
```bash
claude-sandbox
```
This will:
1. Create a new branch (`claude/[timestamp]`)
2. Start a Docker container with Claude Code
3. Forward your credentials automatically
4. Open an interactive session with Claude
### Command Options
```bash
claude-sandbox [options]
Options:
-c, --config <path> Path to configuration file (default: ./claude-sandbox.config.json)
-d, --detached Run in detached mode
-n, --name <name> Container name prefix
--no-push Disable automatic branch pushing
--no-pr Disable automatic PR creation
-h, --help Display help
-V, --version Display version
```
### Configuration
Create a `claude-sandbox.config.json` file (see `claude-sandbox.config.example.json` for reference):
```json
{
"dockerImage": "claude-code-sandbox:latest",
"dockerfile": "./custom.Dockerfile",
"detached": false,
"autoPush": true,
"autoCreatePR": true,
"autoStartClaude": true,
"envFile": ".env",
"environment": {
"NODE_ENV": "development"
},
"setupCommands": ["npm install", "npm run build"],
"volumes": ["/host/path:/container/path:ro"],
"mounts": [
{
"source": "./data",
"target": "/workspace/data",
"readonly": false
},
{
"source": "/home/user/configs",
"target": "/configs",
"readonly": true
}
],
"allowedTools": ["*"],
"maxThinkingTokens": 100000,
"bashTimeout": 600000,
"containerPrefix": "my-project",
"claudeConfigPath": "~/.claude.json"
}
```
#### Configuration Options
- `dockerImage`: Base Docker image to use (default: `claude-code-sandbox:latest`)
- `dockerfile`: Path to custom Dockerfile (optional)
- `detached`: Run container in detached mode
- `autoPush`: Automatically push branches after commits
- `autoCreatePR`: Automatically create pull requests
- `autoStartClaude`: Start Claude Code automatically (default: true)
- `envFile`: Load environment variables from file (e.g., `.env`)
- `environment`: Additional environment variables
- `setupCommands`: Commands to run after container starts (e.g., install dependencies)
- `volumes`: Legacy volume mounts (string format)
- `mounts`: Modern mount configuration (object format)
- `allowedTools`: Claude tool permissions (default: all)
- `maxThinkingTokens`: Maximum thinking tokens for Claude
- `bashTimeout`: Timeout for bash commands in milliseconds
- `containerPrefix`: Custom prefix for container names
- `claudeConfigPath`: Path to Claude configuration file
#### Mount Configuration
The `mounts` array allows you to mount files or directories into the container:
- `source`: Path on the host (relative paths are resolved from current directory)
- `target`: Path in the container (relative paths are resolved from /workspace)
- `readonly`: Optional boolean to make the mount read-only (default: false)
Example use cases:
- Mount data directories that shouldn't be in git
- Share configuration files between host and container
- Mount build artifacts or dependencies
- Access host system resources (use with caution)
## Features
### Automatic Credential Discovery
Claude Code Sandbox automatically discovers and forwards:
**Claude Credentials:**
- Anthropic API keys (`ANTHROPIC_API_KEY`)
- macOS Keychain credentials (Claude Code)
- AWS Bedrock credentials
- Google Vertex credentials
- Claude configuration files (`.claude.json`, `.claude/`)
**GitHub Credentials:**
- GitHub CLI authentication (`gh auth`)
- GitHub tokens (`GITHUB_TOKEN`, `GH_TOKEN`)
- Git configuration (`.gitconfig`)
### Sandboxed Execution
- Claude runs with `--dangerously-skip-permissions` flag (safe in container)
- Creates isolated branch for each session
- Full access to run any command within the container
- Files are copied into container (not mounted) for true isolation
- Git history preserved for proper version control
### Commit Monitoring
When Claude makes a commit:
1. Real-time notification appears
2. Full diff is displayed with syntax highlighting
3. Interactive menu offers options:
- Continue working
- Push branch to remote
- Push branch and create PR
- Exit
### Asynchronous Operation
Run multiple instances simultaneously:
```bash
# Terminal 1
claude-sandbox
# Terminal 2
claude-sandbox --name project-feature
# Terminal 3
claude-sandbox --detached --name background-task
```
## Docker Environment
### Default Image
The default Docker image includes:
- Ubuntu 22.04
- Git, GitHub CLI
- Node.js, npm
- Python 3
- Claude Code (latest)
- Build essentials
### Custom Dockerfile
Create a custom environment:
```dockerfile
FROM claude-code-sandbox:latest
# Add your tools
RUN apt-get update && apt-get install -y \
rust \
cargo \
postgresql-client
# Install project dependencies
COPY package.json /tmp/
RUN cd /tmp && npm install
# Custom configuration
ENV CUSTOM_VAR=value
```
Reference in config:
```json
{
"dockerfile": "./my-custom.Dockerfile"
}
```
## Workflow Example
1. **Start Claude Sandbox:**
```bash
cd my-project
claude-sandbox
```
2. **Interact with Claude:**
```
> Help me refactor the authentication module to use JWT tokens
```
3. **Claude works autonomously:**
- Explores codebase
- Makes changes
- Runs tests
- Commits changes
4. **Review and push:**
- See commit notification
- Review syntax-highlighted diff
- Choose to push and create PR
## Security Considerations
- Credentials are mounted read-only
- Containers are isolated from host
- Branch restrictions prevent accidental main branch modifications
- All changes require explicit user approval before pushing
## Troubleshooting
### Claude Code not found
Ensure Claude Code is installed globally:
```bash
npm install -g @anthropic-ai/claude-code@latest
```
### Docker permission issues
Add your user to the docker group:
```bash
sudo usermod -aG docker $USER
# Log out and back in for changes to take effect
```
### Container cleanup
Remove all Claude Sandbox containers and images:
```bash
npm run purge-containers
```
### Credential discovery fails
Set credentials explicitly:
```bash
export ANTHROPIC_API_KEY=your-key
export GITHUB_TOKEN=your-token
```
Or use an `.env` file with `envFile` config option.
### Build errors
Ensure you're using Node.js >= 18.0.0:
```bash
node --version
```
## Development
### Available Scripts
- `npm run build` - Build TypeScript to JavaScript
- `npm run dev` - Watch mode for development
- `npm start` - Run the CLI
- `npm run lint` - Run ESLint
- `npm test` - Run tests
- `npm run purge-containers` - Clean up all containers
## Contributing
1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Run tests: `npm test`
5. Run linter: `npm run lint`
6. Submit a pull request
## License
MIT

3
TODO.md Normal file
View file

@ -0,0 +1,3 @@
- [ ] Flag for including vs not including non-tracked files
- [ ] Fix terminal output
- [ ] Create listener for Claude turn end, to commit, push and create a PR

View file

@ -0,0 +1,31 @@
{
"dockerImage": "claude-code-sandbox:latest",
"dockerfile": null,
"detached": false,
"autoPush": true,
"autoCreatePR": true,
"autoStartClaude": true,
"envFile": ".env",
"environment": {
"NODE_ENV": "development"
},
"setupCommands": ["npm install", "npm run build"],
"volumes": [],
"mounts": [
{
"source": "./data",
"target": "/workspace/data",
"readonly": false
},
{
"source": "/home/user/shared-configs",
"target": "/configs",
"readonly": true
}
],
"allowedTools": ["*"],
"maxThinkingTokens": 100000,
"bashTimeout": 600000,
"containerPrefix": "claude-code-sandbox",
"claudeConfigPath": "~/.claude.json"
}

94
docker/Dockerfile Normal file
View file

@ -0,0 +1,94 @@
FROM ubuntu:22.04
# Prevent interactive prompts during package installation
ENV DEBIAN_FRONTEND=noninteractive
# Install system dependencies
RUN apt-get update && apt-get install -y \
curl \
git \
openssh-client \
python3 \
python3-pip \
build-essential \
sudo \
vim \
jq \
ca-certificates \
gnupg \
&& rm -rf /var/lib/apt/lists/*
# Install Node.js 20.x
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
&& apt-get install -y nodejs
# Install GitHub CLI
RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \
&& chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
&& apt-get update \
&& apt-get install -y gh
# Install Claude Code
RUN npm install -g @anthropic-ai/claude-code@latest
# Create workspace directory
RUN mkdir -p /workspace
WORKDIR /workspace
# Create a wrapper script for git that prevents branch switching
RUN echo '#!/bin/bash\n\
# Allow the initial branch creation\n\
if [ ! -f /tmp/.branch-created ]; then\n\
/usr/bin/git.real "$@"\n\
if [[ "$1" == "checkout" ]] && [[ "$2" == "-b" ]]; then\n\
touch /tmp/.branch-created\n\
fi\n\
else\n\
# After initial branch creation, prevent switching\n\
if [[ "$1" == "checkout" ]] && [[ "$2" != "-b" ]] && [[ "$*" != *"--"* ]]; then\n\
echo "Error: Branch switching is disabled in claude-code-sandbox"\n\
echo "You can only create new branches with git checkout -b"\n\
exit 1\n\
fi\n\
if [[ "$1" == "switch" ]]; then\n\
echo "Error: Branch switching is disabled in claude-code-sandbox"\n\
exit 1\n\
fi\n\
/usr/bin/git.real "$@"\n\
fi' > /usr/local/bin/git-wrapper && \
chmod +x /usr/local/bin/git-wrapper && \
mv /usr/bin/git /usr/bin/git.real && \
ln -s /usr/local/bin/git-wrapper /usr/bin/git
# Set up SSH config
RUN mkdir -p /root/.ssh && \
echo "Host github.com\n\
StrictHostKeyChecking no\n\
UserKnownHostsFile /dev/null" > /root/.ssh/config && \
chmod 600 /root/.ssh/config
# Set git to use credential helper
RUN git config --global credential.helper 'cache --timeout=3600'
# Create entrypoint script
RUN echo '#!/bin/bash\n\
set -e\n\
\n\
# Copy SSH keys if mounted\n\
if [ -d "/tmp/.ssh" ]; then\n\
cp -r /tmp/.ssh/* /root/.ssh/ 2>/dev/null || true\n\
chmod 600 /root/.ssh/* 2>/dev/null || true\n\
fi\n\
\n\
# Copy git config if mounted\n\
if [ -f "/tmp/.gitconfig" ]; then\n\
cp /tmp/.gitconfig /root/.gitconfig\n\
fi\n\
\n\
# Execute the command\n\
exec "$@"' > /entrypoint.sh && \
chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["bash"]

View file

@ -1,23 +1,27 @@
## Claude Sandbox Requirements Summary
### Core Concept
Claude-sandbox is a tool that runs Claude Code as an interactive agent inside Docker containers, providing a sandboxed environment for autonomous coding with git integration.
### Key Functional Requirements
#### 1. **Launch Behavior**
- Simple command: just type `claude-sandbox` in any git repository
- No pre-specified task - users interact with Claude directly after launch
- Claude Code runs as an interactive REPL (like a smart terminal)
- Maintains persistent context throughout the session (never exits)
#### 2. **Sandboxing**
- Runs inside Docker container for complete isolation
- Claude has full permissions to run any command (since it's sandboxed)
- No permission prompts - everything is auto-allowed
- Environment can be customized via Dockerfile configuration
#### 3. **Credential Management**
- Automatically discovers and forwards Claude credentials from host:
- Claude Max OAuth tokens
- Anthropic API keys
@ -28,12 +32,21 @@ Claude-sandbox is a tool that runs Claude Code as an interactive agent inside Do
- Git configuration
#### 4. **Git Workflow**
- Container automatically starts on a new branch (never on main)
- Branch naming: `claude/[timestamp]`
- Claude can make commits but cannot switch branches
- Git wrapper prevents branch switching operations
- **CRITICAL**: NO branch switching happens on the host machine - EVER
- Host repository stays on whatever branch the user is currently on
- **CRITICAL**: Files must be COPIED into the container, NOT mounted
- This ensures git operations in the container don't affect the host
- Container gets a snapshot of the current working directory
- Changes made in container don't affect host until explicitly exported
- Inside the container:
- A new branch `claude/[timestamp]` is created from the current state
- All work happens on this new branch
- Claude can make commits but cannot switch to other branches
- Git wrapper prevents branch switching operations within container
#### 5. **Change Detection & Review**
- Real-time monitoring for new commits
- When commit detected:
- User gets notification
@ -47,6 +60,7 @@ Claude-sandbox is a tool that runs Claude Code as an interactive agent inside Do
- Exit
#### 6. **Asynchronous Operation**
- Multiple containers can run simultaneously
- Each gets its own branch and isolated environment
- Fire-and-forget model for parallel work
@ -54,18 +68,21 @@ Claude-sandbox is a tool that runs Claude Code as an interactive agent inside Do
### Technical Implementation Details
#### Docker Container Setup
- Base image with all necessary tools (git, gh CLI, build tools)
- Claude Code installed globally
- SSH configured for GitHub
- Auto-permission wrapper to bypass all prompts
#### Monitoring System
- Watches for file changes
- Detects git commits
- Tracks Claude's activity state
- Determines when tasks are complete
#### User Experience Flow
1. Run `claude-sandbox` in repo
2. System creates new branch
3. Docker container starts with Claude Code
@ -76,6 +93,7 @@ Claude-sandbox is a tool that runs Claude Code as an interactive agent inside Do
8. Choose to push/PR after review
### Design Principles
- **Zero configuration** - works out of the box
- **Natural interaction** - chat with Claude like normal
- **Full visibility** - see all changes before they leave the machine

View file

@ -9,12 +9,13 @@ description: "Configure Claude Code to work with Amazon Bedrock and Google Verte
tags:
- "clippings"
---
## Model configuration
Claude Code uses the following defaults:
| Provider | Default Model |
| --- | --- |
| ----------------- | -------------------------------------------------------------------------------- |
| Anthropic Console | `claude-sonnet-4-20250514` |
| Claude Max | `claude-opus-4-20250514` or `claude-sonnet-4-20250514` based on Max usage limits |
| Amazon Bedrock | `claude-3-7-sonnet-20250219` |

View file

@ -9,6 +9,7 @@ description: "Learn how to use Claude Code from the command line, including CLI
tags:
- "clippings"
---
## Getting started
Claude Code provides two main ways to interact:
@ -19,7 +20,7 @@ Claude Code provides two main ways to interact:
## CLI commands
| Command | Description | Example |
| --- | --- | --- |
| ---------------------------------- | ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `claude` | Start interactive REPL | `claude` |
| `claude "query"` | Start REPL with initial prompt | `claude "explain this project"` |
| `claude -p "query"` | Run one-off query, then exit | `claude -p "explain this function"` |
@ -36,7 +37,7 @@ Claude Code provides two main ways to interact:
Customize Claude Codes behavior with these command-line flags:
| Flag | Description | Example |
| --- | --- | --- |
| -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
| `--print`, `-p` | Print response without interactive mode (see [SDK documentation](https://docs.anthropic.com/en/docs/claude-code/sdk) for programmatic usage details) | `claude -p "query"` |
| `--output-format` | Specify output format for print mode (options: `text`, `json`, `stream-json`) | `claude -p "query" --output-format json` |
| `--verbose` | Enable verbose logging, shows full turn-by-turn output (helpful for debugging in both print and interactive modes) | `claude --verbose` |
@ -54,7 +55,7 @@ For detailed information about print mode (`-p`) including output formats, strea
Control Claudes behavior during an interactive session:
| Command | Purpose |
| --- | --- |
| ------------------------- | --------------------------------------------------------------------- |
| `/bug` | Report bugs (sends conversation to Anthropic) |
| `/clear` | Clear conversation history |
| `/compact [instructions]` | Compact conversation with optional focus instructions |
@ -75,7 +76,7 @@ Control Claudes behavior during an interactive session:
## Special shortcuts
### Quick memory with #
### Quick memory with
Add memories instantly by starting your input with `#`:

View file

@ -9,6 +9,7 @@ description: "Learn about Claude Code, an agentic coding tool made by Anthropic.
tags:
- "clippings"
---
Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster through natural language commands. By integrating directly with your development environment, Claude Code streamlines your workflow without requiring additional servers or complex setup.
Claude Codes key capabilities include:

View file

@ -9,6 +9,7 @@ description: "Learn how to configure Claude Code with global and project-level s
tags:
- "clippings"
---
Claude Code offers a variety of settings to configure its behavior to meet your needs. You can configure Claude Code by running `claude config` in your terminal, or the `/config` command when using the interactive REPL.
## Configuration hierarchy
@ -26,7 +27,7 @@ Example settings.json
`settings.json` supports a number of options:
| Key | Description | Example |
| --- | --- | --- |
| --------------------- | -------------------------------------------------------------------------------------------------------- | ------------------------------- |
| `apiKeyHelper` | Custom script to generate an Anthropic API key | `/bin/generate_temp_api_key.sh` |
| `cleanupPeriodDays` | How long to locally retain chat transcripts (default: 30 days) | `20` |
| `env` | Environment variables that will be applied to every session | `{"FOO": "bar"}` |
@ -61,7 +62,7 @@ By default `config` changes your project configuration. To manage your global co
To set a global configuration, use `claude config set -g <key> <value>`:
| Key | Description | Example |
| --- | --- | --- |
| ----------------------- | ---------------------------------------------------------------- | -------------------------------------------------------------------------- |
| `autoUpdaterStatus` | Enable or disable the auto-updater (default: `enabled`) | `disabled` |
| `preferredNotifChannel` | Where you want to receive notifications (default: `iterm2`) | `iterm2`, `iterm2_with_bell`, `terminal_bell`, or `notifications_disabled` |
| `theme` | Color theme | `dark`, `light`, `light-daltonized`, or `dark-daltonized` |
@ -94,7 +95,7 @@ MCP tool names follow the format: `mcp__server_name__tool_name` where:
More examples:
| Rule | Description |
| --- | --- |
| ------------------------------------ | ---------------------------------------------------------------------------------------------------- |
| `Bash(npm run build)` | Matches the exact Bash command `npm run build`. |
| `Bash(npm run test:*)` | Matches Bash commands starting with `npm run test`. See note below about command separator handling. |
| `Edit(~/.zshrc)` | Matches the `~/.zshrc` file. |
@ -223,7 +224,7 @@ Claude Code supports the following environment variables to control its behavior
All environment variables can also be configured in [`settings.json`](https://docs.anthropic.com/en/docs/claude-code/settings#available-settings). This is useful as a way to automatically set environment variables for each session, or to roll out a set of environment variables for your whole team or organization.
| Variable | Purpose |
| --- | --- |
| ------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ANTHROPIC_AUTH_TOKEN` | Custom value for the `Authorization` and `Proxy-Authorization` headers (the value you set here will be prefixed with `Bearer `) |
| `ANTHROPIC_CUSTOM_HEADERS` | Custom headers you want to add to the request (in `Name: Value` format) |
| `ANTHROPIC_MODEL` | Name of custom model to use (see [Model Configuration](https://docs.anthropic.com/en/docs/claude-code/bedrock-vertex-proxies#model-configuration)) |

View file

@ -9,6 +9,7 @@ description: "Explore Claude Code's powerful features for editing, searching, te
tags:
- "clippings"
---
Claude Code operates directly in your terminal, understanding your project context and taking real actions. No need to manually add files to context - Claude will explore your codebase as needed.
## Understand unfamiliar code

View file

@ -9,6 +9,7 @@ description: "Learn how to install, authenticate, and start using Claude Code."
tags:
- "clippings"
---
## Check system requirements
- **Operating Systems**: macOS 10.15+, Ubuntu 20.04+/Debian 10+, or Windows via WSL

View file

@ -9,6 +9,7 @@ description: "Integrate Claude Code with your GitHub workflows for automated cod
tags:
- "clippings"
---
Claude Code GitHub Actions brings AI-powered automation to your GitHub workflow. With a simple `@claude` mention in any PR or issue, Claude can analyze your code, create pull requests, implement features, and fix bugs - all while following your projects standards.
Claude Code GitHub Actions is currently in beta. Features and functionality may evolve as we refine the experience.
@ -53,7 +54,7 @@ This command will guide you through setting up the GitHub app and required secre
If the `/install-github-app` command fails or you prefer manual setup, please follow these manual setup instructions:
1. **Install the Claude GitHub app** to your repository: [https://github.com/apps/claude](https://github.com/apps/claude)
2. **Add ANTHROPIC\_API\_KEY** to your repository secrets ([Learn how to use secrets in GitHub Actions](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions))
2. **Add ANTHROPIC_API_KEY** to your repository secrets ([Learn how to use secrets in GitHub Actions](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions))
3. **Copy the workflow file** from [examples/claude.yml](https://github.com/anthropics/claude-code-action/blob/main/examples/claude.yml) into your repositorys `.github/workflows/`
## Example use cases
@ -167,7 +168,7 @@ jobs:
"View", # Read file contents
"GlobTool", # Find files by pattern
"GrepTool", # Search file contents
"BatchTool" # Run multiple tools in parallel
"BatchTool", # Run multiple tools in parallel
]
# Your Anthropic API key (stored as a GitHub secret)
@ -208,7 +209,7 @@ jobs:
"Bash(git diff HEAD~1)", # See actual changes
"View", # Read file contents
"GlobTool", # Find related files
"GrepTool" # Search for patterns
"GrepTool", # Search for patterns
]
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
@ -229,14 +230,14 @@ Before setting up Claude Code GitHub Actions with cloud providers, you need:
1. A Google Cloud Project with Vertex AI enabled
2. Workload Identity Federation configured for GitHub Actions
3. A service account with the required permissions
4. A GitHub App (recommended) or use the default GITHUB\_TOKEN
4. A GitHub App (recommended) or use the default GITHUB_TOKEN
#### For AWS Bedrock:
1. An AWS account with Amazon Bedrock enabled
2. GitHub OIDC Identity Provider configured in AWS
3. An IAM role with Bedrock permissions
4. A GitHub App (recommended) or use the default GITHUB\_TOKEN
4. A GitHub App (recommended) or use the default GITHUB_TOKEN
## Troubleshooting
@ -257,7 +258,7 @@ Confirm API key is valid and has sufficient permissions. For Bedrock/Vertex, che
The Claude Code Action supports these key parameters:
| Parameter | Description | Required |
| --- | --- | --- |
| ------------------- | ------------------------------ | -------- |
| `prompt` | The prompt to send to Claude | Yes\* |
| `prompt_file` | Path to file containing prompt | Yes\* |
| `allowed_tools` | Array of allowed tools | No |

View file

@ -9,6 +9,7 @@ description: "Integrate Claude Code with your favorite development environments"
tags:
- "clippings"
---
Claude Code seamlessly integrates with popular Integrated Development Environments (IDEs) to enhance your coding workflow. This integration allows you to leverage Claudes capabilities directly within your preferred development environment.
## Supported IDEs

View file

@ -9,6 +9,7 @@ description: "Learn how to manage Claude Code's memory across sessions with diff
tags:
- "clippings"
---
Claude Code can remember your preferences across sessions, like style guidelines and common commands in your workflow.
## Determine memory type
@ -16,10 +17,10 @@ Claude Code can remember your preferences across sessions, like style guidelines
Claude Code offers three memory locations, each serving a different purpose:
| Memory Type | Location | Purpose | Use Case Examples |
| --- | --- | --- | --- |
| -------------------------- | --------------------- | ---------------------------------------- | ---------------------------------------------------------------- |
| **Project memory** | `./CLAUDE.md` | Team-shared instructions for the project | Project architecture, coding standards, common workflows |
| **User memory** | `~/.claude/CLAUDE.md` | Personal preferences for all projects | Code styling preferences, personal tooling shortcuts |
| **Project memory (local)** | `./CLAUDE.local.md` | Personal project-specific preferences | *(Deprecated, see below)* Your sandbox URLs, preferred test data |
| **Project memory (local)** | `./CLAUDE.local.md` | Personal project-specific preferences | _(Deprecated, see below)_ Your sandbox URLs, preferred test data |
All memory files are automatically loaded into Claude Codes context when launched.
@ -35,7 +36,7 @@ Imported files can recursively import additional files, with a max-depth of 5 ho
## How Claude looks up memories
Claude Code reads memories recursively: starting in the cwd, Claude Code recurses up to */* and reads any CLAUDE.md or CLAUDE.local.md files it finds. This is especially convenient when working in large repositories where you run Claude Code in *foo/bar/*, and have memories in both *foo/CLAUDE.md* and *foo/bar/CLAUDE.md*.
Claude Code reads memories recursively: starting in the cwd, Claude Code recurses up to _/_ and reads any CLAUDE.md or CLAUDE.local.md files it finds. This is especially convenient when working in large repositories where you run Claude Code in _foo/bar/_, and have memories in both _foo/CLAUDE.md_ and _foo/bar/CLAUDE.md_.
Claude will also discover CLAUDE.md nested in subtrees under your current working directory. Instead of loading them at launch, they are only included when Claude reads files in those subtrees.

View file

@ -9,6 +9,7 @@ description: "Learn how to track and optimize token usage and costs when using C
tags:
- "clippings"
---
Claude Code consumes tokens for each interaction. The average cost is $6 per developer per day, with daily costs remaining below $12 for 90% of users.
## Track your costs

View file

@ -9,10 +9,11 @@ description: "Learn about Claude Code's permission system, tools access, and sec
tags:
- "clippings"
---
Claude Code uses a tiered permission system to balance power and safety:
| Tool Type | Example | Approval Required | ”Yes, dont ask again” Behavior |
| --- | --- | --- | --- |
| ----------------- | -------------------- | ----------------- | --------------------------------------------- |
| Read-only | File reads, LS, Grep | No | N/A |
| Bash Commands | Shell execution | Yes | Permanently per project directory and command |
| File Modification | Edit/write files | Yes | Until session end |
@ -22,7 +23,7 @@ Claude Code uses a tiered permission system to balance power and safety:
Claude Code has access to a set of powerful tools that help it understand and modify your codebase:
| Tool | Description | Permission Required |
| --- | --- | --- |
| ---------------- | ---------------------------------------------------- | ------------------- |
| **Agent** | Runs a sub-agent to handle complex, multi-step tasks | No |
| **Bash** | Executes shell commands in your environment | Yes |
| **Glob** | Finds files based on pattern matching | No |

View file

@ -9,6 +9,7 @@ description: "Monitor Claude Code usage with OpenTelemetry metrics"
tags:
- "clippings"
---
OpenTelemetry support is currently in beta and details are subject to change.
## OpenTelemetry in Claude Code
@ -43,7 +44,7 @@ Managed settings can be distributed via MDM (Mobile Device Management) or other
### Common Configuration Variables
| Environment Variable | Description | Example Values |
| --- | --- | --- |
| ----------------------------------------------- | ------------------------------------------------ | ------------------------------------ |
| `CLAUDE_CODE_ENABLE_TELEMETRY` | Enables telemetry collection (required) | `1` |
| `OTEL_METRICS_EXPORTER` | Exporter type(s) to use (comma-separated) | `console`, `otlp`, `prometheus` |
| `OTEL_EXPORTER_OTLP_PROTOCOL` | Protocol for OTLP exporter | `grpc`, `http/json`, `http/protobuf` |
@ -58,10 +59,10 @@ Managed settings can be distributed via MDM (Mobile Device Management) or other
The following environment variables control which attributes are included in metrics to manage cardinality:
| Environment Variable | Description | Default Value | Example to Disable |
| --- | --- | --- | --- |
| ----------------------------------- | ---------------------------------------------- | ------------- | ------------------ |
| `OTEL_METRICS_INCLUDE_SESSION_ID` | Include session.id attribute in metrics | `true` | `false` |
| `OTEL_METRICS_INCLUDE_VERSION` | Include app.version attribute in metrics | `false` | `true` |
| `OTEL_METRICS_INCLUDE_ACCOUNT_UUID` | Include user.account\_uuid attribute in metrics | `true` | `false` |
| `OTEL_METRICS_INCLUDE_ACCOUNT_UUID` | Include user.account_uuid attribute in metrics | `true` | `false` |
These variables help control the cardinality of metrics, which affects storage requirements and query performance in your metrics backend. Lower cardinality generally means better performance and lower storage costs but less granular data for analysis.
@ -72,7 +73,7 @@ These variables help control the cardinality of metrics, which affects storage r
Claude Code exports the following metrics:
| Metric Name | Description | Unit |
| --- | --- | --- |
| --------------------------------- | ------------------------------- | ------ |
| `claude_code.session.count` | Count of CLI sessions started | count |
| `claude_code.lines_of_code.count` | Count of lines of code modified | count |
| `claude_code.pull_request.count` | Number of pull requests created | count |
@ -126,7 +127,7 @@ These metrics provide insights into usage patterns, productivity, and costs:
### Usage Monitoring
| Metric | Analysis Opportunity |
| --- | --- |
| ------------------------------------------------------------- | --------------------------------------------------------- |
| `claude_code.token.usage` | Break down by `type` (input/output), user, team, or model |
| `claude_code.session.count` | Track adoption and engagement over time |
| `claude_code.lines_of_code.count` | Measure productivity by tracking code additions/removals |
@ -154,7 +155,7 @@ All metrics can be segmented by `user.account_uuid`, `organization.id`, `session
## Backend Considerations
| Backend Type | Best For |
| --- | --- |
| -------------------------------------------- | ------------------------------------------ |
| Time series databases (Prometheus) | Rate calculations, aggregated metrics |
| Columnar stores (ClickHouse) | Complex queries, unique user analysis |
| Observability platforms (Honeycomb, Datadog) | Advanced querying, visualization, alerting |

View file

@ -9,6 +9,7 @@ description: "Programmatically integrate Claude Code into your applications usin
tags:
- "clippings"
---
The Claude Code SDK allows developers to programmatically integrate Claude Code into their applications. It enables running Claude Code as a subprocess, providing a way to build AI-powered coding assistants and tools that leverage Claudes capabilities.
The SDK currently support command line usage. TypeScript and Python SDKs are coming soon.
@ -49,7 +50,7 @@ This security measure ensures that MCP tools are only used when explicitly permi
The SDK leverages all the CLI options available in Claude Code. Here are the key ones for SDK usage:
| Flag | Description | Example |
| --- | --- | --- |
| -------------------------- | ---------------------------------------------------------------- | -------------------------------------------------------------- |
| `--print`, `-p` | Run in non-interactive mode | `claude -p "query"` |
| `--output-format` | Specify output format (`text`, `json`, `stream-json`) | `claude -p --output-format json` |
| `--resume`, `-r` | Resume a conversation by session ID | `claude --resume abc123` |

View file

@ -9,6 +9,7 @@ description: "Learn how to onboard your team to Claude Code, including user mana
tags:
- "clippings"
---
## User management
Setting up Claude Code requires access to Anthropic models. For teams, you can set up Claude Code access in one of three ways:
@ -89,7 +90,7 @@ When users run the `/bug` command, a copy of their full conversation history inc
By default, we disable all non-essential traffic (including error reporting, telemetry, and bug reporting functionality) when using Bedrock or Vertex. You can also opt out of all of these at once by setting the `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` environment variable. Here are the full default behaviors:
| Service | Anthropic API | Vertex API | Bedrock API |
| --- | --- | --- | --- |
| ---------------------------------- | --------------------------------------------------- | ------------------------------------------------ | ------------------------------------------------- |
| **Statsig (Metrics)** | Default on. `DISABLE_TELEMETRY=1` to disable. | Default off. `CLAUDE_CODE_USE_VERTEX` must be 1. | Default off. `CLAUDE_CODE_USE_BEDROCK` must be 1. |
| **Sentry (Errors)** | Default on. `DISABLE_ERROR_REPORTING=1` to disable. | Default off. `CLAUDE_CODE_USE_VERTEX` must be 1. | Default off. `CLAUDE_CODE_USE_BEDROCK` must be 1. |
| **Anthropic API (`/bug` reports)** | Default on. `DISABLE_BUG_COMMAND=1` to disable. | Default off. `CLAUDE_CODE_USE_VERTEX` must be 1. | Default off. `CLAUDE_CODE_USE_BEDROCK` must be 1. |

View file

@ -9,6 +9,7 @@ description: "Solutions for common issues with Claude Code installation and usag
tags:
- "clippings"
---
## Common installation issues
When installing Claude Code with npm, you may encounter permission errors if your npm global prefix is not user writable (eg. `/usr`, or `/use/local`).

View file

@ -9,6 +9,7 @@ description: "Practical examples and patterns for effectively using Claude Code
tags:
- "clippings"
---
This guide provides step-by-step tutorials for common workflows with Claude Code. Each tutorial includes clear instructions, example commands, and best practices to help you get the most from Claude Code.
- [Resume previous conversations](https://docs.anthropic.com/en/docs/claude-code/tutorials#resume-previous-conversations)
@ -213,7 +214,7 @@ Use third party MCP servers at your own risk. Make sure you trust the MCP server
- `project`: Shared with everyone in the project via `.mcp.json` file
- `user`: Available to you across all projects (was called `global` in older versions)
- Set environment variables with `-e` or `--env` flags (e.g., `-e KEY=value`)
- Configure MCP server startup timeout using the MCP\_TIMEOUT environment variable (e.g., `MCP_TIMEOUT=10000 claude` sets a 10-second timeout)
- Configure MCP server startup timeout using the MCP_TIMEOUT environment variable (e.g., `MCP_TIMEOUT=10000 claude` sets a 10-second timeout)
- Check MCP server status any time using the `/mcp` command within Claude Code
- MCP follows a client-server architecture where Claude Code (the client) can connect to multiple specialized servers

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,260 @@
# Environment Variables
This document explains how to pass environment variables to Claude Sandbox containers.
## Overview
Claude Sandbox supports two ways to pass environment variables to containers:
1. **Inline environment variables** in the configuration file
2. **Loading from a `.env` file**
Both methods can be used together, with inline variables taking precedence over those loaded from a file.
## Configuration
### Inline Environment Variables
Add environment variables directly in your `claude-sandbox.config.json`:
```json
{
"environment": {
"API_KEY": "your-api-key",
"DATABASE_URL": "postgresql://user:pass@host:5432/db",
"NODE_ENV": "development",
"DEBUG": "true"
}
}
```
### Loading from .env File
Specify a path to a `.env` file to load:
```json
{
"envFile": ".env",
"environment": {
"OVERRIDE_VAR": "this-overrides-env-file"
}
}
```
The `.env` file format:
```bash
# Comments are supported
API_KEY=your-api-key
DATABASE_URL=postgresql://user:pass@host:5432/db
# Empty lines are ignored
# Quotes are optional but removed if present
QUOTED_VAR="value with spaces"
SINGLE_QUOTED='another value'
# Values can contain = signs
CONNECTION_STRING=key=value;another=value
# Export statements are ignored (just use KEY=VALUE)
NODE_ENV=development
```
## Precedence Order
Environment variables are loaded in this order (later sources override earlier ones):
1. Variables from `.env` file (if specified)
2. Inline `environment` configuration
3. Claude credentials (ANTHROPIC_API_KEY, etc.)
4. GitHub token (GITHUB_TOKEN)
5. Git author information (GIT_AUTHOR_NAME, etc.)
6. System variables (MAX_THINKING_TOKENS, etc.)
## Examples
### Basic Configuration
```json
{
"dockerImage": "claude-code-sandbox:latest",
"environment": {
"MY_APP_KEY": "12345",
"API_ENDPOINT": "https://api.example.com"
}
}
```
### Using .env File
Create `.env`:
```bash
# Development settings
DATABASE_URL=postgresql://localhost:5432/myapp
REDIS_URL=redis://localhost:6379
SECRET_KEY=development-secret
DEBUG=true
```
Configure `claude-sandbox.config.json`:
```json
{
"envFile": ".env",
"environment": {
"NODE_ENV": "development"
}
}
```
### Multiple Environment Files
For different environments, use different config files:
`claude-sandbox.dev.json`:
```json
{
"envFile": ".env.development",
"environment": {
"NODE_ENV": "development"
}
}
```
`claude-sandbox.prod.json`:
```json
{
"envFile": ".env.production",
"environment": {
"NODE_ENV": "production"
}
}
```
Run with:
```bash
claude-sandbox --config claude-sandbox.dev.json
```
## Security Best Practices
1. **Never commit sensitive data**: Add `.env` files to `.gitignore`
```gitignore
.env
.env.*
claude-sandbox.config.json
```
2. **Use placeholder values** in committed config files:
```json
{
"environment": {
"API_KEY": "REPLACE_ME"
}
}
```
3. **Use .env files** for sensitive data:
- Keep `.env` files local
- Use `.env.example` with dummy values for documentation
4. **Validate required variables** in setup commands:
```json
{
"setupCommands": [
"test -n \"$API_KEY\" || (echo 'Error: API_KEY not set' && exit 1)"
]
}
```
## Special Environment Variables
These variables have special meaning in Claude Sandbox:
### Claude Configuration
- `ANTHROPIC_API_KEY` - Claude API key
- `CLAUDE_CODE_USE_BEDROCK` - Use AWS Bedrock
- `CLAUDE_CODE_USE_VERTEX` - Use Google Vertex
- `MAX_THINKING_TOKENS` - Maximum thinking tokens
- `BASH_MAX_TIMEOUT_MS` - Bash command timeout
### GitHub Configuration
- `GITHUB_TOKEN` - GitHub authentication token
- `GH_TOKEN` - Alternative GitHub token variable
- `GIT_AUTHOR_NAME` - Git commit author name
- `GIT_AUTHOR_EMAIL` - Git commit author email
### System Configuration
- `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` - Always set to 1
## Debugging
To see what environment variables are available in the container:
```bash
# In the container
env | sort
# Or check specific variables
echo $MY_VAR
```
## Common Use Cases
### API Keys and Secrets
```json
{
"envFile": ".env.secrets",
"environment": {
"API_VERSION": "v1"
}
}
```
### Database Configuration
```json
{
"environment": {
"DB_HOST": "localhost",
"DB_PORT": "5432",
"DB_NAME": "myapp"
},
"envFile": ".env.local"
}
```
### Feature Flags
```json
{
"environment": {
"FEATURE_NEW_UI": "true",
"FEATURE_BETA_API": "false"
}
}
```
### Development Tools
```json
{
"environment": {
"DEBUG": "*",
"LOG_LEVEL": "verbose",
"PRETTY_PRINT": "true"
}
}
```

View file

@ -0,0 +1,206 @@
# GitHub Authentication
This document explains how to set up GitHub authentication for use within Claude Sandbox containers.
## Overview
Claude Sandbox uses GitHub tokens for authentication, providing a secure and simple way to access private repositories and push changes.
## Authentication Methods (in order of preference)
### 1. GitHub CLI Token (Recommended)
The most secure and convenient method:
```bash
# One-time setup on host:
gh auth login
# The token is automatically discovered and passed to containers
```
**How it works:**
- Claude Sandbox runs `gh auth token` to get your token
- Token is passed as `GITHUB_TOKEN` environment variable
- Git is configured to use the token for both HTTPS and SSH URLs
- Works for cloning, pulling, and pushing
**Benefits:**
- ✅ Cross-platform (macOS, Linux, Windows)
- ✅ Secure (tokens can be scoped)
- ✅ Easy to refresh (`gh auth refresh`)
- ✅ No manual token management
### 2. Environment Variables
Set a token in your shell:
```bash
# Using GitHub Personal Access Token
export GITHUB_TOKEN=ghp_xxxxxxxxxxxx
# Or using GitHub CLI token
export GH_TOKEN=$(gh auth token)
# Then run
claude-sandbox
```
**Supported variables:**
- `GITHUB_TOKEN` - Standard GitHub token variable
- `GH_TOKEN` - GitHub CLI token variable
### 3. Git Configuration
Your `.gitconfig` is automatically copied to containers, preserving:
- User name and email
- Custom aliases
- Other git settings (excluding credential helpers)
## Setup Examples
### Quick Setup (GitHub CLI)
```bash
# Install GitHub CLI
brew install gh # macOS
# or
sudo apt install gh # Ubuntu/Debian
# Authenticate
gh auth login
# Run claude-sandbox (token is auto-detected)
claude-sandbox
```
### Manual Token Setup
1. Create a Personal Access Token:
- Go to GitHub Settings → Developer settings → Personal access tokens
- Create a token with `repo` scope
- Copy the token
2. Set environment variable:
```bash
export GITHUB_TOKEN=ghp_your_token_here
claude-sandbox
```
## Using in Container
Once authenticated, git is automatically configured to use your token:
```bash
# Clone private repos (both HTTPS and SSH URLs work)
git clone https://github.com/username/private-repo.git
git clone git@github.com:username/private-repo.git
# Use GitHub CLI
gh repo create
gh pr create
gh issue list
# Push changes
git push origin main
```
## Configuration File
Add GitHub token to your project's `claude-sandbox.config.json`:
```json
{
"environment": {
"GITHUB_TOKEN": "ghp_xxxxxxxxxxxx"
}
}
```
**Warning:** Don't commit tokens to version control!
## Troubleshooting
### Permission Denied
If you get "Permission denied" errors:
1. Check if token is available:
```bash
# In container
echo $GITHUB_TOKEN
gh auth status
```
2. Verify git configuration:
```bash
git config --list | grep url
```
### Token Not Found
If no token is detected:
- Ensure you're logged in with `gh auth login`
- Or set `GITHUB_TOKEN` environment variable
- Check that the token has appropriate scopes
### Rate Limiting
If you hit rate limits:
- Ensure you're using an authenticated token
- Check rate limit: `gh api rate_limit`
## Security Best Practices
1. **Use Scoped Tokens**: Only grant necessary permissions (usually just `repo`)
2. **Rotate Tokens**: Regularly refresh tokens
3. **Don't Commit Tokens**: Use environment variables
4. **Use GitHub CLI**: It manages token lifecycle automatically
## Platform-Specific Notes
### macOS
- GitHub CLI token stored in macOS Keychain
- Git credentials may use osxkeychain helper
### Linux
- GitHub CLI token in `~/.config/gh/`
- Git credentials may use libsecret
### Windows (WSL)
- Use WSL for best compatibility
- GitHub CLI works in WSL
## Advanced Configuration
### Multiple GitHub Accounts
Use different tokens for different organizations:
```bash
# For work repos
export GITHUB_TOKEN=ghp_work_token
# For personal repos (in another session)
export GITHUB_TOKEN=ghp_personal_token
```
### Custom Git Configuration
The container automatically configures git to use tokens for all GitHub URLs:
- `https://github.com/` URLs use token authentication
- `git@github.com:` URLs are rewritten to use HTTPS with token
This means you can clone repositories using either format and authentication will work seamlessly.

View file

@ -0,0 +1,106 @@
# Lift and Shift Credentials
This document explains how `claude-sandbox` automatically transfers Claude credentials from your host machine to the Docker container.
## Overview
Claude Code stores authentication credentials in different locations depending on your operating system and how you authenticated. The `claude-sandbox` tool automatically detects and copies these credentials to ensure Claude Code works seamlessly in the container.
## Credential Sources
### macOS Keychain (Priority 1)
On macOS, Claude Code stores OAuth credentials in the system Keychain. These are automatically extracted using:
```bash
security find-generic-password -s "Claude Code-credentials" -w
```
The credentials are stored as JSON:
```json
{
"claudeAiOauth": {
"accessToken": "sk-ant-oat01-...",
"refreshToken": "sk-ant-ort01-...",
"expiresAt": 1748276587173,
"scopes": ["user:inference", "user:profile"]
}
}
```
These credentials are copied to: `/home/claude/.claude/.credentials.json`
### API Key Configuration (Priority 2)
If you have an API key stored in `~/.claude.json`:
```json
{
"api_key": "sk-ant-api03-..."
}
```
This file is copied to: `/home/claude/.claude.json`
### Environment Variable (Priority 3)
If `ANTHROPIC_API_KEY` is set in your environment, it's passed to the container:
```bash
export ANTHROPIC_API_KEY="sk-ant-api03-..."
```
### Existing .claude Directory (Fallback)
On non-macOS systems, if `~/.claude/` directory exists, it's copied entirely to the container.
## File Permissions
All copied credential files are set with appropriate permissions:
- `.claude/` directory: `700` (owner read/write/execute only)
- `.credentials.json`: `600` (owner read/write only)
- `.claude.json`: `644` (owner read/write, others read)
## Security Considerations
1. **Keychain Access**: On macOS, you may be prompted to allow terminal access to your Keychain
2. **File Ownership**: All files are owned by the `claude` user in the container
3. **No Root Access**: Claude Code runs as a non-root user for security
4. **Credential Updates**: Changes to credentials in the container don't affect your host
## Troubleshooting
### macOS Keychain Access Denied
If you see "No Claude credentials found in macOS Keychain", ensure:
1. You've logged into Claude Code on your host machine
2. Terminal has Keychain access permissions
3. The credential name is exactly "Claude Code-credentials"
### Missing Credentials
If Claude Code prompts for login in the container:
1. Check if credentials exist on your host
2. Verify file permissions in the container
3. Try setting `ANTHROPIC_API_KEY` as a fallback
### Manual Credential Setup
You can manually copy credentials into a running container:
```bash
docker exec -it <container-id> bash
# Inside container:
mkdir -p ~/.claude
echo '{"api_key": "your-key"}' > ~/.claude.json
```
## Platform Support
- **macOS**: Full support with Keychain integration
- **Linux**: Supports file-based credentials
- **Windows**: Supports file-based credentials (WSL recommended)

175
docs/setup-commands.md Normal file
View file

@ -0,0 +1,175 @@
# Setup Commands
This document explains how to run custom setup commands in your Claude Sandbox container.
## Overview
Setup commands allow you to automatically run initialization scripts when your container starts. This is useful for:
- Installing project dependencies
- Setting up databases
- Configuring environment-specific settings
- Installing additional tools
## Configuration
Add a `setupCommands` array to your `claude-sandbox.config.json`:
```json
{
"setupCommands": [
"npm install",
"pip install -r requirements.txt",
"sudo apt-get update && sudo apt-get install -y postgresql-client",
"createdb myapp_dev || true"
]
}
```
## Execution Order
Setup commands run:
1. **After** workspace files are copied
2. **After** git branch is created
3. **Before** Claude Code starts (if auto-start is enabled)
4. **As the `claude` user** (with sudo access)
## Examples
### Node.js Project
```json
{
"setupCommands": ["npm install", "npm run build", "npm run db:migrate"]
}
```
### Python Project
```json
{
"setupCommands": [
"pip install -r requirements.txt",
"python manage.py migrate",
"python manage.py collectstatic --noinput"
]
}
```
### Installing System Packages
```json
{
"setupCommands": [
"sudo apt-get update",
"sudo apt-get install -y redis-server postgresql-client",
"sudo service redis-server start"
]
}
```
### Complex Setup
```json
{
"setupCommands": [
"# Install dependencies",
"npm install && pip install -r requirements.txt",
"# Set up database",
"sudo service postgresql start",
"createdb myapp_dev || true",
"npm run db:migrate",
"# Start background services",
"redis-server --daemonize yes",
"npm run workers:start &"
]
}
```
## Best Practices
1. **Use `|| true`** for commands that might fail but shouldn't stop setup:
```json
["createdb myapp_dev || true"]
```
2. **Chain related commands** with `&&`:
```json
["cd frontend && npm install && npm run build"]
```
3. **Add comments** for clarity:
```json
["# Install Python dependencies", "pip install -r requirements.txt"]
```
4. **Test commands** in a regular container first:
```bash
docker run -it claude-code-sandbox:latest bash
# Test your commands here
```
## Error Handling
- Commands are run sequentially
- If a command fails (non-zero exit code), subsequent commands still run
- Failed commands show an error message but don't stop the container
- To stop on first error, add `"set -e"` as the first command
## Working Directory
All commands run in `/workspace` (your project root) as the `claude` user.
## Environment Variables
Commands have access to:
- All environment variables from your config
- Standard container environment
- `HOME=/home/claude`
- `USER=claude`
## Limitations
- Commands run synchronously (one at a time)
- Long-running commands will delay container startup
- Background processes should be daemonized
- Output is prefixed with `>` for clarity
## Troubleshooting
### Command Not Found
Ensure the tool is installed in the Docker image or install it in your setup commands:
```json
{
"setupCommands": ["sudo apt-get update && sudo apt-get install -y <package>"]
}
```
### Permission Denied
The `claude` user has passwordless sudo access. Prefix commands with `sudo` if needed:
```json
{
"setupCommands": ["sudo systemctl start postgresql"]
}
```
### Command Hangs
Ensure commands don't wait for user input. Use flags like `-y` or `--yes`:
```json
{
"setupCommands": ["sudo apt-get install -y package-name"]
}
```

6146
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

50
package.json Normal file
View file

@ -0,0 +1,50 @@
{
"name": "claude-code-sandbox",
"version": "0.1.0",
"description": "Run Claude Code as an autonomous agent in Docker containers with git integration",
"main": "dist/index.js",
"bin": {
"claude-sandbox": "./dist/cli.js"
},
"scripts": {
"build": "tsc",
"dev": "tsc --watch",
"start": "node dist/cli.js",
"lint": "eslint src/**/*.ts",
"test": "jest",
"purge-containers": "docker ps -a --filter \"ancestor=claude-code-sandbox:latest\" -q | xargs -r docker rm -f && docker rmi claude-code-sandbox:latest"
},
"keywords": [
"claude",
"ai",
"docker",
"sandbox",
"automation"
],
"author": "",
"license": "MIT",
"dependencies": {
"chalk": "^4.1.2",
"chokidar": "^3.6.0",
"commander": "^12.0.0",
"dockerode": "^4.0.2",
"inquirer": "^8.2.6",
"ora": "^5.4.1",
"simple-git": "^3.22.0",
"tar-stream": "^3.1.7"
},
"devDependencies": {
"@types/dockerode": "^3.3.23",
"@types/inquirer": "^9.0.7",
"@types/node": "^20.11.5",
"@typescript-eslint/eslint-plugin": "^6.19.0",
"@typescript-eslint/parser": "^6.19.0",
"eslint": "^8.56.0",
"jest": "^29.7.0",
"ts-jest": "^29.1.2",
"typescript": "^5.3.3"
},
"engines": {
"node": ">=18.0.0"
}
}

53
src/cli.ts Normal file
View file

@ -0,0 +1,53 @@
#!/usr/bin/env node
import { Command } from "commander";
import chalk from "chalk";
import { ClaudeSandbox } from "./index";
import { loadConfig } from "./config";
const program = new Command();
program
.name("claude-sandbox")
.description("Run Claude Code as an autonomous agent in Docker containers")
.version("0.1.0")
.option(
"-c, --config <path>",
"Path to configuration file",
"./claude-sandbox.config.json",
)
.option(
"-d, --detached",
"Run in detached mode (container runs in background)",
false,
)
.option("-n, --name <name>", "Container name prefix")
.option(
"--claude-config <path>",
"Path to Claude configuration file (default: ~/.claude.json)",
)
.option("--no-push", "Disable automatic branch pushing")
.option("--no-pr", "Disable automatic PR creation")
.option("--no-auto-claude", "Disable automatic Claude Code startup", false)
.action(async (options) => {
try {
console.log(chalk.blue("🚀 Starting Claude Sandbox..."));
const config = await loadConfig(options.config);
const sandbox = new ClaudeSandbox({
...config,
detached: options.detached,
containerPrefix: options.name,
claudeConfigPath: options.claudeConfig || config.claudeConfigPath,
autoPush: options.push,
autoCreatePR: options.pr,
autoStartClaude: !options.noAutoClaude,
});
await sandbox.run();
} catch (error) {
console.error(chalk.red("Error:"), error);
process.exit(1);
}
});
program.parse();

42
src/config.ts Normal file
View file

@ -0,0 +1,42 @@
import fs from "fs/promises";
import path from "path";
import os from "os";
import { SandboxConfig } from "./types";
const DEFAULT_CONFIG: SandboxConfig = {
dockerImage: "claude-code-sandbox:latest",
detached: false,
autoPush: true,
autoCreatePR: true,
autoStartClaude: true,
claudeConfigPath: path.join(os.homedir(), ".claude.json"),
setupCommands: [], // Example: ["npm install", "pip install -r requirements.txt"]
allowedTools: ["*"], // All tools allowed in sandbox
// maxThinkingTokens: 100000,
// bashTimeout: 600000, // 10 minutes
};
export async function loadConfig(configPath: string): Promise<SandboxConfig> {
try {
const fullPath = path.resolve(configPath);
const configContent = await fs.readFile(fullPath, "utf-8");
const userConfig = JSON.parse(configContent);
// Merge with defaults
return {
...DEFAULT_CONFIG,
...userConfig,
};
} catch (error) {
// Config file not found or invalid, use defaults
return DEFAULT_CONFIG;
}
}
export async function saveConfig(
config: SandboxConfig,
configPath: string,
): Promise<void> {
const fullPath = path.resolve(configPath);
await fs.writeFile(fullPath, JSON.stringify(config, null, 2));
}

1153
src/container.ts Normal file

File diff suppressed because it is too large Load diff

164
src/credentials.ts Normal file
View file

@ -0,0 +1,164 @@
import fs from "fs/promises";
import path from "path";
import os from "os";
import { execSync } from "child_process";
import { Credentials } from "./types";
import chalk from "chalk";
export class CredentialManager {
async discover(): Promise<Credentials> {
const credentials: Credentials = {};
// Discover Claude credentials (optional)
try {
credentials.claude = await this.discoverClaudeCredentials();
} catch {
// Claude credentials are optional - user can set them in the container
console.log(
chalk.yellow(
"No Claude credentials found on host. You can set them in the container.",
),
);
}
// Discover GitHub credentials
credentials.github = await this.discoverGitHubCredentials();
return credentials;
}
private async discoverClaudeCredentials(): Promise<Credentials["claude"]> {
// Check environment variables
if (process.env.ANTHROPIC_API_KEY) {
return {
type: "api_key",
value: process.env.ANTHROPIC_API_KEY,
};
}
// Check for ~/.claude.json configuration
try {
const claudeConfigPath = path.join(os.homedir(), ".claude.json");
const configContent = await fs.readFile(claudeConfigPath, "utf-8");
const config = JSON.parse(configContent);
if (config.api_key) {
return {
type: "api_key",
value: config.api_key,
};
}
} catch {
// File doesn't exist or is invalid, continue checking other sources
}
// Check for Bedrock configuration
if (process.env.CLAUDE_CODE_USE_BEDROCK === "1") {
return {
type: "bedrock",
value: "bedrock",
region: process.env.AWS_REGION || "us-east-1",
};
}
// Check for Vertex configuration
if (process.env.CLAUDE_CODE_USE_VERTEX === "1") {
return {
type: "vertex",
value: "vertex",
project: process.env.GOOGLE_CLOUD_PROJECT,
};
}
// Try to find OAuth tokens (Claude Max)
const oauthToken = await this.findOAuthToken();
if (oauthToken) {
return {
type: "oauth",
value: oauthToken,
};
}
throw new Error(
"No Claude credentials found. Please set ANTHROPIC_API_KEY or create ~/.claude.json with your API key.",
);
}
private async findOAuthToken(): Promise<string | null> {
// Check common locations for Claude OAuth tokens
const possiblePaths = [
path.join(os.homedir(), ".claude", "auth.json"),
path.join(
os.homedir(),
"Library",
"Application Support",
"Claude",
"auth.json",
),
path.join(os.homedir(), ".config", "claude", "auth.json"),
];
for (const authPath of possiblePaths) {
try {
const content = await fs.readFile(authPath, "utf-8");
const auth = JSON.parse(content);
if (auth.access_token) {
return auth.access_token;
}
} catch {
// Continue checking other paths
}
}
// Try to get from system keychain (macOS)
if (process.platform === "darwin") {
try {
const token = execSync(
'security find-generic-password -s "claude-auth" -w 2>/dev/null',
{
encoding: "utf-8",
},
).trim();
if (token) return token;
} catch {
// Keychain access failed
}
}
return null;
}
private async discoverGitHubCredentials(): Promise<Credentials["github"]> {
const github: Credentials["github"] = {};
// Check for GitHub token in environment
if (process.env.GITHUB_TOKEN) {
github.token = process.env.GITHUB_TOKEN;
} else if (process.env.GH_TOKEN) {
github.token = process.env.GH_TOKEN;
} else {
// Try to get from gh CLI
try {
const token = execSync("gh auth token 2>/dev/null", {
encoding: "utf-8",
}).trim();
if (token) github.token = token;
} catch {
// gh CLI not available or not authenticated
}
}
// Get git config
try {
const gitConfig = await fs.readFile(
path.join(os.homedir(), ".gitconfig"),
"utf-8",
);
github.gitConfig = gitConfig;
} catch {
// No git config found
}
return github;
}
}

104
src/git-monitor.ts Normal file
View file

@ -0,0 +1,104 @@
import { SimpleGit } from "simple-git";
import { EventEmitter } from "events";
import chokidar from "chokidar";
import path from "path";
import { CommitInfo } from "./types";
export class GitMonitor extends EventEmitter {
private git: SimpleGit;
private watcher: chokidar.FSWatcher | null = null;
private lastCommitHash: string = "";
private monitoring = false;
constructor(git: SimpleGit) {
super();
this.git = git;
}
async start(_branchName: string): Promise<void> {
this.monitoring = true;
// Get initial commit hash
const log = await this.git.log({ maxCount: 1 });
this.lastCommitHash = log.latest?.hash || "";
// Only watch if we're monitoring the host (for now we'll disable this)
// TODO: This should watch the container's git directory instead
console.log(
"Note: Git monitoring is currently disabled for container isolation",
);
return;
// Watch .git directory for changes
const gitDir = path.join(process.cwd(), ".git");
this.watcher = chokidar.watch(gitDir, {
persistent: true,
ignoreInitial: true,
depth: 2,
});
this.watcher!.on("change", async (filepath) => {
if (!this.monitoring) return;
// Check if there's a new commit
if (filepath.includes("refs/heads") || filepath.includes("logs/HEAD")) {
await this.checkForNewCommit();
}
});
// Also poll periodically as backup
this.startPolling();
}
async stop(): Promise<void> {
this.monitoring = false;
if (this.watcher) {
await this.watcher.close();
this.watcher = null;
}
}
private async checkForNewCommit(): Promise<void> {
try {
const log = await this.git.log({ maxCount: 1 });
const latestHash = log.latest?.hash || "";
if (latestHash && latestHash !== this.lastCommitHash) {
this.lastCommitHash = latestHash;
// Get commit details
const commit = await this.getCommitInfo(latestHash);
this.emit("commit", commit);
}
} catch (error) {
console.error("Error checking for new commit:", error);
}
}
private async getCommitInfo(hash: string): Promise<CommitInfo> {
const log = await this.git.log({ from: hash, to: hash, maxCount: 1 });
const commit = log.latest!;
// Get list of changed files
const diff = await this.git.diffSummary([`${hash}~1`, hash]);
const files = diff.files.map((f) => f.file);
return {
hash: commit.hash,
author: commit.author_name,
date: commit.date,
message: commit.message,
files,
};
}
private startPolling(): void {
const pollInterval = setInterval(async () => {
if (!this.monitoring) {
clearInterval(pollInterval);
return;
}
await this.checkForNewCommit();
}, 2000); // Poll every 2 seconds
}
}

208
src/index.ts Normal file
View file

@ -0,0 +1,208 @@
import Docker from "dockerode";
import { simpleGit, SimpleGit } from "simple-git";
import chalk from "chalk";
import { CredentialManager } from "./credentials";
import { GitMonitor } from "./git-monitor";
import { ContainerManager } from "./container";
import { UIManager } from "./ui";
import { SandboxConfig } from "./types";
import path from "path";
export class ClaudeSandbox {
private docker: Docker;
private git: SimpleGit;
private config: SandboxConfig;
private credentialManager: CredentialManager;
private gitMonitor: GitMonitor;
private containerManager: ContainerManager;
private ui: UIManager;
constructor(config: SandboxConfig) {
this.config = config;
this.docker = new Docker();
this.git = simpleGit();
this.credentialManager = new CredentialManager();
this.gitMonitor = new GitMonitor(this.git);
this.containerManager = new ContainerManager(this.docker, config);
this.ui = new UIManager();
}
async run(): Promise<void> {
try {
// Verify we're in a git repository
await this.verifyGitRepo();
// Check current branch
const currentBranch = await this.git.branchLocal();
console.log(chalk.blue(`Current branch: ${currentBranch.current}`));
// Generate branch name (but don't switch yet)
const timestamp = new Date()
.toISOString()
.replace(/[:.]/g, "-")
.split("T")[0];
const branchName = `claude/${timestamp}-${Date.now()}`;
console.log(chalk.blue(`Will create branch in container: ${branchName}`));
// Discover credentials (optional - don't fail if not found)
const credentials = await this.credentialManager.discover();
// Prepare container environment
const containerConfig = await this.prepareContainer(
branchName,
credentials,
);
// Start container
const containerId = await this.containerManager.start(containerConfig);
console.log(
chalk.green(`✓ Started container: ${containerId.substring(0, 12)}`),
);
// Start monitoring for commits
this.gitMonitor.on("commit", async (commit) => {
await this.handleCommit(commit);
});
await this.gitMonitor.start(branchName);
console.log(chalk.blue("✓ Git monitoring started"));
// Attach to container or run detached
if (!this.config.detached) {
console.log(chalk.blue("Preparing to attach to container..."));
// Set up cleanup handler
const cleanup = async () => {
console.log(chalk.blue("\nShutting down..."));
await this.cleanup();
process.exit(0);
};
// Handle process signals
process.on("SIGINT", cleanup);
process.on("SIGTERM", cleanup);
try {
console.log(chalk.gray("About to call attach method..."));
await this.containerManager.attach(containerId, branchName);
console.log(chalk.gray("Attach method completed"));
} catch (error) {
console.error(chalk.red("Failed to attach to container:"), error);
await this.cleanup();
throw error;
}
} else {
console.log(
chalk.blue(
"Running in detached mode. Container is running in the background.",
),
);
console.log(chalk.gray(`Container ID: ${containerId}`));
console.log(chalk.yellow("\nTo connect to the container, run:"));
console.log(
chalk.white(` docker attach ${containerId.substring(0, 12)}`),
);
console.log(chalk.yellow("\nOr use docker exec for a new shell:"));
console.log(
chalk.white(
` docker exec -it ${containerId.substring(0, 12)} /bin/bash`,
),
);
console.log(chalk.yellow("\nTo stop the container:"));
console.log(
chalk.white(` docker stop ${containerId.substring(0, 12)}`),
);
console.log(
chalk.gray(
"\nThe container will continue running until you stop it manually.",
),
);
}
} catch (error) {
console.error(chalk.red("Error:"), error);
throw error;
}
}
private async verifyGitRepo(): Promise<void> {
const isRepo = await this.git.checkIsRepo();
if (!isRepo) {
throw new Error(
"Not a git repository. Please run claude-sandbox from within a git repository.",
);
}
}
private async prepareContainer(
branchName: string,
credentials: any,
): Promise<any> {
const workDir = process.cwd();
const repoName = path.basename(workDir);
return {
branchName,
credentials,
workDir,
repoName,
dockerImage: this.config.dockerImage || "claude-sandbox:latest",
};
}
private async handleCommit(commit: any): Promise<void> {
// Show commit notification
this.ui.showCommitNotification(commit);
// Show diff
const diff = await this.git.diff(["HEAD~1", "HEAD"]);
this.ui.showDiff(diff);
// Ask user what to do
const action = await this.ui.askCommitAction();
switch (action) {
case "nothing":
console.log(chalk.blue("Continuing..."));
break;
case "push":
await this.pushBranch();
break;
case "push-pr":
await this.pushBranchAndCreatePR();
break;
case "exit":
await this.cleanup();
process.exit(0);
}
}
private async pushBranch(): Promise<void> {
const currentBranch = await this.git.branchLocal();
await this.git.push("origin", currentBranch.current);
console.log(chalk.green(`✓ Pushed branch: ${currentBranch.current}`));
}
private async pushBranchAndCreatePR(): Promise<void> {
await this.pushBranch();
// Use gh CLI to create PR
const { execSync } = require("child_process");
try {
execSync("gh pr create --fill", { stdio: "inherit" });
console.log(chalk.green("✓ Created pull request"));
} catch (error) {
console.error(
chalk.yellow(
"Could not create PR automatically. Please create it manually.",
),
);
}
}
private async cleanup(): Promise<void> {
await this.gitMonitor.stop();
await this.containerManager.cleanup();
}
}
export * from "./types";

45
src/types.ts Normal file
View file

@ -0,0 +1,45 @@
export interface VolumeMount {
source: string;
target: string;
readonly?: boolean;
}
export interface SandboxConfig {
dockerImage?: string;
dockerfile?: string;
detached?: boolean;
containerPrefix?: string;
autoPush?: boolean;
autoCreatePR?: boolean;
autoStartClaude?: boolean;
claudeConfigPath?: string;
setupCommands?: string[];
environment?: Record<string, string>;
envFile?: string;
volumes?: string[];
mounts?: VolumeMount[];
allowedTools?: string[];
maxThinkingTokens?: number;
bashTimeout?: number;
}
export interface Credentials {
claude?: {
type: "api_key" | "oauth" | "bedrock" | "vertex";
value: string;
region?: string;
project?: string;
};
github?: {
token?: string;
gitConfig?: string;
};
}
export interface CommitInfo {
hash: string;
author: string;
date: string;
message: string;
files: string[];
}

82
src/ui.ts Normal file
View file

@ -0,0 +1,82 @@
import chalk from "chalk";
import inquirer from "inquirer";
import ora from "ora";
import { CommitInfo } from "./types";
export class UIManager {
showCommitNotification(commit: CommitInfo): void {
console.log("\n" + chalk.yellow("━".repeat(80)));
console.log(chalk.yellow.bold("🔔 New Commit Detected!"));
console.log(chalk.yellow("━".repeat(80)));
console.log(chalk.white(`Hash: ${commit.hash.substring(0, 8)}`));
console.log(chalk.white(`Author: ${commit.author}`));
console.log(chalk.white(`Date: ${commit.date}`));
console.log(chalk.white(`Message: ${commit.message}`));
console.log(chalk.white(`Files changed: ${commit.files.length}`));
commit.files.forEach((file) => {
console.log(chalk.gray(` - ${file}`));
});
console.log(chalk.yellow("━".repeat(80)) + "\n");
}
showDiff(diff: string): void {
console.log(chalk.blue.bold("\n📝 Diff:"));
console.log(chalk.blue("─".repeat(80)));
// Apply syntax highlighting to diff
const lines = diff.split("\n");
lines.forEach((line) => {
if (line.startsWith("+") && !line.startsWith("+++")) {
console.log(chalk.green(line));
} else if (line.startsWith("-") && !line.startsWith("---")) {
console.log(chalk.red(line));
} else if (line.startsWith("@@")) {
console.log(chalk.cyan(line));
} else if (line.startsWith("diff --git")) {
console.log(chalk.yellow.bold(line));
} else {
console.log(line);
}
});
console.log(chalk.blue("─".repeat(80)) + "\n");
}
async askCommitAction(): Promise<string> {
const { action } = await inquirer.prompt([
{
type: "list",
name: "action",
message: "What would you like to do?",
choices: [
{ name: "Continue working", value: "nothing" },
{ name: "Push branch to remote", value: "push" },
{ name: "Push branch and create PR", value: "push-pr" },
{ name: "Exit claude-code-sandbox", value: "exit" },
],
},
]);
return action;
}
showSpinner(message: string): any {
return ora(message).start();
}
showSuccess(message: string): void {
console.log(chalk.green(`${message}`));
}
showError(message: string): void {
console.log(chalk.red(`${message}`));
}
showWarning(message: string): void {
console.log(chalk.yellow(`${message}`));
}
showInfo(message: string): void {
console.log(chalk.blue(` ${message}`));
}
}

23
tsconfig.json Normal file
View file

@ -0,0 +1,23 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "commonjs",
"lib": ["ES2022"],
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist", "**/*.test.ts"]
}