Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.charlielabs.ai/llms.txt

Use this file to discover all available pages before exploring further.

Charlie works best when your repo can set up its own development environment from a fresh clone. Put setup where your repo already runs after dependency installation. For JavaScript and TypeScript repos, that usually means postinstall. Gate Charlie-only work with IS_CHARLIE=1, store secrets in dashboard repository environment variables, and use AGENTS.md to tell Charlie how to use the environment.
Use this setup path for build, test, and tooling dependencies that can be installed noninteractively. Running services, such as Docker Compose stacks, background processes, or databases, should be documented in AGENTS.md and handled as a separate workflow.

What Charlie sets up automatically

Charlie creates repo-specific devbox blueprints so new runs start from a prepared environment instead of a blank machine. For most repos, Charlie will:
  • Clone the repository into the devbox.
  • Provide common tools and package categories: Git, Bash, Python, Node package managers, build tools such as make, cmake, and pkg-config, CLIs such as jq, ripgrep, curl, and gh, mise, and native headers used by frequent Node/image/database-client packages.
  • Detect JavaScript package managers and run dependency installation with the repo’s normal lifecycle scripts.
  • Inject configured repository environment variables from the Charlie dashboard.
  • Set IS_CHARLIE=1 during Charlie runs.
Charlie does not try to guess every apt package your repo might need. If your tests, builds, or tools need extra system packages after dependencies install, declare them in your repo setup. For JavaScript and TypeScript repos, use this shape for setup that can run after package-manager dependency installation has completed:
1

Call a setup script from postinstall

Keep package.json small and route the real work to a script. Do not use this path for apt packages that are required by dependency install scripts or native addon builds; postinstall runs too late for those.
{
  "scripts": {
    "postinstall": "bash scripts/setup-charlie-env.sh"
  }
}
2

Guard Charlie-only work with IS_CHARLIE

The script should exit quickly outside Charlie unless you intentionally support local use.
#!/usr/bin/env bash
set -euo pipefail

if [[ "${IS_CHARLIE:-}" != "1" ]]; then
  exit 0
fi

sudo DEBIAN_FRONTEND=noninteractive apt-get update
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
  libpq-dev \
  pkg-config
3

Make setup idempotent and noninteractive

Design setup so it is safe to run more than once.
  • Use --no-install-recommends for apt packages.
  • Pass DEBIAN_FRONTEND=noninteractive on each sudo apt-get command.
  • Prefer commands that no-op when packages already exist.
  • Do not prompt for input.
  • Do not print secrets.

Install system dependencies

Use real apt commands for packages that must exist before tests or build tools run, as long as those packages are not required during dependency installation itself. Example: native database client headers and build metadata:
sudo DEBIAN_FRONTEND=noninteractive apt-get update
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
  libpq-dev \
  pkg-config
Example: image processing dependencies used by common native modules:
sudo DEBIAN_FRONTEND=noninteractive apt-get update
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
  libvips-dev \
  libcairo2-dev \
  libpango1.0-dev
Example: command-line tools needed by tests:
sudo DEBIAN_FRONTEND=noninteractive apt-get update
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
  poppler-utils \
  graphviz
Keep the list focused. If Charlie already has a tool installed, you do not need to reinstall it. If a package is needed while bun install, pnpm install, yarn install, or npm install is still running, do not rely on postinstall; ask Charlie for a pre-dependency-install blueprint update instead.
If you want one setup script to work in Charlie and on developer laptops, consider using mise for user-level tools and runtimes. Charlie devboxes include mise, so a guarded setup script can run mise install for repo tools while keeping apt-only work behind the IS_CHARLIE=1 guard or a separate opt-in local path.

Non-JS repos

postinstall is the main recipe for work that can happen after JavaScript dependency installation. Charlie runs package-manager installs first, so dependency install scripts and native addon builds may fail before the root postinstall script can install missing system packages. For non-JS repos, use the closest equivalent your team already trusts:
  • make setup-charlie
  • just setup-charlie
  • scripts/setup-charlie-env.sh
  • mise install plus a documented setup task
Then document the command in AGENTS.md so Charlie knows to run it when preparing the repo or debugging environment failures.

Tell Charlie how to use the environment

Use AGENTS.md for durable instructions about setup, verification, and known caveats.
## Charlie environment

- Repo setup that runs after dependency installation is handled by `postinstall`, which calls `scripts/setup-charlie-env.sh`.
- The setup script installs Charlie-only system packages when `IS_CHARLIE=1`.
- If tests fail because a system package is missing after dependencies are installed, update the setup script instead of installing packages ad hoc.
- If dependency installation itself fails because a native package is missing, ask Charlie for a pre-dependency-install blueprint update.
- Required secrets are configured as Charlie dashboard repository environment variables. Do not print them in logs.
- Validate environment changes with `bun test` and the affected package checks.
Keep this short and operational. AGENTS.md should tell Charlie what to do, not repeat every package in the setup script.

Secrets and environment variables

Use dashboard repository environment variables for non-public keys, tokens, and runtime config needed during Charlie runs. Configure them under your repository settings in the Charlie dashboard. Good uses include:
  • Package registry tokens such as NPM_TOKEN.
  • API keys for test doubles or sandbox services.
  • Runtime config used by build or verification commands.
Do not commit secrets to the repo, echo them from setup scripts, or include them in generated logs. If a setup command needs a secret, read it from the environment and fail with a generic message when it is missing.

How blueprints work

Blueprints are repo-specific prepared devbox images. They are similar to Docker images: Charlie builds them from your repo setup so future devboxes can start faster with dependencies already present. Charlie checks blueprints on repository pushes and rebuilds them when the existing blueprint is stale. Changes may not apply immediately, and existing devboxes may keep using the environment they already have. If you need a setup change available right away, contact Charlie and ask for an on-demand blueprint update.

Troubleshooting

apt-get prompts or hangs

Pass DEBIAN_FRONTEND=noninteractive on the sudo apt-get command and use -y:
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends <package>

A native dependency fails during package install

postinstall cannot repair apt packages required by dependency install scripts or native addon builds, because the package-manager install may fail before postinstall runs. Ask Charlie for a pre-dependency-install blueprint update for those packages.

Package install works once, then fails later

Make the script idempotent. Check for files, directories, or commands before creating or installing them, and prefer package manager commands that tolerate already-installed packages.

A package is missing in Charlie but installed locally

If the package is needed after dependencies install, add it to the repo setup script and commit the change. If it is needed while dependencies install, ask Charlie for a pre-dependency-install blueprint update. Local machine state is not part of the blueprint unless the repo can recreate it.

A change is not visible in a new Charlie run

Blueprint updates may lag. Ask Charlie for an on-demand blueprint update if the new package is blocking work.

Setup needs a running service

Leave it out of this page’s setup path for now. Document the need in AGENTS.md and ask Charlie how to handle that workflow separately.

Complete example

package.json:
{
  "scripts": {
    "postinstall": "bash scripts/setup-charlie-env.sh"
  }
}
scripts/setup-charlie-env.sh:
#!/usr/bin/env bash
set -euo pipefail

if [[ "${IS_CHARLIE:-}" != "1" ]]; then
  exit 0
fi

sudo DEBIAN_FRONTEND=noninteractive apt-get update
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
  libpq-dev \
  pkg-config \
  poppler-utils

if command -v mise >/dev/null 2>&1 && [[ -f .mise.toml ]]; then
  mise trust .mise.toml -y
  mise install
fi
AGENTS.md:
## Charlie environment

- Environment setup that can run after dependency installation runs from `postinstall` via `scripts/setup-charlie-env.sh`.
- Charlie-only setup is guarded by `IS_CHARLIE=1`.
- Repository secrets come from Charlie dashboard environment variables. Never print them.
- If tests or builds fail after dependency installation because a package is missing, update `scripts/setup-charlie-env.sh` and re-run the affected verification command.
- If dependency installation itself fails because a native package is missing, ask Charlie for a pre-dependency-install blueprint update.