| title | Coming from Gas Town |
|---|---|
| description | The fastest way to translate Gas Town concepts into Gas City primitives. |
Gas City is the SDK extracted from Gas Town. The fastest way to get productive is to stop looking for a one-to-one port of Town's role tree and instead map Town concepts onto Gas City's primitives:
- agents
- beads
- events
- config
- prompt templates
- derived mechanisms like orders, formulas, waits, mail, and sling
If you built systems in Gas Town, you already know the operational problems Gas City is trying to solve. The main change is where the logic lives.
Gas Town is shaped around a role taxonomy and a filesystem layout. Gas City is shaped around a small primitive set plus configuration.
In Gas Town, it is normal to think in terms of:
- mayor, deacon, witness, refinery, polecat, crew, dog
~/gt/...directory layout- plugins and convoys as named orchestration features
- role-specific managers and cwd-derived identity
In Gas City, the default mental model should be:
- reusable behavior lives in
pack.tomlplus pack directories - deployment choices live in
city.toml - machine-local bindings and runtime state live in
.gc/ - every durable work item is a bead
- agents are generic; roles come from prompts, formulas, orders, and config
- the controller owns SDK infrastructure behavior
- directories are an implementation detail, not the architecture
That is the biggest onboarding difference. Gas City is not "Gas Town with renamed commands". It is the lower-level orchestration toolkit that Gas Town can be expressed in.
| Gas Town concept | Gas City concept | What changes for you |
|---|---|---|
| Town config + rig config + role homes | PackV2: pack.toml, city.toml, agents/, and .gc/ |
Definition, deployment, and machine-local state are separated instead of being spread across role-specific directories and managers. |
| Mayor, deacon, witness, refinery, polecat, crew, dog | Configured agents | Gas City has no baked-in role names in Go. These are pack conventions, not SDK primitives. |
| Plugin | Order | An exec order runs shell directly with no agent session. A formula order instantiates agent work. If you were thinking "plugin that runs a command", start with an exec order. |
| Convoy | Convoy bead plus sling/formulas | Convoys are still bead-backed work grouping, but there is no special convoy runtime layer you have to use to get orchestration. |
| Dog | Usually an order first, sometimes a scalable session config | In Gas Town, dogs are named infrastructure helpers. In Gas City, a lot of that work is cleaner as exec orders because no LLM session is needed. |
| Deacon watchdog logic | Controller and supervisor | Health patrol, order dispatch, wisp GC, and reconciliation are controller concerns, not role-agent responsibilities. |
| Witness lifecycle logic | Pack behavior built on waits, formulas, session scale config, and controller wake/sleep | The SDK gives you the mechanisms. A pack decides whether to model a witness role at all. |
| Crew and polecats as hard types | Persistent sessions and scalable session configs | "Crew" and "polecat" are operating styles. Gas City only knows agent config and session behavior. |
Directory tree under ~/gt |
dir for identity scope and work_dir for session cwd |
Do not encode architecture into paths. Keep identity in config and metadata. Use work_dir only when a role really needs filesystem isolation. |
| Role-specific startup files and local settings dirs | Prompt templates, overlays, provider hooks, pre_start, session_setup, gc prime |
Startup shaping is explicit and provider-aware instead of being mostly inferred from where a role lives on disk. |
| Path-derived identity | Explicit agent identity, rig scope, env, bead metadata | Avoid porting code or prompts that assume cwd implies who the agent is. |
| Formula runner inside Town workflows | Formula resolution in Gas City plus backend-owned execution | Gas City resolves formulas and dispatches them, but real multi-step execution is still backend-dependent today. bd is the production path. |
If you would have added a new role in Gas Town, the Gas City move is usually:
- start in your local
city.toml - include a pack if one already solves most of the problem
- override the stamped agent if you just need local behavior changes
- edit the pack only when you are changing the shared default for everyone
- add formulas or orders around the agent if it needs workflow automation
That keeps role behavior in configuration instead of hardcoding more role semantics into the SDK, while still making the common day-one workflow feel local and incremental.
This is the main day-one habit to adopt.
Most Gas Town users should begin with the root city pack plus city.toml, not
by editing an imported shared pack. The split is:
pack.tomlimports reusable packs and defines city-specific behavioragents/<name>/defines city-owned named agentscity.tomldeclares deployment choices such as rigs, substrates, and scale.gc/stores site bindings such as local rig paths
Reach for a pack edit when the change should become the new reusable default for every consumer of that pack.
This is the most important practical translation.
If the Gas Town idea is "something should run automatically on a schedule, on an event, or when a condition is true", you probably want an order.
- Use an exec order when the work is just shell or controller-side logic.
- Use a formula order when the work should instantiate agent-driven workflow.
That is the clean replacement for many Town "plugin" instincts. Exec orders are especially important because they can run non-agent commands with no prompt, no session, and no extra role agent.
Gas Town taught people to think in convoys. That mental model still transfers well, but the implementation boundary is different.
In Gas City:
- convoys are still bead-backed grouping and lineage
gc slingcan create convoy structure as part of routing- formulas, orders, and waits compose around that bead graph
So keep the convoy mental model for tracking work, but do not assume it needs a special orchestration subsystem beyond beads plus dispatch.
In Gas Town, these feel like first-class worker types. In Gas City, they are best thought of as conventions:
- crew: persistent named agents you expect humans to reason about
- polecats: scalable or transient sessions, often with dedicated worktrees
That distinction is real and useful, but the SDK does not force it. A pack can adopt the convention, relax it, or replace it.
In Gas Town, some orchestration behavior is mediated through specific roles. In Gas City, the controller is the canonical owner of infrastructure operations like:
- reconcile desired sessions to running sessions
- session scaling
- order evaluation
- health patrol
- wisp garbage collection
If something is fundamentally SDK infrastructure, prefer putting it in the controller path instead of inventing another deacon-like role behavior.
Gas Town uses directories as part of the system contract. Gas City tries not to.
The current rule of thumb is:
- use
dirto carry the agent's scope and identity context - use
work_dirwhen the session must run somewhere else - use bead metadata for durable handoff state
Good reasons to use a separate work_dir:
- the role mutates a repo and needs an isolated worktree
- provider scratch files would collide with another role
- the role needs a durable sandbox independent from the canonical rig root
Bad reason:
- "Gas Town had a separate folder for this role"
The Gastown pack still ships familiar roles, but that is an example operating model, not a type system inside Gas City.
This matters when you change the system:
- adding a new behavior usually means editing a pack, formula, order, or prompt
- it usually does not mean adding a new hardcoded role to the SDK
That is a feature, not a missing abstraction.
It is also worth separating two kinds of changes:
- local city change: edit
city.toml, add rig overrides, add patches, or add a city-specific agent - shared product change: edit the pack because you want a better default for everyone
Most onboarding work should live in the first category.
Ask this first:
- Can this be an exec order?
If yes, prefer the order. That gives you trigger logic, history, and controller ownership without burning an agent slot.
Reach for a dog-like scalable session config only if the task truly needs a long-lived session, rich interactive context, or repeated agent judgment.
Ask which parts are:
- controller infrastructure
- bead state transitions
- formula logic
- prompt guidance
Only the first category belongs in Go SDK infrastructure. The rest usually live better in the pack.
Usually you do not.
Start with:
- canonical repo root from the rig
- isolated
work_dironly for roles that mutate repos or need provider-file isolation - explicit env and metadata, not cwd inference
Use an exec order before inventing a plugin, helper role, or hidden session.
That is the direct Gas City answer to many old Town automation tasks.
If you are using the Gastown pack, these are the most common local changes.
Import the Gastown pack in the root pack, then bind rigs in city.toml and
with gc rig add:
# pack.toml
[pack]
name = "my-city"
schema = 2
[imports.gastown]
source = "./assets/gastown"# city.toml
[[rigs]]
name = "myproject"
[rigs.imports.gastown]
source = "./assets/gastown"gc rig add /path/to/myproject --name myprojectThis is the cleanest answer to "I want more or fewer polecats for this rig."
# city.toml
[[rigs]]
name = "myproject"
[rigs.imports.gastown]
source = "./assets/gastown"
[[rigs.patches]]
agent = "gastown.polecat"
[rigs.patches.pool]
max = 10# city.toml
[[rigs]]
name = "myproject"
[rigs.imports.gastown]
source = "./assets/gastown"
[[rigs.patches]]
agent = "gastown.polecat"
provider = "codex"You can combine that with session scale overrides, env, prompt changes, or hook changes on the same override block.
City-scoped agents such as mayor, deacon, and boot are easiest to tweak
with patches:
[[patches.agent]]
name = "gastown.mayor"
provider = "codex"
idle_timeout = "2h"Use patches when the target is already a concrete city-scoped agent. Use
[[rigs.patches]] when the target is a pack agent stamped per rig.
Crew is usually city-specific, so it often belongs in the root city pack rather than in the shared Gastown pack:
agents/wolf/
├── agent.toml
└── prompt.template.md
# agents/wolf/agent.toml
scope = "rig"
nudge = "Check your hook and mail, then act accordingly."
work_dir = ".gc/worktrees/myproject/crew/wolf"
idle_timeout = "4h"That keeps the shared pack generic while still letting your city have named long-lived workers.
This is what rig overrides are for:
# city.toml
[[rigs]]
name = "myproject"
[rigs.imports.gastown]
source = "./assets/gastown"
[[rigs.patches]]
agent = "gastown.refinery"
idle_timeout = "4h"For prompt or overlay replacement, patch the imported agent from your root city pack rather than editing the shared pack in place.
If that change turns out to be broadly useful across cities, that is when it should move into the pack.
This is a closest-match map, not a claim that the two CLIs have identical architecture.
Two rules help a lot:
- if the old
gtcommand was about orchestration, sessions, routing, hooks, or runtime behavior, the closest home is usuallygc - if the old
gtcommand was really about bead CRUD or bead content, the closest home is often stillbd, notgc
gt |
Closest in Gas City | Notes |
|---|---|---|
gt install |
gc init |
Gas City uses gc init to create a city. |
gt init |
gc rig add or gc init |
Town init and install split across city creation and rig registration in Gas City. |
gt rig |
gc rig |
Near-direct mapping. |
gt start |
gc start |
Starts the city under the machine-wide supervisor. |
gt up |
gc start |
Same high-level intent. |
gt down |
gc stop |
Stop sessions for the current city. |
gt shutdown |
gc stop |
Same intent, different implementation model. |
gt daemon |
gc supervisor |
Supervisor is the canonical long-running runtime in Gas City. |
gt status |
gc status |
City-wide overview. |
gt dashboard |
gc dashboard |
Same general purpose; gc dashboard serve still exists as the explicit form. |
gt doctor |
gc doctor |
Near-direct mapping. |
gt config |
gc config plus editing city.toml |
Gas City config is file-first; gc config is mostly inspect/explain. |
gt disable |
gc suspend |
Closest operational match is per-city suspension, not a system-wide Town toggle. |
gt enable |
gc resume |
Resumes a suspended city. |
gt uninstall |
no direct equivalent | Gas City has supervisor install/uninstall, but not a Town-style global uninstall command. |
gt version |
gc version |
Direct mapping. |
gt completion |
no direct equivalent | Gas City does not currently expose a matching completion command. |
gt help |
gc help |
Direct mapping. |
gt info |
gc version, gc status, docs |
No single gc info command. |
gt stale |
no direct equivalent | Closest checks are gc version and gc doctor. |
gt town |
split across gc start, gc status, gc stop, gc supervisor |
Gas City does not keep a separate Town namespace. |
gt |
Closest in Gas City | Notes |
|---|---|---|
gt git-init |
git init plus gc rig add |
Git repo setup and city registration are separate concerns in Gas City. |
gt hooks |
config-driven hook install plus gc doctor |
Gas City does not have Town's hook-management namespace; hook install is primarily config and lifecycle driven. |
gt plugin |
gc order |
Plugin-like controller automation usually becomes an exec order or formula order. |
gt issue |
no direct equivalent | Usually replaced by bead metadata or session context, depending intent. |
gt account |
no direct equivalent | Provider account management is outside Gas City's core CLI. |
gt shell |
no direct equivalent | Gas City does not ship a Town-style shell integration namespace. |
gt theme |
no direct equivalent | Pack scripts or tmux config are the normal path. |
gt |
Closest in Gas City | Notes |
|---|---|---|
gt sling |
gc sling |
Direct mapping in spirit and name. |
gt handoff |
gc handoff |
Near-direct mapping. |
gt convoy |
gc convoy |
Near-direct mapping for convoy creation and tracking. |
gt hook |
gc hook |
Same name, narrower surface: gc hook is work-query and hook injection behavior, not the full Town hook manager. |
gt ready |
bd ready |
This stays bead-centric more than city-centric. |
gt done |
no single direct equivalent | In Gas City this is usually a bead close, metadata transition, convoy action, or formula step. |
gt unsling |
no direct equivalent | Usually replaced by bead edits plus re-routing with bd and gc sling. |
gt formula |
gc formula list/show/cook, gc sling --formula, gc order |
gc formula manages formulas (list, show, cook). gc sling --formula dispatches as a wisp. |
gt mol |
gc formula cook, bd mol ... |
gc formula cook creates molecules; bd handles bead-level operations. |
gt mq |
no direct generic gc command |
Gastown-style merge queue behavior lives in the pack and formulas, not a generic SDK namespace. |
gt gate |
gc wait |
Durable waits are the closest SDK concept. |
gt park |
gc wait |
Same underlying idea: stop and resume around a dependency or gate. |
gt resume |
gc wait ready, gc session wake, gc mail check |
Depends on whether the old action was a parked wait, sleeping session, or handoff/mail resume. |
gt synthesis |
partial: gc converge, formulas, convoys |
No one-command parity. |
gt orphans |
no direct generic command | In Gas City this is usually pack logic plus witness/refinery formulas and bead inspection. |
gt release |
mostly bd state edits |
No single gc release command. |
gt |
Closest in Gas City | Notes |
|---|---|---|
gt agents |
gc session plus gc status |
Session management is generic in Gas City; not a Town-specific agent switcher. |
gt session |
gc session |
Same broad idea, but not polecat-specific. |
gt crew |
city.toml agents plus gc session |
Crew is a pack convention, not a first-class SDK command family. |
gt polecat |
Gastown pack polecat agent plus gc status / gc session / gc sling |
No dedicated top-level SDK namespace. |
gt witness |
Gastown pack witness agent plus gc session / gc status |
No dedicated top-level SDK namespace. |
gt refinery |
Gastown pack refinery agent plus gc session / gc status |
No dedicated top-level SDK namespace. |
gt mayor |
Gastown pack mayor agent plus gc session attach mayor / gc status |
Managed as a configured agent, not a baked-in command family. |
gt deacon |
Gastown pack deacon agent plus gc session, gc status, controller behavior |
In Gas City, much of what deacon did lives in the controller/supervisor. |
gt boot |
Gastown pack boot agent |
Same pattern as other role agents. |
gt dog |
usually gc order, sometimes a scalable session config in city.toml |
Dog-like helpers are often better modeled as exec orders. |
gt role |
gc config explain, gc session list, prompt/config inspection |
Role is not a first-class SDK concept. |
gt callbacks |
no direct equivalent | Callback behavior is folded into runtime, hooks, waits, and orders. |
gt cycle |
no direct generic command | Closest equivalents are tmux bindings or pack-specific session UX. |
gt namepool |
config-only today | Gas City supports namepool files in config, but does not expose a top-level gc namepool command. |
gt worktree |
work_dir, pre_start, git worktree, pack scripts |
Worktree behavior is explicit config and script wiring, not a generic gc worktree namespace. |
gt |
Closest in Gas City | Notes |
|---|---|---|
gt mail |
gc mail |
Near-direct mapping. |
gt nudge |
gc session nudge or gc nudge |
Use gc session nudge for a specific live session, gc nudge for deferred delivery controls. |
gt peek |
gc session peek |
Near-direct mapping. |
gt broadcast |
no single direct equivalent | Usually modeled as gc mail send to a group or multiple explicit targets. |
gt notify |
no direct equivalent | Notification policy is not a top-level SDK command family. |
gt dnd |
no direct equivalent | Closest behavior usually lives in mail or local workflow policy. |
gt escalate |
no direct equivalent | Model escalations with beads, mail, orders, or pack-specific workflow. |
gt whoami |
no direct equivalent | Identity is explicit in config, session metadata, and GC_* env rather than a dedicated CLI. |
gt |
Closest in Gas City | Notes |
|---|---|---|
gt bead |
mostly bd |
Bead CRUD is still primarily the bead tool's job. |
gt cat |
mostly bd |
Same rule: bead content inspection is bead-centric. |
gt show |
mostly bd |
Use the bead tool for detailed bead state/content. |
gt close |
mostly bd close |
Still bead-centric. |
gt commit |
git commit |
Gas City does not wrap commit the way Town did. |
gt activity |
gc event emit and gc events |
Same basic event/logging space. |
gt trail |
gc events, gc session peek, gc session logs |
No one-command parity. |
gt feed |
gc events |
Closest live system feed. |
gt log |
gc events or gc supervisor logs |
Depends on whether you want event history or runtime logs. |
gt audit |
partial: gc events, gc graph, bd queries |
No single audit namespace equivalent. |
gt checkpoint |
no direct equivalent | Session durability lives in the runtime and bead/session model rather than a user-facing checkpoint CLI. |
gt patrol |
no direct equivalent | Patrol behavior is generally modeled with orders plus formulas. |
gt migrate-agents |
gc migration |
Same general migration/upgrade bucket. |
gt prime |
gc prime |
Direct mapping. |
gt account |
no direct equivalent | Provider account management is outside Gas City's core CLI. |
gt shell |
no direct equivalent | Gas City does not ship a Town-style shell integration namespace. |
gt theme |
no direct equivalent | Pack scripts or tmux config are the normal path. |
gt costs |
no direct equivalent | No matching top-level cost accounting command today. |
gt seance |
no direct equivalent | Gas City has resume and session metadata, but not a seance command. |
gt thanks |
no direct equivalent | No matching command. |
If you are unsure where a gt command went, ask this in order:
- Is it now just
gcwith nearly the same name? - Is it really a bead operation that should stay in
bd? - Is it no longer a special command because Gas City moved that behavior into config, orders, waits, formulas, or controller logic?
These Gas Town habits usually create unnecessary complexity in Gas City:
- exact
~/gt/...directory trees - cwd-derived identity
- new hardcoded role names in SDK code
- plugin systems when an order is enough
- special helper agents for work that is really a shell command
- duplicating durable state outside beads when labels or metadata are enough
The most common architectural mistake is importing Town's surface area instead of re-expressing the intent in Gas City's primitives.
If you already know Gas Town, this is the shortest path to becoming effective in Gas City:
- Read the Nine Concepts Overview (
engdocs/architecture/nine-concepts). - Read the Config System docs (
engdocs/architecture/config). - Read Orders (
engdocs/architecture/orders) and mentally remap "plugins" to "orders". - Read Formulas & Molecules (
engdocs/architecture/formulas) and remember that formulas are resolved by Gas City but executed by the configured beads backend. - Look at examples/gastown/city.toml first, then examples/gastown/packs/gastown/pack.toml. The city file is the normal starting point; the pack defines the reusable defaults behind it.
If you keep those five points straight, most of the Gas Town to Gas City ramp goes quickly.