Agent Manifest
Overview
Section titled “Overview”Every agent repo must contain a jackin.agent.toml file at the repository root. This manifest tells jackin’ how to build, configure, and identify the agent.
jackin’ enforces strict parsing — unknown fields are rejected with an error. This catches typos and prevents silent misconfiguration.
Full schema
Section titled “Full schema”dockerfile = "Dockerfile"
[identity]name = "The Architect"
[claude]plugins = ["code-review@claude-plugins-official"]
[hooks]pre_launch = "hooks/pre-launch.sh"
[env.PROJECT]interactive = trueoptions = ["project1", "project2"]prompt = "Select a project:"
[env.BRANCH]interactive = truedepends_on = ["env.PROJECT"]prompt = "Branch name:"default = "main"Top-level fields
Section titled “Top-level fields”| Field | Required | Description |
|---|---|---|
dockerfile | Yes | Relative path to the Dockerfile within the repo |
The Dockerfile path must:
- Be relative (no absolute paths)
- Stay inside the repository (no
../escapes) - Point to a valid Dockerfile
- Have a final stage that starts with
FROM projectjackin/construct:trixie
[claude]
Section titled “[claude]”| Field | Required | Description |
|---|---|---|
plugins | No | List of Claude plugin identifiers to install at runtime |
Example values:
dockerfile = "Dockerfile"
[claude]plugins = [ "code-review@claude-plugins-official", "feature-dev@claude-plugins-official"][identity]
Section titled “[identity]”| Field | Required | Description |
|---|---|---|
name | No | Human-readable display name for the agent |
When omitted, jackin’ uses the class selector name.
[hooks]
Section titled “[hooks]”| Field | Required | Description |
|---|---|---|
pre_launch | No | Relative path to a bash script run before Claude starts |
The pre-launch hook runs inside the container after plugin installation but before Claude Code launches. It has access to all resolved environment variables.
The script path must:
- Be relative (no absolute paths)
- Stay inside the repository (no
../escapes) - Point to an existing, non-empty file
- Not be a symlink
Example:
[hooks]pre_launch = "hooks/pre-launch.sh"#!/bin/bashset -euo pipefail
# Configure Context7 MCP if API key is availableif [ -n "${CONTEXT7_API_KEY:-}" ]; then ctx7 setup --claude --mcp --api-key "$CONTEXT7_API_KEY" -yfi[env.<NAME>]
Section titled “[env.<NAME>]”Declare environment variables that the agent needs at runtime. Each variable is a TOML table under [env].
Fields
Section titled “Fields”| Field | Type | Default | Description |
|---|---|---|---|
default | String | — | Default value (used if no prompt or user accepts default) |
interactive | bool | false | Whether to prompt the user at launch time |
skippable | bool | false | Whether the user can skip this prompt |
prompt | String | Variable name | Text shown when prompting |
options | String[] | [] | Options for a select-style prompt |
depends_on | String[] | [] | Variables that must be resolved first (use env. prefix) |
Validation rules
Section titled “Validation rules”- A non-interactive variable must have a
defaultvalue optionsrequiresinteractive = truedepends_onentries must use theenv.prefix (e.g.,"env.PROJECT")depends_onmust reference variables declared in the same manifestCLAUDE_ENVis reserved for jackin and cannot be declared in[env]- Circular dependencies are rejected
Runtime-managed variables
Section titled “Runtime-managed variables”jackin sets CLAUDE_ENV=jackin automatically inside the container to mark the isolated runtime. Do not declare CLAUDE_ENV in [env].
Interactive text input
Section titled “Interactive text input”Prompt the user for a free-text value:
[env.GIT_BRANCH]interactive = trueprompt = "Branch name:"
[env.BRANCH_WITH_DEFAULT]interactive = trueprompt = "Branch name:"default = "main"Interactive select
Section titled “Interactive select”Present a list of options:
[env.PROJECT]interactive = trueoptions = ["frontend", "backend", "infra"]prompt = "Select a project:"Skippable prompts
Section titled “Skippable prompts”Allow the user to skip a prompt. The variable won’t be set:
[env.API_KEY]interactive = trueskippable = trueprompt = "API key (optional):"Dependencies
Section titled “Dependencies”Control prompt ordering and skip cascading:
[env.PROJECT]interactive = trueskippable = trueoptions = ["frontend", "backend"]prompt = "Select a project:"
[env.BRANCH]interactive = truedepends_on = ["env.PROJECT"]prompt = "Branch to work on:"default = "main"If a skippable variable is skipped, all variables that depend on it are also skipped — regardless of their own skippable setting.
Minimal example
Section titled “Minimal example”The smallest valid manifest:
dockerfile = "Dockerfile"
[claude]plugins = []Complete example
Section titled “Complete example”dockerfile = "docker/Dockerfile.agent"
[identity]name = "The Architect"
[claude]plugins = ["code-review@claude-plugins-official"]
[hooks]pre_launch = "hooks/pre-launch.sh"
[env.CONTEXT7_API_KEY]interactive = trueskippable = trueprompt = "Context7 API key:"
[env.PROJECT]interactive = trueoptions = ["frontend", "backend", "infra"]prompt = "Select a project to clone"
[env.BRANCH]interactive = truedepends_on = ["env.PROJECT"]prompt = "Branch name:"default = "main"