- Add Alias field to RigEntry struct for short display names
- Limit displayed rigs to 3 (was unlimited, causing overflow)
- Use alias in statusline when configured (e.g., gcr instead of google_cookie_retrieval)
- Show +N overflow indicator when more rigs exist
Closes: hq-5j33zz
Add CrewRegistryConfig to RigEntry allowing crew members to be defined
in rigs.json and synced across machines. The new `gt crew sync` command
creates missing crew members from the configuration.
Configuration example:
"rigs": {
"gastown": {
"crew": {
"theme": "mad-max",
"members": ["diesel", "chrome", "nitro"]
}
}
}
Closes: gt-tu4
Add the ability to force dark or light mode colors for CLI output,
overriding the automatic terminal background detection.
Changes:
- Add CLITheme field to TownSettings for persisting preference
- Add GetThemeMode() and HasDarkBackground() to ui package for
theme detection with GT_THEME env var override
- Add ApplyThemeMode() to explicitly set lipgloss dark background
- Add 'gt theme cli' subcommand to view/set CLI theme preference
- Initialize theme in CLI startup (persistentPreRun)
- Add comprehensive tests for theme mode functionality
Usage:
- gt theme cli # show current theme
- gt theme cli dark # force dark mode
- gt theme cli light # force light mode
- gt theme cli auto # auto-detect (default)
- GT_THEME=dark gt status # per-command override
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Add support for agent presets to specify environment variables that
get exported when starting sessions. This enables agents to use
environment-based configuration.
Changes:
- Add Env field to RuntimeConfig struct in types.go
- Add Env field to AgentPresetInfo struct in agents.go
- Update RuntimeConfigFromPreset to copy Env from preset
- Update fillRuntimeDefaults to preserve Env field
- Merge agent Env vars in BuildStartupCommand functions
- Add comprehensive tests for Env preservation and copy semantics
This is a prerequisite for the OpenCode agent preset which uses
OPENCODE_PERMISSION='{"*":"allow"}' for auto-approve mode.
Co-authored-by: Avyukth <subhrajit.makur@hotmail.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Fix "Unable to attach mayor" timeout caused by claude being installed
as a shell alias rather than in PATH. Non-interactive shells spawned
by tmux cannot resolve aliases, causing the session to exit immediately.
Changes:
- Add resolveClaudePath() to find claude at ~/.claude/local/claude
- Apply path resolution in RuntimeConfigFromPreset() for claude preset
- Make hasClaudeChild() recursive (now hasClaudeDescendant()) to search
entire process subtree as defensive improvement
- Update fillRuntimeDefaults() to use DefaultRuntimeConfig() for
consistent path resolution
Fixes https://github.com/steveyegge/gastown/issues/703
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
The WaitForRuntimeReady function was looking for "> " to detect
when Claude is ready, but Claude Code uses "❯" (U+276F) as its
prompt character. This caused refineries to timeout during startup.
Fixes#763
Executed-By: mayor
Role: mayor
- Change EscalationConfig to use Routes map with action strings
- Rename severity "normal" to "medium" per design doc
- Move config from config/ to settings/escalation.json
- Add --source flag for escalation source tracking
- Add Source field to EscalationFields
- Add executeExternalActions() for email/sms/slack with warnings
- Add default escalation config creation in gt install
- Add comprehensive unit tests for config loading
- Update help text with correct severity levels and paths
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add severity-based routing for escalations with config-driven targets.
Changes:
- EscalationConfig type with severity routes and external channels
- beads/beads_escalation.go: Escalation bead operations (create/ack/close/list)
- Refactored gt escalate command with subcommands:
- list: Show open escalations
- ack: Acknowledge an escalation
- close: Resolve with reason
- stale: Find unacknowledged escalations past threshold
- show: Display escalation details
- Added TypeEscalationAcked and TypeEscalationClosed event types
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Allow `gt formula run` to be called without a formula name by configuring
a default in the rig's settings/config.json under workflow.default_formula.
Co-authored-by: Brett VanderVeen <brett.vanderveen@gfs.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Enterprise teams can now customize integration branch names to match
their conventions (e.g., username/TICKET-123/feature-name).
- Add integration_branch_template to MergeQueueConfig
- Add --branch CLI override for gt mq integration create
- Support {epic}, {prefix}, {user} template variables
- Validate branch names for git-safe characters
- Store actual branch name in epic metadata at create time
- Read stored branch name in land/status (fallback for old epics)
Also fixes unrelated build error in polecat/manager.go (polecatPath
variable was undefined).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds support for alternative AI runtime backends (Codex, OpenCode) alongside
the default Claude backend through a runtime abstraction layer.
- internal/runtime/runtime.go - Runtime-agnostic helper functions
- Extended RuntimeConfig with provider-specific settings
- internal/opencode/ for OpenCode plugin support
- Updated session managers to use runtime abstraction
- Removed unused ensureXxxSession functions
- Fixed daemon.go indentation, updated terminology to runtime
Backward compatible: Claude remains default runtime.
Co-Authored-By: Ben Kraus <ben@cinematicsoftware.com>
Co-Authored-By: Cameron Palmer <cameronmpalmer@users.noreply.github.com>
* feat: Add rig-level custom agent support
Implement rig-level custom agent configuration support to enable per-rig
agent definitions in <rig>/settings/config.json, following the same pattern as
town-level agents in settings/config.json.
Changes:
- Added RigSettings.Agents field to internal/config/types.go
- Added DefaultRigAgentRegistryPath() and LoadRigAgentRegistry() functions to internal/config/agents.go
- Updated ResolveAgentConfigWithOverride() to accept and pass rigSettings parameter
- Updated GetRuntimeCommandWithAgentOverride() to use rigSettings when available
- Updated GetRuntimeCommandWithPromptAndAgentOverride() to use rigSettings
- Updated all Build*WithOverride functions to pass rigSettings
This fixes the issue where rig-level agent settings were loaded but
ignored by lookupAgentConfig, enabling per-rig custom agents for
polecats and crew members.
* test: Add rig-level custom agent tests
Added comprehensive unit tests for rig agent registry functions:
- TestDefaultRigAgentRegistryPath: verifies path construction
- TestLoadRigAgentRegistry: verifies file loading and JSON parsing
- TestLookupAgentConfigWithRigSettings: verifies agent lookup priority (rig > town > builtin)
Added placeholder integration test for future CI/CD setup.
* initial commit
* fix: resolve compilation errors in rig-level custom agent support
- Add missing RigAgentRegistryPath function (alias for DefaultRigAgentRegistryPath)
- Restore ResolveAgentConfigWithOverride function that was incorrectly removed
- Fix ResolveAgentConfig to return single value (not triple)
- Add initRegistryLocked() call to LoadRigAgentRegistry to prevent nil panic
- Fix DefaultRigAgentRegistryPath to use rigPath directly (not parent dir)
- Fix test file syntax errors (remove EOF artifacts)
- Fix test parameter order for lookupAgentConfig calls
- Fix test expectations to match correct custom agent override behavior
* test: implement rig-level custom agent integration test
- Add stub agent script that simulates AI agent with Q&A capability
- Test ResolveAgentConfig correctly picks up rig-level agents
- Test BuildPolecatStartupCommand includes custom agent command
- Test ResolveAgentConfigWithOverride respects rig agents
- Test rig agents override town agents with same name
- Add tmux integration test that spawns session and verifies output
- Stub agent echoes 'STUB_AGENT_STARTED' and handles ping/pong Q&A
- All tests pass including real tmux session verification
* docs: add OpenCode custom agent example to reference
- Show settings/agents.json format for advanced configs
- Include OpenCode example with session resume flags
- Document OPENCODE_PERMISSION env var for autonomous mode
* fix: improve rig-level agent support with docs and test fixes
- Add rig-level agent documentation to reference.md
- Document agent resolution order (rig → town → built-in)
- Deduplicate LoadAgentRegistry/LoadRigAgentRegistry into shared helper
- Fix test isolation in TestLoadRigAgentRegistry
- Fix nil pointer dereference in test assertions (use t.Fatal not t.Error)
* feat: add Cursor Agent as compatible agent for Gas Town
Add AgentCursor preset with ProcessNames field for multi-agent detection:
- AgentCursor preset: cursor-agent -p -f (headless + force mode)
- ProcessNames field on AgentPresetInfo for agent detection
- IsAgentRunning(session, processNames) in tmux package
- GetProcessNames(agentName) helper function
Closes: ga-vwr
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: centralize agent preset list in config.go
Replace hardcoded ["claude", "gemini", "codex"] arrays with calls to
config.ListAgentPresets() to dynamically include all registered agents.
This fixes cursor agent not appearing in `gt config agent list` and
ensures new agent presets are automatically included everywhere.
Also updated doc comments to include "cursor" in example lists.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* test: add comprehensive agent client tests
Add tests for agent detection and command generation:
- TestIsAgentRunning: validates process name detection for all agents
(claude/node, gemini, codex, cursor-agent)
- TestIsAgentRunning_NonexistentSession: edge case handling
- TestIsClaudeRunning: backwards compatibility wrapper
- TestListAgentPresetsMatchesConstants: ensures ListAgentPresets()
returns all AgentPreset constants
- TestAgentCommandGeneration: validates full command line generation
for all supported agents
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat: add Auggie agent, fix Cursor interactive mode
Add Auggie CLI as supported agent:
- Command: auggie
- Args: --allow-indexing
- Supports session resume via --resume flag
Fix Cursor agent configuration:
- Remove -p flag (requires prompt, breaks interactive mode)
- Clear SessionIDEnv (cursor uses --resume with chatId directly)
- Keep -f flag for force/YOLO mode
Updated all test cases for both agents.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat(agents): add Sourcegraph AMP as agent preset
Add AgentAmp constant and builtinPresets entry for Sourcegraph AMP CLI.
Configuration:
- Command: amp
- Args: --dangerously-allow-all --no-ide
- ResumeStyle: subcommand (amp threads continue <threadId>)
- ProcessNames: amp
Closes: ga-guq
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: lint error in cleanBeadsRuntimeFiles
Change function to not return error (was always nil).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: beads v0.46.0 compatibility and test fixes
- Add custom types config (agent,role,rig,convoy,event) after bd init calls
- Fix tmux_test.go to use variadic IsAgentRunning signature
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* docs: update agent documentation for new presets
- README.md: Update agent examples to show cursor/auggie, add built-in presets list
- docs/reference.md: Add cursor, auggie, amp to built-in agents list
- CHANGELOG.md: Add entry for new agent presets under [Unreleased]
Addresses PR #247 review feedback.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* fix: create mayor/daemon.json during gt start and gt doctor --fix (#5)
- Add DaemonPatrolConfig type with heartbeat and patrol settings
- Add Load/Save/Ensure functions for daemon patrol config
- Create daemon.json in gt start (non-fatal if fails)
- Make PatrolHooksWiredCheck fixable with Fix() method
- Add comprehensive tests for both config and doctor checks
This fixes the issue where gt doctor expects mayor/daemon.json to exist
but it was never created by gt start or any other command.
* refactor: use constants.DirMayor instead of hardcoded string
Implements agent abstraction layer to support multiple AI coding agents.
Built-in presets (E2E tested):
- Claude Code (default)
- Gemini CLI
- OpenAI Codex
Key changes:
- Add AgentRegistry with built-in presets and custom agent support
- Add TownSettings with default_agent and custom agents map
- Add Agent field to RigSettings for per-rig agent selection
- Update ResolveAgentConfig for hierarchical config resolution
- Update spawn paths to use configured agent instead of hardcoded claude
Configuration hierarchy (first match wins):
1. Rig's Runtime config (backwards compat)
2. Rig's Agent -> custom agents -> built-in presets
3. Town's default_agent setting
4. Fallback to Claude
Additional agents (aider, opencode, etc.) can be added via config file:
settings/agents.json
Addresses Issue #10: Agent Agnostic Engine with Multi-provider support
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Agent directories (witness/, refinery/, mayor/) contained state.json files
with last_active timestamps that were never updated, making them stale and
misleading. This change removes:
- initAgentStates function that created vestigial state.json files
- AgentState type and related Load/Save functions from config package
- MayorStateValidCheck from doctor checks
- requesting_* lifecycle verification (dead code - flags were never set)
- FileStateJSON constant and MayorStatePath function
Kept intact:
- daemon/state.json (actively used for daemon runtime state)
- crew/<name>/state.json (operational CrewWorker metadata)
- Agent state tracking via beads (the ZFC-compliant approach)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use git --reference-if-able when a local repo is provided so rigs and crew share objects without changing remotes.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add RuntimeConfig type to RigSettings allowing per-rig LLM runtime
configuration. This moves hardcoded "claude --dangerously-skip-permissions"
invocations to configurable settings.
Changes:
- Add RuntimeConfig type with Command, Args, InitialPrompt fields
- Add BuildCommand() and BuildCommandWithPrompt() methods
- Add helper functions: LoadRuntimeConfig, BuildAgentStartupCommand,
BuildPolecatStartupCommand, BuildCrewStartupCommand
- Update startup paths in up.go and mayor.go to use new config
- Add comprehensive tests for RuntimeConfig functionality
Remaining hardcoded invocations can be updated incrementally.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add NudgeChannels field to MessagingConfig struct in types.go
- Initialize NudgeChannels map in NewMessagingConfig()
- Add validation in validateMessagingConfig(): channel names must be
non-empty and each channel must have at least one recipient
- Add tests for valid nudge channels and empty recipient validation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds federation identity fields to town.json:
- Owner: email address for entity identity (defaults to git user.email)
- PublicName: public display name (defaults to town name)
Schema version bumped to 2. Existing town.json files remain compatible
as new fields are optional.
Also adds --owner and --public-name flags to 'gt install'.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Features:
- Add CrewConfig to RigSettings (settings/config.json)
- Add --restore flag to gt up
- Crew startup from natural language preferences (e.g., 'max', 'joe and max', 'all')
- Polecat restoration from hook files (work attached)
Example rig settings:
{"crew": {"startup": "max"}}
Usage:
gt up --restore
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add DefaultCrewName constant ('max') to config package
- Add default_crew_name field to MayorConfig for town-level override
- Update gt rig add to resolve crew name: --crew flag > town config > default
- Update help text to reflect new default
Priority: --crew flag > MayorConfig.DefaultCrewName > config.DefaultCrewName ('max')
Adds support for managing multiple Claude Code accounts in Gas Town:
- accounts.json config parsing in mayor/ directory
- gt account list/add/default commands
- GT_ACCOUNT env var support with priority resolution
- --account flag on gt spawn and gt crew at commands
- CLAUDE_CONFIG_DIR injection into tmux sessions
Priority order: GT_ACCOUNT env var > --account flag > default from config
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add tmux status bar theming for Gas Town sessions:
- Per-rig color themes auto-assigned via consistent hashing
- 10 curated dark themes (ocean, forest, rust, plum, etc.)
- Special gold/dark theme for Mayor
- Dynamic status line showing current issue and mail count
- Mayor status shows polecat/rig counts
New commands:
- gt theme --list: show available themes
- gt theme apply: apply to running sessions
- gt issue set/clear: agents update their current issue
- gt status-line: internal command for tmux refresh
Status bar format:
- Left: [rig/worker] role
- Right: <issue> | <mail> | HH:MM
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add MergeQueueConfig struct and RigConfig type with:
- All merge queue settings (enabled, target_branch, on_conflict, etc.)
- Default values via DefaultMergeQueueConfig()
- Validation for on_conflict strategy and poll_interval duration
- Load/Save/Validate functions following existing config patterns
- Comprehensive tests for round-trip, custom config, and validation
Implements gt-h5n.8.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- gt crew at: auto-detect crew from cwd, run gt prime after launch
- Polecats now use git worktrees from refinery (faster than clones)
- Updated architecture.md for two-tier beads mail model
- Town beads (gm-*) for Mayor mail/coordination
- Rig .beads/ symlinks to refinery/rig/.beads
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Types:
- TownConfig: main town configuration (config/town.json)
- RigsConfig: rigs registry with BeadsConfig per rig
- AgentState: agent state with role, session, extras
Features:
- Load/Save functions for all types
- Version compatibility checks
- Required field validation
- Creates parent directories on save
Closes gt-f9x.1
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>