Skip to content

Latest commit

 

History

History
151 lines (115 loc) · 8.2 KB

File metadata and controls

151 lines (115 loc) · 8.2 KB

Repos — the repositories tasks operate on

Every task runs against a repo: the git repository it clones, works in, and (for the GitHub workflows) opens a PR against. A repo is more than a git URL, though — it also carries the per-repo configuration the runner needs to build and launch a task container: which secrets to inject, what to add to the container image, which container privileges to grant, and which workflows the repo offers.

Crucially, a repo record holds mostly references, never the sensitive values themselves. The secrets, image layer, and hook script live as files on each runner host; the repo only names them. That keeps secrets out of the database, artifacts, and image layers, and lets a remote runner resolve each reference against its own host — so the value stays host-agnostic and never crosses the wire.

A repo's identity is its id; name is the human label. Every task carries a repo_id pointing at one.

Fields

The Repo model (src/panopticon/core/models.py) has these fields:

Field Meaning
id Stable identifier; a task references it as repo_id.
name Human-readable label.
git_url Git remote the per-task clone is cloned from and origin points at.
default_base Default base branch for new tasks (defaults to main).
env_file Name (relative to the secrets dir) of an env-file of secrets, injected at spawn via --env-file. See Secrets.
image_layer_file Name (relative to the layers dir) of a Dockerfile fragment — the repo tier of the composed image. See Container image.
capabilities Opt-in map for elevated container privileges (e.g. docker_in_docker). See Capabilities.
hook_file Name (relative to the hooks dir) of a script the runner runs before docker run. See Host hook.
enabled_workflows / disabled_workflows Filter which workflows the repo offers. See Workflow visibility.

The three reference fields (env_file, image_layer_file, hook_file) are all optional — a minimal repo is just an id, name, and git_url.

Secrets (env_file)

env_file is a name relative to the secrets dir$PANOPTICON_CONFIG/secrets, default ~/.config/panopticon/secrets/ — naming a file of KEY=value lines. At spawn the runner resolves the name against its own host's secrets dir and injects the file with docker run --env-file, so the task container gets exactly its repo's secrets and nothing else.

Because only the name is stored, secrets stay out of the database, artifacts, and image layers, and a remote runner resolves the same name against its own host — the file's content never crosses the wire. The resolver refuses any name that escapes the secrets dir (a .. segment or an absolute path).

The env-file's most important entry is the container's claude auth token, CLAUDE_CODE_OAUTH_TOKEN (plus any ANTHROPIC_API_KEY or GH_TOKEN the tasks need). You don't have to write it by hand: panopticon quickstart sets a repo's token up at any time, and the setup-repo workflow is available from the dashboard whenever you need to (re-)mint it — press g to open the repos modal, highlight the repo, and press s. See auth.md for the details and the by-hand path.

env_file is validated at create time: POST /repos rejects a reference whose file doesn't exist under the secrets dir.

Container image (image_layer_file)

image_layer_file is a name relative to the layers dir, naming a Dockerfile fragment (not inline content) — the repo's own tier of the task image, which the runner composes as base → workflow → repo and builds at spawn. This is where a repo layers on its toolchain, for example installing uv and make. The task service serves the fragment over GET /repos/{id}/image-layer; the layer is optional (declare none and the repo tier is empty), and secrets are never baked in — they're injected at run time via env_file. See layers.md for how the layers compose.

Capabilities

capabilities is a JSON opt-in map for elevated container privileges the runner grants at spawn. The first (and currently only) capability is docker_in_docker: set it and the runner spawns the container --privileged, gives it a volume for /var/lib/docker, and the entrypoint starts a nested Docker daemon. It's off by default because it's a trust escalation — a privileged container is effectively host root — so a repo opts in only when its tasks genuinely need to run Docker.

Host hook (hook_file)

hook_file names a script the runner runs on the host after the per-task workspace is prepared but before docker run — a chance to adjust the checkout before the agent sees it (for example stripping host-only config files). Like env_file, it is a name relative to the hooks dir ($PANOPTICON_CONFIG/hooks), resolved against each runner's own host. See hooks.md for what the hook receives and how failures are handled.

Workflow visibility

enabled_workflows and disabled_workflows filter which workflows the repo offers in the task-creation picker, on top of each workflow's own opt-in flag. GET /repos/{id}/workflows returns the filtered list.

How a task uses its repo

When the session service spawns a task, it uses the repo's fields in order:

  1. Fetch the repo by the task's repo_id.
  2. Prepare the per-task clonegit clone --local from the host's per-repo cache into a fresh directory mounted read-write at /workspace.
  3. Run hook_file on the host, if the repo declares one.
  4. Compose the image — fetch the workflow and repo (image_layer_file) layers, build base → workflow → repo.
  5. docker run the container with the repo's config: --env-file from env_file, the /workspace mount, and --privileged when capabilities.docker_in_docker is set.

Managing repos from the dashboard

panopticon quickstart registers the repo you run it in and enables the matching workflow. To add or reconfigure other repos, use the dashboard's repos modal.

Press g to open it. It lists your repos; from there:

  • n — add a repo.
  • e — edit the highlighted repo.
  • s — run the highlighted repo's setup-repo task, which mints its claude token (see auth.md).
  • esc — close.

n and e open the repo form, which has two tabs. Space toggles a checkbox; Enter (or Ctrl+S) saves from any field; Esc cancels.

general — the repo's core fields:

  • git_url — the git remote. It leads: in create mode, blank id and name auto-fill from it.
  • id — stable identifier. Editable only when creating; shown read-only when editing.
  • name — human label.
  • default_base — base branch for new tasks (defaults to main).
  • env_file, image_layer_file, hook_file — the reference fields described above.
  • privileged docker (docker-in-docker) — a checkbox for the one capability the form edits; it maps to capabilities.docker_in_docker. Other capability keys are left untouched on save.

workflows — a checklist of the workflows this repo can offer. This is where you turn on github-self-reviewed, github-peer-reviewed, and the rest. An opt-in workflow is off until you check it; an opt-out one is on until you uncheck it.

Managing repos over REST

Repos are also managed over the task service's REST API:

  • POST /repos — create a repo (validates that env_file exists).
  • GET /repos / GET /repos/{id} — list or fetch.
  • PATCH /repos/{id} — partial update; fields you don't send are preserved.
  • GET /repos/{id}/workflows — the workflows this repo offers.
  • GET /repos/{id}/image-layer — the repo's composed Dockerfile layer.

Related

  • auth.md — the claude token that lives in env_file.
  • layers.md — how the base → workflow → repo image layers compose.
  • hooks.md — repo hooks and how hook_file resolves.
  • workflows/setup-repo.md — host-side utility that mints and places the auth token.