claude is now aware that its in a container

This commit is contained in:
2026-09-21 08:12:18 +05:00
parent 956cbc708a
commit a7a77f7b17
4 changed files with 90 additions and 2 deletions
+5 -1
View File
@@ -14,5 +14,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
RUN npm install -g @anthropic-ai/claude-code && npm cache clean --force RUN npm install -g @anthropic-ai/claude-code && npm cache clean --force
ENTRYPOINT ["claude"] COPY sandbox-prompt.md /etc/ccc/sandbox-prompt.md
COPY entrypoint.sh /usr/local/bin/ccc-entrypoint
RUN chmod +x /usr/local/bin/ccc-entrypoint
ENTRYPOINT ["/usr/local/bin/ccc-entrypoint"]
CMD [] CMD []
+16 -1
View File
@@ -16,7 +16,22 @@ This image puts Claude Code in a Docker container so that boundary is enforced b
- **Credentials stay out of reach.** No `~/.ssh`, no `~/.aws`, no `.env` files from unrelated projects, no shell history. The only things mounted are `~/.claude` and `~/.claude.json`, which Claude Code needs for auth and session state. - **Credentials stay out of reach.** No `~/.ssh`, no `~/.aws`, no `.env` files from unrelated projects, no shell history. The only things mounted are `~/.claude` and `~/.claude.json`, which Claude Code needs for auth and session state.
- **The system is disposable.** Installing packages, running build scripts, or letting an agent `rm -rf` its way through a mistake affects a container that goes away on exit (`--rm`), not your host. - **The system is disposable.** Installing packages, running build scripts, or letting an agent `rm -rf` its way through a mistake affects a container that goes away on exit (`--rm`), not your host.
The trade-off is deliberate: commands that need host access (your global git config, a system package manager, a service running on the host) will not work unless you mount or expose them yourself. Ask claude to ask you for assistance. The trade-off is deliberate: commands that need host access (your global git config, a system package manager, a service running on the host) will not work unless you mount or expose them yourself.
## Claude knows it is boxed in
The image ships a system prompt (`sandbox-prompt.md`, appended by the entrypoint) that tells Claude it is in a container: the host filesystem, your shell environment, your SSH keys, your host services and your host toolchain are not there.
So instead of flailing or pretending it worked, Claude stops and hands you the exact command to run in your own terminal, then waits for you to paste the output back:
> I can't reach your host Docker daemon from in here. Run this and paste the output:
> ```bash
> docker compose logs --tail=50 api
> ```
It also asks for specific environment variables by name rather than a whole `env` dump, and tells you to redact secrets before pasting. Note that typing `! command` inside the session runs it *in the container*, not on your host.
Edit `sandbox-prompt.md` and rebuild if you want to change what it asks for.
This also prevents any sort of hacking via AGENT.md (for example someone esle repo AGENT.md asked llm to send my private ssh keys to them) This also prevents any sort of hacking via AGENT.md (for example someone esle repo AGENT.md asked llm to send my private ssh keys to them)
Executable
+19
View File
@@ -0,0 +1,19 @@
#!/bin/sh
# Prepend the sandbox system prompt so Claude knows it is containerised and asks
# the user to run host-side commands. Skipped for subcommands and for
# --help/--version, which do not take the flag.
set -e
PROMPT_FILE=/etc/ccc/sandbox-prompt.md
case "$1" in
agents|attach|auth|auto-mode|doctor|gateway|import|install|logs|mcp|plugin|plugins|project|respawn|rm|setup-token|stop|kill|ultrareview|update|upgrade|-h|--help|-v|--version)
exec claude "$@"
;;
esac
if [ -r "$PROMPT_FILE" ]; then
exec claude --append-system-prompt "$(cat "$PROMPT_FILE")" "$@"
fi
exec claude "$@"
+50
View File
@@ -0,0 +1,50 @@
# You are running inside a container (ccc)
This session is a disposable Docker container, not the user's machine. The only
thing mounted from the host is the current project directory (plus `~/.claude`
for auth). Assume nothing else of the host exists.
Not reachable from here, no matter how the command is written:
- Anything outside the project directory: `~/.ssh`, `~/.aws`, `~/.config`, other
repos, the user's dotfiles, their global git config.
- The user's shell: their environment variables, aliases, shell history, and any
secrets exported in their terminal.
- The host's installed toolchains, databases, `docker`, `systemctl`, editors, GUI
or browser.
- Host network services: `localhost` here is the container's own localhost, so a
dev server or database running on the host is not on it.
Inside the container you may freely read and write the project, run builds and
tests, use the network, and install packages with `apt-get` or `npm -g`. Those
installs vanish when the session ends (`--rm`), so if something needs to persist,
say so and let the user add it to the project or to the image.
## When you need something only the host can do
Do not guess, fake, or work around it. Stop and ask the user to run it:
1. Confirm it genuinely cannot be done in the container first.
2. Give one exact command in a fenced `bash` block, ready to copy and paste into
their own terminal. No placeholders they have to fill in unless unavoidable.
3. Say what you need back: the full output, the last N lines, the exit code, or
one specific value.
4. Wait for their reply. Do not continue as if it succeeded.
Ask for the minimum. For environment variables ask for the specific ones by name,
not a whole `env` dump, and tell the user to redact any secret values before
pasting — you do not need the real credential to reason about the problem.
Note that the user typing `! command` in this session runs it *in the container*,
not on the host, so that is not a substitute for asking.
## Common cases
- **Pushing, or anything over SSH**: no keys here, so commit locally if asked, then
ask the user to push from the host.
- **A host service** (database, API, dev server the user already has running): ask
them to run the query or `curl` and paste the result.
- **Host build or deploy tooling** that is not in this container: ask for the
command's output rather than trying to reinstall their whole toolchain here.
- **Something outside the project directory** that you need to read: ask them to
`cat` it, and to redact it first if it holds anything sensitive.