TokenContainer is a Podman-based development container for Claude Code and Codex. It gives coding agents a repeatable Linux workspace with Claude Code, Codex CLI, PDF and TeX tooling, diagram utilities, nested container CLIs, and common developer tools preinstalled. The installed command is named lemon.
TokenContainer is designed for trusted local or shared machines where the container is the safety boundary. Claude is launched with --dangerously-skip-permissions by default so it can work smoothly inside the isolated container.
- Claude Code and Codex CLI in the same image.
- Rootless Podman lifecycle wrapper with
build,run,up,shell,logs, andstatuscommands. - Mounted workspace with matching host-to-container working directory resolution.
- Persistent Claude and Codex state under separately configured host directories.
- Built-in tools for PDF extraction, TeX builds, diagrams, HDL/debug work, nested container workflows, and general command-line development.
- Optional shared-machine mode for teams using one owner-managed container and workspace.
- Composable Dockerfile targets for smaller or fuller images.
Install TokenContainer's lemon command:
git clone <repo-url> TokenContainer
cd TokenContainer
sudo ./install-system.shBuild and start the container:
lemon upLaunch Claude Code in the container:
lemonOpen a shell in the container:
lemon shelllemon # launch Claude Code
lemon -r # open Claude's resume picker
lemon -c # continue the most recent conversation in this directory
lemon shell # open an interactive container shell
lemon ps # list live Claude sessions
lemon kill <session> # stop a live Claude session by session ID or PID
lemon status # show the container status
lemon logs # show container logs
lemon stop # stop the containerWhen launched from a directory under WORKSPACE_DIR, TokenContainer starts in the corresponding /workspace/... path inside the container.
Install updated wrapper files first:
cd TokenContainer
sudo ./install-system.shBuild the new image without interrupting active sessions:
lemon buildCodex is installed in the node-owned npm prefix under /home/node/.local, so it can be updated inside the container without sudo:
npm install -g @openai/codex@latestOn older images that still use the root-owned /usr/local npm prefix, use sudo npm install -g @openai/codex@latest or rebuild the image.
Drain active sessions before replacing the running container:
lemon ps
lemon runlemon up is shorthand for lemon build followed by lemon run. Because run replaces the running container, use it only when active sessions and long-running jobs can be interrupted.
DOCKERFILE_TARGET controls which Dockerfile stage is built. The default is full.
DOCKERFILE_TARGET=base lemon build
DOCKERFILE_TARGET=pdf lemon build
DOCKERFILE_TARGET=tex-debian lemon build
DOCKERFILE_TARGET=full lemon buildTargets:
base: Claude Code, Codex CLI, and core development tools.pdf:baseplus Poppler, MuPDF, andpdf2svg.tex-debian:pdfplus Debian TeX Live packages.full:tex-debianplus general CLI tools, fonts, diagrams, HDL/debug tools, Docker, Podman, and Skopeo.
Package groups live in docker/apt. The image stays based on node:trixie so Node, npm, the node user, Claude, Codex, and Debian packages remain predictable.
The default full image includes:
- Agent CLIs: Claude Code, Codex CLI.
- Core development: Git, GitHub CLI, Python, Node, npm, CMake, build tools, jq, ripgrep, Vim, curl, wget.
- PDF and document processing: Poppler tools, MuPDF tools,
pdf2svg. - TeX and publishing: selected Debian TeX Live packages, including LaTeX, publishers, science, fonts, BibTeX extras, and LuaTeX.
- Diagrams and fonts: Graphviz, PlantUML, Inter, Inconsolata, Liberation, Noto CJK.
- Containers: Docker CLI/daemon package, Podman, Skopeo.
- Debug and HDL: GDB, Icarus Verilog, Verilator.
- Shell quality-of-life: tmux, fzf, fd, bat, shellcheck, shfmt, zip/unzip, xz, bzip2.
Configuration files are loaded in this order:
lemon.defaults.conf/etc/lemon.conflemon.confnext to the installed command
Copy the example config when you need machine-local values:
cp lemon.conf.example lemon.confCommon settings:
IMAGE_NAME: image tag, defaultclaude-dev.CONTAINER_NAME: running container name, defaultclaude-dev.DOCKERFILE_TARGET: Dockerfile target, defaultfull.WORKSPACE_DIR: host workspace mounted at/workspace.LEMON_RUNTIME_DIR: host directory for TokenContainer runtime data such as generated terminfo.CLAUDE_STATE_DIR: host directory mounted as Claude state, default${SCRIPT_DIR}/.lemon/.claude;${CLAUDE_STATE_DIR}.jsonis mounted as/home/node/.claude.json.CODEX_STATE_DIR: host directory mounted as Codex state, default${SCRIPT_DIR}/.lemon/.codex.HOST_DATA_SHARE_DIR: optional extra host directory to bind mount.PODMAN_SERVICE_URL: optional Podman service socket for shared or remote Podman access.
The real lemon.conf is machine-local and ignored by Git.
System installs generate their installed lemon.conf by default so shared users target the owner-managed Podman socket, then append repo-local lemon.conf overrides when that file exists. To install a specific config file exactly, run USE_TRACKED_CONFIG=true sudo ./install-system.sh.
TokenContainer can run as one owner-managed container for multiple local users. This is useful on shared development servers where users should work in the same mounted workspace without creating root-owned files.
Owner setup:
sudo ./install-system.sh
lemon up
sudo ./setup-shared-access.sh <shared-user>
SHARED_SOCKET_GROUP=claude ./lemon.sh share-setup
sudo loginctl enable-linger "$USER"Shared users need to be added to the configured shared group and start a new login session. They can then use the shared Podman socket through PODMAN_SERVICE_URL or the installed configuration.
Repair shared workspace permissions later:
lemon repairFor a full repair of an existing shared tree:
sudo ./setup-shared-access.sh --repair-allTokenContainer is intentionally convenient for agentic coding. Claude Code is launched with --dangerously-skip-permissions by default, and the container is treated as the trust boundary.
Use TokenContainer only with trusted workspaces and host mounts. Avoid mounting secrets or directories that the agent should not read or modify. Recreating the container preserves configured host-mounted state, but it will stop active processes inside the container.
Claude state is mounted from CLAUDE_STATE_DIR, which defaults to ${SCRIPT_DIR}/.lemon/.claude; ${CLAUDE_STATE_DIR}.json is mounted as /home/node/.claude.json. Codex state is mounted from CODEX_STATE_DIR, which defaults to ${SCRIPT_DIR}/.lemon/.codex.
This repository is public-facing but does not currently include a reuse license. Until a license is added, do not assume permission to redistribute or reuse the code beyond what the hosting platform permits.
Implementation names such as claude-dev may still appear in default image and container names.