In the previous chapter, Rigs (Project Containers), we built the construction site (the Rig) where our software will be built. But a construction site is useless without workers.
In Gas Town, we don't just let AI agents roam free over your files. We hire specific workers for specific tasks, and when they are done, they leave. These workers are called Polecats.
Imagine you are working on a new feature in your code. Suddenly, you need to fix a critical bug. If you use the same folder for both tasks:
Now imagine five AI agents trying to do this simultaneously in one folder. It would be chaos.
A Polecat is an ephemeral (temporary) worker agent.
Think of a Polecat like a freelance contractor. You hand them a copy of the blueprints, point them to a temporary shed, they do the repair, hand you the results, and then the shed is removed.
Let's see how to manage these workers using the Gas Town CLI.
To create a new worker named fixer-bot in your current rig:
gt polecat add fixer-bot
What happens?
Gas Town creates a new directory inside polecats/. This isn't just an empty folder; it contains a full checkout of your code, ready for work.
To see who is currently working:
gt polecat list
Output:
Polecats in my-app:
fixer-bot (Working on: polecat/fixer-bot-123xyz)
When the job is done (and the code is merged), you dismiss the worker:
gt polecat remove fixer-bot
Safety First: If the Polecat has written code that hasn't been saved (committed), Gas Town will refuse to delete it unless you force it.
How does Gas Town create these isolated environments so quickly without downloading the whole internet every time? It uses Git Worktrees.
Here is the lifecycle of a Polecat creation:
Every worker needs their own git branch so they don't conflict with the main codebase or other workers. We generate a unique name using the worker's name and a timestamp.
From internal/polecat/manager.go:
func (m *Manager) buildBranchName(name, issue string) string {
// We use a timestamp to ensure the branch name is unique
// Example: polecat/tinker-1h5k9a
timestamp := strconv.FormatInt(time.Now().UnixMilli(), 36)
// Return a structured branch name
return fmt.Sprintf("polecat/%s-%s", name, timestamp)
}
This is the most important part. Instead of cloning the repo (slow), we add a worktree. This allows the Polecat to share the .git history with the Rig but have its own editable files.
From internal/polecat/manager.go:
// AddWithOptions creates the physical worker environment
func (m *Manager) AddWithOptions(name string, opts AddOptions) (*Polecat, error) {
// 1. Define where the worker lives
clonePath := filepath.Join(m.rig.Path, "polecats", name, m.rig.Name)
// 2. Determine where to branch from (usually "main")
startPoint := "origin/main"
// 3. Create the worktree (Fast!)
// git worktree add -b <branch> <path> <start-point>
if err := repoGit.WorktreeAddFromRef(clonePath, branchName, startPoint); err != nil {
return nil, fmt.Errorf("creating worktree: %w", err)
}
// ... setup continues
}
Finally, we need to tell the town's database (see Beads & Dolt (The Ledger)) that this agent exists. This allows us to assign tasks to it later.
From internal/polecat/manager.go:
// Register the agent in the database (Beads)
// We set its initial state to "spawning"
err = m.createAgentBeadWithRetry(agentID, &beads.AgentFields{
RoleType: "polecat",
Rig: m.rig.Name,
AgentState: "spawning",
})
if err != nil {
return nil, err // Fail if we can't track the worker
}
When you run gt polecat remove, the manager ensures we don't lose work.
--force).func (m *Manager) Remove(name string, force bool) error {
// Check if the worker has messy files (uncommitted code)
if !force {
status, _ := polecatGit.CheckUncommittedWork()
if !status.Clean() {
return errors.New("polecat has uncommitted work")
}
}
// Safe to delete!
return os.RemoveAll(polecatPath)
}
gt polecat command handles the complex logic of branching, spawning, and cleanup.Now that we have a Rig and Workers, we need a way to tell the workers how to perform complex sequences of tasks.
Next Chapter: Molecules (Workflow Engines)
Generated by Code IQ