ccweb
Bootstrap Claude Code web environments with one command.
uvx ccweb init
Generates setup.sh, session-start.sh, diagnose.sh, and wires .claude/settings.json for your project. When you start a Claude Code web session, the VM is automatically provisioned with your selected toolchains.
Quick start
# In your project root
uvx ccweb init
# Commit and push
git add scripts/ .claude/settings.json
git commit -m "Add Claude Code web environment setup"
git push
# Start a Claude Code web session — it auto-provisions
# Then verify:
uvx ccweb doctor
Local Docker validation
Before pushing, validate the generated scripts against a clean Ubuntu 24.04 container:
uvx ccweb test # runs setup.sh + diagnose.sh in ubuntu:24.04
uvx ccweb test --image ubuntu:22.04
uvx ccweb test --shell # interactive shell for ad-hoc debugging
Requires a local Docker daemon. The repo is mounted read-only at /workspace, so the test can never modify your working copy.
Options
uvx ccweb init --toolchains auto --extras auto # Detect from repo files
uvx ccweb init --toolchains node,python # Just Node + Python
uvx ccweb init --toolchains go --extras postgres # Go + psql
uvx ccweb init --versions go=1.23.0,zig=0.14.0 # Pin tool versions
uvx ccweb init --env-file .env.example # Declare required env vars
uvx ccweb init --env-file "" # Disable env-file auto-detect
uvx ccweb init --force # Overwrite existing files
uvx ccweb init --scripts-dir ci/scripts # Custom scripts directory
uvx ccweb init --skills ai/skills # Custom skills directory
uvx ccweb init --skills "" # Disable skills wiring
Toolchains
node, python, go, rust, ruby, java, deno, elixir, zig, dotnet, php — default: all
Extras
uv, pnpm, yarn, bun, browser, postgres, redis, docker — default: all
gh, duckdb, yq, sqlite3, jq, pandoc, shellcheck, and friends are always installed — no flag needed.
Auto-detection
Pass auto to either flag to install only what the repo actually needs. Detection inspects the project root for marker files:
| Toolchain | Markers |
|---|---|
node |
package.json, package-lock.json, pnpm-lock.yaml, yarn.lock, bun.lock |
python |
pyproject.toml, requirements.txt, setup.py, Pipfile, uv.lock |
go |
go.mod |
rust |
Cargo.toml |
ruby |
Gemfile, *.gemspec |
java |
pom.xml, build.gradle, build.gradle.kts |
deno |
deno.json, deno.jsonc |
elixir |
mix.exs |
zig |
build.zig, build.zig.zon |
dotnet |
*.csproj, *.fsproj, *.sln |
php |
composer.json |
Extras are detected from lockfiles, Dockerfile / docker-compose.yml, playwright/puppeteer in package.json, [tool.uv] in pyproject.toml, and postgres/redis images referenced in compose files.
The cloud extra (aws, gcloud, terraform, kubectl, helm) is detected from any of: *.tf / *.tfvars at the root, a terraform/ / infra/ / iac/ / k8s/ / kubernetes/ / manifests/ directory, or a Chart.yaml, helmfile.yaml, kubeconfig, or kustomization.yaml file at the root.
Version pinning
Override any of the baked-in versions with --versions KEY=VALUE (comma-separated for multiple). Unspecified tools use the defaults in DEFAULT_VERSIONS.
Valid keys: go, zig, gh, duckdb, yq, dotnet_channel, terraform, kubectl.
uvx ccweb init --versions go=1.23.0
uvx ccweb init --versions go=1.23.0,gh=2.74.1,dotnet_channel=LTS
Pins are also auto-detected from common version files at the project root — no flag required:
| File | Source of pin |
|---|---|
.tool-versions |
asdf/mise entries for golang/go, zig, terraform, kubectl |
.go-version |
Go (takes precedence over .tool-versions) |
.terraform-version |
Terraform (takes precedence over .tool-versions) |
.nvmrc, .python-version |
Read but ignored — node and python are pre-installed and not pinnable |
Explicit --versions entries always win over auto-detected pins, per key.
Environment variables
If the repo contains .env.example or .env.template (or you point --env-file somewhere else), session-start.sh reads the variable names from it and warns when any are unset in the session. diagnose.sh gets a matching section that shows each declared variable as set or missing.
The file is treated as a schema — ccweb never reads, copies, or transmits the values. Store actual secrets in the claude.ai/code Environment Variables UI at the project level.
# .env.example (checked into the repo; values are placeholders)
DATABASE_URL=
OPENAI_API_KEY=
STRIPE_SECRET=
Pass --env-file "" to disable auto-detection.
Skills
By default, ccweb looks for Claude Code skills in .claude/skills/ in your
repo (each subdirectory holds a SKILL.md). On session start, every skill
found there is symlinked into ~/.claude/skills/<name> so Claude Code
discovers them at the user level across every session on the VM. Pass
--skills ai/skills for a custom path, or --skills "" to disable.
<repo>/<DIR>/my-skill/SKILL.md
<repo>/<DIR>/my-skill/reference.md
Auto-formatting on Edit/Write
ccweb init also generates scripts/post-tool-use.sh and wires it as a
PostToolUse hook in .claude/settings.json (matcher: Edit|Write|MultiEdit).
After every file edit, the hook reads the file path from Claude's hook payload
and runs the matching formatter:
| Formatter | Extensions |
|---|---|
ruff format + ruff check --fix |
.py |
gofmt |
.go |
rustfmt |
.rs |
zig fmt |
.zig |
mix format |
.ex, .exs |
shfmt |
.sh, .bash |
clang-format |
.c, .h, .cc, .cpp, .cxx, .hpp, .hh, .hxx, .m, .mm |
rubocop -A |
.rb |
google-java-format |
.java |
php-cs-fixer |
.php |
terraform fmt |
.tf, .tfvars |
prettier (falls back to deno fmt) |
.js, .jsx, .ts, .tsx, .mjs, .cjs, .json, .jsonc, .md, .mdx, .css, .scss, .html, .yaml, .yml |
Each formatter is guarded by command -v, and the hook always exits 0 so a
missing or failing formatter never blocks the agent.
How it works
-
setup.shruns once when a new VM is created. Installs system packages, toolchains, and persists environment variables to/etc/environment. -
session-start.shruns on every session start (new + resumed). Sources env vars, detects project lockfiles, and installs dependencies. Auto-runssetup.shif the VM hasn't been provisioned yet. -
diagnose.shchecks what's installed, what's missing, and what's misconfigured. -
post-tool-use.shruns after every Edit/Write/MultiEdit and formats the changed file. -
.claude/settings.jsonwires both hooks so they run automatically.
License
MIT
Metadata
Release files for ccweb 0.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ccweb-0.5.0.tar.gz | 45.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ccweb-0.5.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 74.9 kB
Release files / ccweb-0.5.0.tar.gz
| Download URL | ccweb-0.5.0.tar.gz |
|---|---|
| Size | 45.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e5e16a99137aa800678f6eaadfeb6b168873c65bd8dafaa5c153e628f964237e
|
|
BLAKE2b-256 checksum How to use checksums |
6caffcaec89c2d6017e59a9e452553400b87520835c0c4b33601bd39bcbd4527
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 25, 2026.
Transparency logRelease files / ccweb-0.5.0-py3-none-any.whl
| Download URL | ccweb-0.5.0-py3-none-any.whl |
|---|---|
| Size | 29.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
311c3135faede6c9ec095b3f65f2f6df8ee0698899e0d71da0b3a7f375992300
|
|
BLAKE2b-256 checksum How to use checksums |
a86e7ff96c9d64937d31dc2216ad5282008a210929f19c1ec0e21de99d677973
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 25, 2026.
Transparency log