A pack is a portable definition of behavior: agents, prompt templates,
providers, formulas, orders, commands, doctor checks, overlays, skills, and
other reusable assets. A city is the root pack plus a city.toml deployment
file and machine-local .gc/ bindings.
Packs separate three concerns:
pack.toml and pack directories define what the system is.
city.toml defines how this deployment runs.
.gc/ stores local site bindings and runtime state managed by gc.
Legacy include and pack registry fields may still load for migration
compatibility, but new docs and new packs should use imports and
agents/<name>/ directories.
Pack Layout
Pack structure is convention-based. Standard directories are loaded by name;
opaque helper files belong under assets/.
Minimal pack.toml
Pack metadata and imports live in pack.toml. Agent definitions live in
agents/<name>/.
schema = 2 is the current pack format. [agent_defaults] applies to
agents discovered from agents/ unless an agent’s own agent.toml overrides a
field.
Agent Directories
A minimal agent is just a directory with a prompt:
Use agent.toml for fields that differ from pack defaults:
Prompt file discovery prefers prompt.template.md. prompt.md and
prompt.md.tmpl are accepted for compatibility.
Imports
Packs compose other packs with named imports. The [imports.<binding>] key is
the local binding you choose; it qualifies the imported agents’ names so
gastown.polecat and review.polecat coexist. See
Understanding Packs for how bindings,
qualified names, and collisions work — this section is about authoring the
imports.
Local imports use a path relative to the importing pack. Remote imports use
source plus an optional version constraint. For GitHub-hosted packs below a
repository root, prefer the same /tree/<ref>/<path> URL a browser can open:
Do not write registry handles such as main:gastown into pack.toml. Registry
handles are command-time lookup shortcuts; authored pack TOML stores the
resolved durable source and, when needed, version.
Registry Discovery
Registries help you find packs; they never change the authored import shape.
When you add a pack from a registry, pack.toml stores the resolved durable
source and optional version, not the registry handle. The main registry
(the public gascity-packs catalog) is configured by default:
Registry pack names are scoped as <github-owner>/<pack>. Before you publish,
[pack].name must already carry that scoped name, and its scope must equal the
lowercased GitHub owner of the source repository: publish submits the name
pack.toml declares, and the registry compares the two byte-for-byte. Unscoped
names are reserved — the registry accepts one only when it already holds a
claim for it, which is what --allow-unscoped-name is for.
See Public Registry Packs for the first-party
catalog and cache-freshness controls (--refresh, GC_REGISTRY_FRESHNESS), and
Understanding Packs
for the handle-vs-source model.
City Usage
A city imports packs at the root pack level and declares deployment details in
city.toml.
Machine-local rig paths are site bindings managed by gc:
Rig-Level Imports
Use rig-level imports when only one rig should receive a pack’s agents or
formulas.
Rig-level imports create rig-scoped identities such as
backend/gastown.polecat and backend/review.reviewer.
Gas City’s built-in packs are not implicit. gc init writes explicit
pinned imports into pack.toml (core, plus bd for bd-provider
cities), and gc doctor --fix repairs
missing or stale entries. The former maintenance pack no longer exists; its
housekeeping orders ship in the bundled core pack. See
System Packs for details.
Named Sessions
Packs can declare sessions that should exist independent of current work.
The template is an agent name from the same pack or an imported qualified
name when needed.
Customizing Imported Agents
Use patches to modify imported agents without redefining them.
For rig-specific customization, patch under the rig:
Formula files go in formulas/ and order files go in orders/. No
[formulas].dir declaration is needed for packs.
When multiple packs provide the same formula name, the importing pack wins over
its imports. Rig-level imports can override city-level formulas for that rig.
Compatibility Notes
The loader still exposes some V1 fields for migration and old city support:
workspace.includes
[[rigs]].includes
[packs.*]
[formulas].dir is not among them: it does not load at all. A
[formulas].dir declaration is a hard parse error in city.toml, in every
config fragment, and in pack.toml ([formulas].dir is no longer supported; use the well-known formulas/ directory), and gc doctor reports any
remaining declaration through the fixable v2-formulas-dir check. Put
formulas in the well-known formulas/ directory.
Treat the listed fields as migration surfaces for your own packs. gc doctor --fix migrates root pack.toml legacy inline agent definitions into
agents/<name>/agent.toml; legacy definitions inside config fragments still
need a hand edit. New shareable packs should use schema = 2, [imports.*],
agents/<name>/, conventional formulas/, and patches for customization. Last modified on October 30, 2026