From fe5b27a3661ac00826ec192e6524ede5dabad48e Mon Sep 17 00:00:00 2001 From: Dmitry Orlov Date: Mon, 18 May 2026 12:12:07 +0200 Subject: [PATCH 1/2] More docs --- docs/commands/auth.md | 41 ++++-- docs/commands/file.md | 31 ++-- docs/commands/images.md | 24 ++++ docs/commands/operation.md | 23 ++- docs/commands/session.md | 90 +++++++++++- docs/commands/skill.md | 84 ++++++++--- docs/tutorial/build.md | 280 +++++++++++++++++++++++++++++++++++++ docs/tutorial/images.md | 2 +- docs/tutorial/index.md | 17 ++- 9 files changed, 536 insertions(+), 56 deletions(-) create mode 100644 docs/tutorial/build.md diff --git a/docs/commands/auth.md b/docs/commands/auth.md index dcfb3f5..4ef71af 100644 --- a/docs/commands/auth.md +++ b/docs/commands/auth.md @@ -83,12 +83,18 @@ export NEBIUS_AI_PROJECT=your-project-id contree auth -y # no prompts, saves immediately ``` -## `auth ls` status column +## `auth list` -`contree auth ls` verifies each saved profile against the API -with a 2-second timeout and adds a `status` column. +`contree auth list` (alias `auth ls`, `profiles`) prints every saved +profile from `auth.ini` and verifies each one against the API with a +2-second timeout, adding a `status` column that tells you at a glance +which profiles are usable. Pass `--offline` to suppress the probe +entirely when you only want to inspect what is saved locally. -Possible values: +```{terminal-shell} contree auth list --help +``` + +Possible `status` values: - `ok` -- probe succeeded and the token has the `list` permission - `inactive` -- probe succeeded but the token lacks the `list` @@ -98,9 +104,6 @@ Possible values: another network/API error - `offline` -- you passed `--offline`, so no probe was attempted -Use `contree auth ls --offline` when you want to inspect saved -profiles without any network traffic. - For automation and agents, prefer: ```bash @@ -108,9 +111,28 @@ contree -f json auth ls contree -f json auth ls --offline ``` +## `auth switch` + +`contree auth switch NAME` rewrites the `active` pointer in `auth.ini` +so subsequent commands resolve credentials from that profile. The +profile must already exist (created by `contree auth --profile=NAME`). +Switching does not touch token data, so it is safe to run as often as +you like to bounce between projects. + +```{terminal-shell} contree auth switch --help +``` + ## `auth remove` -Delete a saved profile from the config file. +`contree auth remove NAME` (aliases `rm`, `del`) deletes the profile +from `auth.ini` and removes its per-profile session database +(`sessions-NAME.db`). If the deleted profile was the active one, the +CLI promotes the first remaining profile to active (or falls back to +`default` if none remain). Confirmation is required unless `-y` is +passed. + +```{terminal-shell} contree auth remove --help +``` ```bash contree auth remove personal @@ -118,9 +140,6 @@ contree auth rm personal # alias contree auth del personal -y # skip confirmation ``` -If the removed profile was active, the CLI switches to the first -remaining profile (or `default` if none remain). - :::{warning} Avoid `--token=eyJ...` on the command line — the token is visible in process listings (`ps`) and shell history. Omit `--token` to use the diff --git a/docs/commands/file.md b/docs/commands/file.md index 1bc8e55..a8e4f48 100644 --- a/docs/commands/file.md +++ b/docs/commands/file.md @@ -25,21 +25,31 @@ contree run nginx -t ### `file edit` -Downloads a file from the session image, opens it in `$EDITOR` (defaults to -`vi`), and stages the changes if the file was modified. If the file does not -exist in the image, an empty file is created. +`contree file edit PATH` (alias `e`) downloads the file at `PATH` from +the session image, opens it in `$EDITOR` (defaults to `vi`), and stages +the modified buffer as a pending upload that will be injected into the +next `contree run`. Missing files are created as empty buffers so the +command doubles as `touch + open`. + +```{terminal-shell} contree file edit --help +``` ### `file cp` -Copies a local file and stages it at the given path inside the image. The -file is uploaded immediately but only applied to the sandbox on the next -`contree run`. +`contree file cp SRC DEST` (alias `f`) reads a local file at `SRC`, uploads +it to the project's file store, and stages it for delivery at `DEST` inside +the session image on the next `contree run`. Use this when you have a file +ready on disk locally and just want it materialised inside the sandbox +without spawning an instance first. + +```{terminal-shell} contree file cp --help +``` ### `file ls` -Lists files uploaded to the project (`GET /v1/files`) and joins each row -with the local upload cache. The `SOURCE` column shows whatever this -machine produced the file from: +`contree file ls` lists files uploaded to the project (`GET /v1/files`) +and joins each row with the local upload cache. The `SOURCE` column shows +whatever this machine produced the file from: - absolute host path for files uploaded via `run --file` or `COPY`; - `https://...` URL for files fetched via `ADD URL`. @@ -72,6 +82,9 @@ contree file ls -q # uuid + sha256 + source only contree -f json file ls | jq 'select(.source != "")' ``` +```{terminal-shell} contree file ls --help +``` + ## Pending files Pending files accumulate until the next `contree run` consumes them. diff --git a/docs/commands/images.md b/docs/commands/images.md index 1563d81..b251167 100644 --- a/docs/commands/images.md +++ b/docs/commands/images.md @@ -43,6 +43,30 @@ contree images --prefix=common/ `--since` and `--until` accept either ISO timestamps or duration intervals like `1h`, `30m`, `7d`. +## Subcommands + +### `images list` + +`contree images list` (alias `ls`) is the explicit form of the bare +`contree images` invocation. Both share the same flag set -- pick the +explicit form when you want a command that reads symmetrically with +`images import`, or in scripts that already use the subcommand style +everywhere. + +```{terminal-shell} contree images list --help +``` + +### `images import` + +`contree images import REF [REF ...]` pulls one or more images from an +external OCI registry into the project and waits for the import +operation to finish. Each reference may be a `docker://` URL or any +form the platform accepts; multiple refs are imported sequentially with +shared credentials, and Ctrl-C cancels the in-flight operation cleanly. + +```{terminal-shell} contree images import --help +``` + ## See also - {doc}`tag` -- assign a tag to an image diff --git a/docs/commands/operation.md b/docs/commands/operation.md index 5878cae..0e2a51a 100644 --- a/docs/commands/operation.md +++ b/docs/commands/operation.md @@ -41,20 +41,23 @@ contree op cancel --all ## Help output +The top-level `op` command is a dispatcher: by itself it only prints +usage and routes to the three subcommands described below. + ```{terminal-shell} contree op --help ``` -```{terminal-shell} contree op list --help -``` +## `op list` -- dynamic columns -```{terminal-shell} contree op show --help -``` +`contree op list` (alias `op ls`) accepts the same filter flags as +`contree ps` (`-a`, `-S STATUS`, `-K KIND`, `--since`, `--until`, +`-q`/`--quiet`) and shares its rendering pipeline. Reach for it when +you want the operations namespace to feel symmetric with the +multi-UUID `show` and `cancel`; otherwise `contree ps` is just as good. -```{terminal-shell} contree op cancel --help +```{terminal-shell} contree op list --help ``` -## `op list` -- dynamic columns - The listing renders **every scalar top-level field** the API returns, not a hard-coded subset. When the server adds a new field (for example `cost`, `project_id`, `started_at`), it appears in the output without a @@ -81,6 +84,9 @@ work uniformly. On API errors (e.g. 404 for an unknown UUID), the command logs the failure and continues with the remaining UUIDs, exiting with status `1` at the end. +```{terminal-shell} contree op show --help +``` + :::{note} With table output (`-f table`) and several UUIDs, each operation currently renders as its own mini-table. Use `default` or `json` for a @@ -95,6 +101,9 @@ operation (`PENDING`, `ASSIGNED`, `EXECUTING`). Combining both is allowed: with `op show`, errors on individual UUIDs do not abort the run; the command exits `1` if any cancellation failed. +```{terminal-shell} contree op cancel --help +``` + ```bash # Mixed: --all still wins, "ignored-1" is not cancelled contree op cancel --all ignored-1 diff --git a/docs/commands/session.md b/docs/commands/session.md index 849741f..f3a8d1f 100644 --- a/docs/commands/session.md +++ b/docs/commands/session.md @@ -56,9 +56,95 @@ branch just adds a new pointer at the current position. Rollback moves the branch pointer backwards. History entries are preserved and can be recovered by creating a new branch. -## `session delete` +## Subcommands -Remove sessions and all their data (history, branches, files, shell history). +### `session list` + +`contree session list` (alias `ls`) prints every session known to the +current profile, with the active session marked. The optional +`--filter` flag narrows the list by substring match against the session +key, which is handy when you keep many disposable sessions named after +features or tickets. + +```{terminal-shell} contree session list --help +``` + +### `session use` + +`contree session use KEY` imports the **current image** of another +session into the active session as a new history entry. The source +session is not modified; this is a "fork the snapshot, keep working +here" operation, distinct from the top-level `contree use` which starts +or resumes a session against an image reference. + +```{terminal-shell} contree session use --help +``` + +### `session branch` + +`contree session branch` (alias `br`) lists branches with `*` marking +the active one. Pass a name to create a new branch pointing at the +current history position, or combine with `--from BRANCH` to fork off a +different branch. The `-U`/`--prune` flag removes branches that no +longer reference live history. + +```{terminal-shell} contree session branch --help +``` + +### `session checkout` + +`contree session checkout BRANCH` (alias `co`) switches the active +branch pointer. Working directory, pending files, and the current +image are all reset to whatever the target branch currently points at, +so it is the safe way to bounce between parallel experiments. + +```{terminal-shell} contree session checkout --help +``` + +### `session rollback` + +`contree session rollback [TARGET]` (alias `rb`) navigates the history +of the current branch. With no argument it steps back one entry; a +positive number jumps to that absolute history index, `-N` steps back +`N` entries, and `+N` steps forward. History entries are preserved -- +rollback only moves the branch pointer. + +```{terminal-shell} contree session rollback --help +``` + +### `session show` + +`contree session show` prints the session history DAG with one row per +entry, including operation IDs, image UUIDs, branch pointers, and +relative timestamps. Use `-a` to include hidden entries, `-k KIND` to +filter by entry kind (e.g. `run`, `cd`), and `-l LAST` to show only the +last N rows. + +```{terminal-shell} contree session show --help +``` + +### `session wait` + +`contree session wait [OP_ID ...]` blocks until the specified operations +reach a terminal state (`SUCCESS`, `FAILED`, or `CANCELLED`). When no +IDs are given it waits for every active operation in the session, which +is the canonical way to drain background `contree run -d` jobs before +moving on. + +```{terminal-shell} contree session wait --help +``` + +### `session delete` + +`contree session delete KEY [KEY ...]` (aliases `rm`, `del`) removes +sessions and all their data -- history, branches, pending files, shell +history. The command prompts before deleting unless `-y` is passed. +Use this to garbage-collect throwaway sessions; the disk savings on +the SQLite database can be substantial when many short-lived sessions +accumulate. + +```{terminal-shell} contree session delete --help +``` ```bash contree session delete KEY [KEY ...] diff --git a/docs/commands/skill.md b/docs/commands/skill.md index 7db264a..821d279 100644 --- a/docs/commands/skill.md +++ b/docs/commands/skill.md @@ -4,27 +4,37 @@ Install, remove, or upgrade ConTree agent skills for Codex and Claude Code. ## Spec format -Commands accept **specs** — a `kind:hint` URI that identifies the skill type +Commands accept **specs** -- a `kind:hint` URI that identifies the skill type and target path: | Spec | Resolves to | Skill type | |------|------------|------------| -| `claude:` | `.claude/skills/contree` (project-level) | ClaudeSkill | +| `claude:` | `.claude/skills/contree` (project) | ClaudeSkill | | `claude:~` | `~/.claude/skills/contree` (global) | ClaudeSkill | -| `codex:` | `.codex/skills/contree` (project-level) | OpenAISkill | -| `codex:~` | `~/.codex/skills/contree` (global) | OpenAISkill | +| `codex:` | `.codex/skills/contree` (project) | CodexSkill | +| `codex:~` | `~/.codex/skills/contree` (global) | CodexSkill | +| `opencode:` | `.opencode/skills/contree` (project) | OpenCodeSkill | +| `opencode:~` | `$OPENCODE_HOME/skills/contree` (or `~/.config/opencode/skills/contree`) | OpenCodeSkill | +| `amp:` | `.amp/skills/contree` (project) | AmpSkill | +| `amp:~` | `~/.config/agents/skills/contree` (global) | AmpSkill | +| `cline:` | `.cline/skills/contree` (project) | ClineSkill | +| `cline:~` | `$CLINE_DIR/skills/contree` (or `~/.cline/skills/contree`) | ClineSkill | +| `claude-subagent:` | `.claude/agents/contree-subagent.md` (project) | ClaudeSubagentSkill | +| `claude-subagent:~` | `~/.claude/agents/contree-subagent.md` (global) | ClaudeSubagentSkill | | `claude-agent:` | `.claude/agents/contree.md` (project) | ClaudeAgentSkill | | `claude-agent:~` | `~/.claude/agents/contree.md` (global) | ClaudeAgentSkill | -| `claude://./path` | `./path` (explicit) | ClaudeSkill | -| `./path` | `./path` (guessed from path) | auto | +| `./path` | `./path` (skill type guessed from path) | auto | -When no specs are given, `install` defaults to all detected agent homes -(e.g. `codex:~ claude:~ claude-agent:~`). +When no specs are given, `install` targets the global (`:~`) variant of +**every** known kind. The Claude-based kinds (`claude`, `claude-agent`, +`claude-subagent`) are skipped unless `~/.claude` already exists, so a +machine without Claude Code installed will not have empty directories +created for it. ## Examples ```bash -# Install globally (default: codex:~ claude:~) +# Install globally to every known kind (Claude kinds gated on ~/.claude) contree skill install # Install into project-level .claude/skills/contree @@ -61,23 +71,53 @@ contree skill ls ```{terminal-shell} contree skill --help ``` -## Behavior +## Subcommands -`contree skill install [SPEC ...]` installs skill directories. Each spec -resolves to a skill class and a filesystem path. The skill class (`kind`) -is stored in the session SQLite database alongside the resolved path. +### `skill install` -`contree skill list` shows remembered installs with their kind, -installed version, latest available version, outdated flag, and -whether the path exists on disk. +`contree skill install [SPEC ...]` (alias `i`) installs skill directories. +Each spec resolves to a skill class and a filesystem path, both of which +are persisted in `skills.db` so future `list` and `upgrade` calls can +find the install without re-specifying it. With no specs the command +targets the global (`:~`) variant of every known kind -- Claude-based +kinds are skipped automatically when `~/.claude` does not exist. Pass +`-y` to overwrite an existing install non-interactively. -`contree skill upgrade [SPEC ...]` overwrites existing installs with the -current bundled version. Without specs, upgrades all remembered locations. -A `.version` file in each install directory tracks the installed version -for quick outdated detection. +```{terminal-shell} contree skill install --help +``` + +### `skill list` + +`contree skill list` (alias `ls`) shows every remembered install with +its kind, installed version (read from `.version`), the version +bundled with this CLI, an `outdated` flag, and whether the install +path still exists on disk. Stale entries whose path was deleted +externally are pruned from the registry automatically when this +command runs. + +```{terminal-shell} contree skill list --help +``` + +### `skill upgrade` -`contree skill remove SPEC [...]` deletes installed skill files and -forgets the path from the registry. +`contree skill upgrade [SPEC ...]` overwrites existing installs with +the version bundled in the current CLI. With no specs it upgrades +every remembered location, which is the normal post-`pip install -U` +maintenance step. Targets that are already at the bundled version are +rewritten anyway so any local edits to skill files are reverted. + +```{terminal-shell} contree skill upgrade --help +``` + +### `skill remove` + +`contree skill remove SPEC [...]` (aliases `r`, `rm`, `del`) deletes +installed skill files and forgets the path from the registry. Specs +may be the same URI form accepted by `install`, or a literal filesystem +path. Pass `-y` to skip the confirmation prompt. + +```{terminal-shell} contree skill remove --help +``` ### Install contents diff --git a/docs/tutorial/build.md b/docs/tutorial/build.md new file mode 100644 index 0000000..da6d106 --- /dev/null +++ b/docs/tutorial/build.md @@ -0,0 +1,280 @@ +# Building from a Dockerfile + +`contree build` turns a familiar `Dockerfile` into a ConTree image. Each +directive becomes one image layer, every layer is a real session +checkpoint, and re-running the same `Dockerfile` reuses prior layers +through a content-addressed cache. This tutorial walks through the +`build-demo` example shipped with the repo so you can see the moving +parts end-to-end. + +## The example project + +The tree at `docs/examples/build-demo` contains a minimal Python app +plus a Dockerfile that exercises the directives most builds actually +use: + +``` +docs/examples/build-demo/ +├── .dockerignore +├── Dockerfile +├── hello.py +└── src/ + ├── __init__.py + └── banner.py +``` + +`hello.py` reads a greeting from an environment variable and prints a +boxed banner; `src/banner.py` provides the box renderer. Nothing +exotic -- it just gives the Dockerfile something to `COPY` and `RUN`. + +The Dockerfile itself: + +```{literalinclude} /examples/build-demo/Dockerfile +:language: dockerfile +``` + +Six directives, in order: + +1. `FROM python:3.12-alpine` -- resolves the base image. If + `tag:python:3.12-alpine` is not already in the project, `contree build` + auto-imports it from the registry. +2. `ARG GREETING=hello` and `ENV APP_GREETING=${GREETING}` -- declare a + build-time variable and pin its value into a runtime environment + variable that the app will read. +3. `WORKDIR /app` -- sets the working directory for everything below. +4. Two `COPY` directives stage local files (`hello.py` and the `src/` + directory) into the build's pending uploads. +5. `ADD https://...master.zip /tmp/contree-cli.zip` -- streams a remote + archive straight from GitHub into the contree file store, without + creating a local temp file. +6. Five `RUN` directives prove the toolchain works, unpack the zip, + install the CLI from source, and run the demo app. + +## Build context and `.dockerignore` + +The first positional argument to `contree build` is the **build +context** -- the directory that anchors every `COPY` and `ADD` source +path. Anything outside that directory is invisible to the build. In +this example the context is `docs/examples/build-demo`, and the +Dockerfile sits at the top of it. + +A `.dockerignore` next to the Dockerfile keeps junk out of the upload: + +```{literalinclude} /examples/build-demo/.dockerignore +:language: text +``` + +The matcher uses the same rule set as `run --file`: `*` is a +single-segment wildcard, `**` crosses directories, `?` matches one +character, and a leading `!` re-includes a previously ignored path. +The last matching rule wins. On top of your `.dockerignore`, the CLI +always filters `.git`, `__pycache__`, `*.pyc`, `.venv`, +`node_modules`, `dist`, and `build`, so you do not need to repeat the +usual suspects. + +## Your first build + +From the repository root, run: + +```bash +contree build docs/examples/build-demo --tag contree-cli-build-demo:latest +``` + +You should see one log line per directive plus a stdout dump after +each `RUN`: + +```text +[INFO] FROM python:3.12-alpine -> tag:python:3.12-alpine +[INFO] COPY hello.py -> /app/hello.py +[INFO] COPY src -> /app/src +[INFO] ADD https://.../master.zip -> /tmp/contree-cli.zip +[INFO] RUN spawned op=019e... RUN python -c "import sys; print('python', sys.version)" +[INFO] stdout: +python 3.12.13 ... +[INFO] RUN spawned op=019e... RUN python /app/hello.py +[INFO] stdout: ++---------------+ +| hello | +| contree build | ++---------------+ +[INFO] tagged as contree-cli-build-demo:latest +IMAGE TAG SESSION + contree-cli-build-demo:latest build: +``` + +The final tagged image is now usable everywhere a tag is accepted: + +```bash +eval $(contree use tag:contree-cli-build-demo:latest) +contree run python /app/hello.py +``` + +## Layer cache: the second build is free + +Run the same command a second time. Every step prints **cache hit** +and the build finishes in seconds without spawning a single instance. + +The cache key for each layer is a chain hash: + +``` +sha256(parent_layer_hash || state(workdir/env/user/args) + || directive || pending_files) +``` + +That means a layer is reused if and only if: + +- the previous layer was identical, +- the directive text is byte-for-byte the same, +- the resolved environment (`WORKDIR`, `ENV`, `USER`, `ARG`) matches, and +- for `COPY`/`ADD`, the **content** of the staged files matches (the + SHA-256 of every uploaded file, not their timestamps). + +Edit `hello.py`, run the build again, and only the last `RUN` step +plus everything depending on it rebuilds. The earlier `RUN python -c +'import sys; print(sys.version)'` layer is reused because it has no +dependency on `hello.py`. + +Each cached layer is materialised as a branch named +`layer:` inside a session keyed by the absolute path of +the context directory: `build:`. So the +cache is **per-context-path** -- moving the directory or building from +a sibling worktree starts a fresh cache. + +To inspect the layer history: + +```bash +contree session list --filter build: +contree session use build: +contree session show +``` + +`contree session show` prints the DAG with one row per layer and the +chain hash visible in the branch column. Switching to a `layer:` branch +puts you on that layer's image, so you can `contree run` against any +intermediate snapshot to debug a step in isolation. + +To force a rebuild ignoring all cached layers: + +```bash +contree build docs/examples/build-demo --no-cache \ + --tag contree-cli-build-demo:latest +``` + +## Build args and variable substitution + +Variables (`$VAR` and `${VAR}`) expand in `FROM`, `RUN`, `COPY`/`ADD` +arguments, `WORKDIR`, `ENV` values, and `USER`. The lookup order is: + +1. `--build-arg KEY=VALUE` for any `ARG` already declared. +2. `ENV` directives processed so far. +3. `ARG` defaults from the Dockerfile. +4. Empty string for unknown names. + +The demo declares `ARG GREETING=hello` and uses it through +`ENV APP_GREETING=${GREETING}`. Override it at the CLI: + +```bash +contree build docs/examples/build-demo --build-arg GREETING=ciao \ + --tag contree-cli-build-demo:ciao +``` + +The final `RUN python /app/hello.py` step now prints `ciao` in the +boxed banner because the chain hash of the layer that ran +`ENV APP_GREETING=...` changed, invalidating every layer below it. + +## `ADD URL` streams without a temp file + +The `ADD` line in the demo points at a GitHub archive: + +```dockerfile +ADD https://github.com/nebius/contree-cli/archive/refs/heads/master.zip /tmp/contree-cli.zip +``` + +`contree build` opens the HTTP connection and pipes the response body +**directly** into `POST /v1/files` -- the bytes never touch your local +disk. The CLI also remembers the URL's `ETag`, `Last-Modified`, and +`Content-MD5` validators in the per-context cache. On the next build +it issues a conditional `HEAD` first; if the validators match, the +upload is skipped entirely and the log line reads +`URL cache hit (HEAD validators match)`. + +Two things this does **not** do: + +- It does not extract tarballs/zips. Use a `RUN python -m zipfile -e` + (or `tar xf`) directive when you need extraction, exactly like the + demo does. +- It does not follow private auth -- the request is anonymous. Mirror + the asset to a public URL, or `COPY` it from your build context. + +## Supported and skipped directives + +The MVP interpreter implements the directives most Dockerfiles +actually rely on: + +| Implemented | Notes | +|-------------|-------| +| `FROM ref[:tag] [AS name]` | Auto-imports missing tags; `AS name` is parsed but multi-stage is not yet executed. | +| `RUN ...` | Shell-form and JSON exec-form. Spawns one instance per `RUN`. | +| `COPY [--chown=] [--chmod=] SRC... DEST` | Honours `.dockerignore`, dedups by SHA-256. | +| `ADD ...` | Local paths behave like `COPY`; URLs stream through `POST /v1/files`. | +| `WORKDIR`, `ENV`, `ARG`, `USER` | Accumulated and applied to subsequent steps. | + +Directives that are parsed and **skipped with a warning** (the build +continues, the image is still produced): + +`CMD`, `ENTRYPOINT`, `LABEL`, `EXPOSE`, `VOLUME`, `STOPSIGNAL`, +`MAINTAINER`, `HEALTHCHECK`, `ONBUILD`, `SHELL`, +`COPY --from=stage`. + +ConTree images are filesystem snapshots, not OCI runtime configs, so +`CMD`/`ENTRYPOINT` have nowhere to live -- you express the entrypoint +explicitly at `contree run` time instead. + +## When to reach for `build` vs `run` + +The same image you can produce with `contree build` can be produced +by hand with a sequence of `contree run` calls. Pick the right tool: + +| Situation | Prefer | +|-----------|--------| +| You already have a working `Dockerfile` | `contree build` -- just reuse it. | +| You want reproducible, cacheable setup driven from version control | `contree build`. | +| You are still experimenting and do not know the final steps | `contree run` interactively; tag a checkpoint when you are happy. | +| You need `CMD`/`ENTRYPOINT`/`HEALTHCHECK` semantics | Neither -- those are runtime concerns for OCI runtimes, not for ConTree. | +| You want multi-stage builds today | Not yet -- stage `AS` parses but is skipped. Track Phase 2. | + +## Cheat sheet + +```bash +# Simplest build; finds ./Dockerfile in the context, tags the result. +contree build . --tag myapp:dev + +# Out-of-tree Dockerfile. +contree build ./service \ + --dockerfile ./service/Dockerfile.prod \ + --tag svc:prod + +# Override build-time variables. +contree build . \ + --build-arg VERSION=2.5 \ + --build-arg DEBUG=1 + +# Force a full rebuild. +contree build . --no-cache --tag myapp:dev + +# Raise the per-RUN timeout to 30 minutes. +contree build . --timeout 1800 --tag myapp:dev + +# Inspect the build's layer history. +contree session list --filter build: +contree session use build: +contree session show +``` + +--- + +You now have a tagged image that came from a `Dockerfile`, a cached +layer history you can branch off, and a feel for which directives +behave and which are parsed-but-skipped. Next, see +{doc}`workflows` for scripting builds into pipelines, or +{doc}`/commands/build` for the full reference. diff --git a/docs/tutorial/images.md b/docs/tutorial/images.md index 24df3e9..9c823ec 100644 --- a/docs/tutorial/images.md +++ b/docs/tutorial/images.md @@ -150,4 +150,4 @@ contree images --prefix=python-dev --- -Images are your checkpoints. Next: {doc}`workflows`. +Images are your checkpoints. Next: {doc}`build`. diff --git a/docs/tutorial/index.md b/docs/tutorial/index.md index ed1d10d..5b28a37 100644 --- a/docs/tutorial/index.md +++ b/docs/tutorial/index.md @@ -1,7 +1,7 @@ # Tutorial -Learn contree-cli by building a real workflow — from zero to automated -scripting in six short sections. +Learn contree-cli by building a real workflow -- from zero to automated +scripting in nine short sections. ## What you'll build @@ -72,7 +72,15 @@ Tag working images for reuse, import from registries, and search by prefix. Build reusable base environments. ::: -:::{grid-item-card} 7. Scripting & Automation +:::{grid-item-card} 7. Building from a Dockerfile +:link: build +:link-type: doc + +Turn a `Dockerfile` into a tagged ConTree image. Layer caching, +build args, `.dockerignore`, and URL streaming for `ADD`. +::: + +:::{grid-item-card} 8. Scripting & Automation :link: workflows :link-type: doc @@ -80,7 +88,7 @@ Shell mode, shebang scripts, detached runs, operation monitoring, and machine-readable output formats for pipelines. ::: -:::{grid-item-card} 8. Configuration & Profiles +:::{grid-item-card} 9. Configuration & Profiles :link: configuration :link-type: doc @@ -146,6 +154,7 @@ shell sessions files images +build workflows configuration ``` From d20a2de799b95d927f9026742d3874e471189642 Mon Sep 17 00:00:00 2001 From: Dmitry Orlov Date: Mon, 18 May 2026 12:16:20 +0200 Subject: [PATCH 2/2] lost file --- docs/examples/build-demo/.dockerignore | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 docs/examples/build-demo/.dockerignore diff --git a/docs/examples/build-demo/.dockerignore b/docs/examples/build-demo/.dockerignore new file mode 100644 index 0000000..7269d15 --- /dev/null +++ b/docs/examples/build-demo/.dockerignore @@ -0,0 +1,4 @@ +# Demo .dockerignore: keep build context lean +**/*.log +**/__pycache__ +.env*