Docs From Codebase
MIT↓ 0 downloadsA single Claude Code agent reads your repository — a shell-expanded file map seeds it, and it can install and run the project — then writes and incrementally commits a real `docs/` set: a getting-started guide, an architecture overview, and per-module reference pages.
Topology
Disclosures
Everything below runs on your machine or inside the sandbox when you use this workflow. Mismatches between these declarations and the actual code block publishing.
Host hooks
Commands executed on YOUR host machine by Sandcastle lifecycle hooks.
None declared.
Sandbox hooks
Commands executed inside the sandbox container.
npm install
Network access
None. The agent reads and writes only the local repository inside the sandbox; the sandbox hook runs `npm install` against your declared package registry.
Shell expansion
Prompt files contain !`command` blocks — the agent CLI executes these commands at prompt-load time. They are highlighted amber in the prompt files below.
Files
Diff vs the stock Sandcastle 0.12.0 template Dockerfile — green lines were added by the author, red lines were removed from stock.
+# Sandbox image for the Docs From Codebase workflow.+# Node 22 + git + the Claude Code CLI, running as a non-root `agent` user.+# Add your project's toolchain (python, go, ...) here if the agent needs to run+# it to understand the project.FROM node:22-bookworm-# System dependencies.RUN apt-get update && apt-get install -y --no-install-recommends \git \curl \jq \ca-certificates \&& rm -rf /var/lib/apt/lists/*# Claude Code CLI (the agent runtime).RUN npm install -g @anthropic-ai/claude-code# Non-root agent user. `sandcastle docker build-image` aligns AGENT_UID/GID to# the host user via --build-arg to avoid permission errors on bind mounts.+# node:22-bookworm already ships a "node" user at UID/GID 1000, so we RENAME it+# (the stock Sandcastle template pattern) — groupadd/useradd would collide with+# the existing IDs on a default build.ARG AGENT_UID=1000ARG AGENT_GID=1000-RUN groupadd --gid ${AGENT_GID} agent \- && useradd --uid ${AGENT_UID} --gid ${AGENT_GID} --create-home --shell /bin/bash agent+RUN groupmod -o -g ${AGENT_GID} node \+ && usermod -o -u ${AGENT_UID} -g ${AGENT_GID} -d /home/agent -m -l agent node-USER agent-WORKDIR /workspace+USER ${AGENT_UID}:${AGENT_GID}+WORKDIR /home/agent++# Sandcastle bind-mounts the worktree and sets the working directory at+# container start; the container just needs to stay alive until then.+ENTRYPOINT ["sleep", "infinity"]
Show full Dockerfile (highlighted)
# Sandbox image for the Docs From Codebase workflow.
# Node 22 + git + the Claude Code CLI, running as a non-root `agent` user.
# Add your project's toolchain (python, go, ...) here if the agent needs to run
# it to understand the project.
FROM node:22-bookworm
RUN apt-get update && apt-get install -y --no-install-recommends \
git \
curl \
jq \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*
# Claude Code CLI (the agent runtime).
RUN npm install -g @anthropic-ai/claude-code
# Non-root agent user. `sandcastle docker build-image` aligns AGENT_UID/GID to
# the host user via --build-arg to avoid permission errors on bind mounts.
# node:22-bookworm already ships a "node" user at UID/GID 1000, so we RENAME it
# (the stock Sandcastle template pattern) — groupadd/useradd would collide with
# the existing IDs on a default build.
ARG AGENT_UID=1000
ARG AGENT_GID=1000
RUN groupmod -o -g ${AGENT_GID} node \
&& usermod -o -u ${AGENT_UID} -g ${AGENT_GID} -d /home/agent -m -l agent node
USER ${AGENT_UID}:${AGENT_GID}
WORKDIR /home/agent
# Sandcastle bind-mounts the worktree and sets the working directory at
# container start; the container just needs to stay alive until then.
ENTRYPOINT ["sleep", "infinity"]
# Auth for the Claude Code agent.
# Run `claude setup-token` on your host to generate a token, then paste it here
# in your local .sandcastle/.env (never commit the real .env).
CLAUDE_CODE_OAUTH_TOKEN=
import { run, claudeCode } from "@ai-hero/sandcastle";
import { docker } from "@ai-hero/sandcastle/sandboxes/docker";
// A single Claude Code agent documents the repository over up to four passes,
// committing each doc incrementally. The sandbox hook installs dependencies once
// on startup so the agent can actually run the project while it writes about it.
// The prompt seeds the agent with a shell-expanded file map (`git ls-files`), and
// the agent emits the completion signal when the docs are done, ending early.
const result = await run({
name: "docs-from-codebase",
agent: claudeCode("claude-opus-4-8", { effort: "high" }),
sandbox: docker({ imageName: "sandcastle:docs-from-codebase" }),
promptFile: ".sandcastle/prompt.md",
maxIterations: 4,
completionSignal: "<promise>DOCS_DONE</promise>",
hooks: {
sandbox: {
onSandboxReady: [{ command: "npm install", timeoutMs: 300_000 }],
},
},
});
console.log(`Ran ${result.iterations.length} iteration(s).`);
console.log(`Wrote docs in ${result.commits.length} commit(s) on ${result.branch}.`);
Document this codebase
You are a staff engineer writing the documentation this repository is missing.
Your goal is a genuinely useful docs/ directory that a new contributor could
read to get productive — grounded in the actual code, never invented.
Repository file map
!git ls-files | head -300
What to produce
Write (or update) these under docs/, committing after each file so progress is
incremental and reviewable:
docs/getting-started.md— what the project is, prerequisites, how to install, configure, run, and test it. Verify the commands by actually running them in the sandbox (dependencies are already installed); document what really works, not what you assume.docs/architecture.md— the big picture: the main components, how data and control flow between them, key directories, and the important design choices. A simple ASCII or Mermaid diagram is welcome.docs/reference/<module>.md— one reference page per significant module or package: its responsibility, public surface (key functions/types), inputs and outputs, and gotchas. Cover the modules that carry real logic; skip generated files and trivial re-exports.
How to work
- Read before you write. Use the file map above to orient, then open the files that matter. Cite real symbols and paths.
- Match the project's existing tone and any docs already present; improve them rather than duplicating.
- Keep each pass focused and commit with clear messages (e.g.
docs: add architecture overview).
When the getting-started guide, the architecture overview, and reference pages
for every significant module are written and committed, output the exact line
<promise>DOCS_DONE</promise> and stop.
README
Docs From Codebase
Point one Claude Code agent at an under-documented repository and get back a real
docs/ set — a getting-started guide, an architecture overview, and per-module
reference pages — grounded in the code that actually exists, not in guesses.
What it does
Most codebases are documented badly or not at all, and the docs that do exist rot
the moment the code moves. This workflow reads your repository and writes the
documentation a new contributor actually needs. Because dependencies are installed
in the sandbox, the agent can run the project to confirm the commands it writes
down really work — so the getting-started guide is verified, not assumed. It
commits each doc incrementally and stops when the set is complete, emitting
<promise>DOCS_DONE</promise>.
How it works
main.ts runs a single claude-opus-4-8 agent in a Docker sandbox for up to four
passes. An onSandboxReady hook runs npm install once so the project is
runnable, and the prompt seeds the agent with a shell-expanded repository map via
a !`git ls-files | head -300` block — giving it an instant sense of the
layout before it opens a single file. Across passes it writes
docs/getting-started.md, docs/architecture.md, and one
docs/reference/<module>.md per significant module, committing as it goes.
The topology is a loop: install → map → write & commit docs → next pass.
Requirements
Set CLAUDE_CODE_OAUTH_TOKEN in .sandcastle/.env (run claude setup-token on
your host). The default sandbox hook runs npm install; if your project is not
npm-based, adjust or remove that hook in .sandcastle/main.ts and add your
toolchain to the Dockerfile. Build the image once with
npx @ai-hero/sandcastle docker build-image, then run it with
npx tsx .sandcastle/main.ts. Docs land in docs/.