fix(rig): improve UX for rig creation (#7)
- Add progress feedback during slow clone operations (30+ seconds) - Fix README Quick Start to match actual workflow (--git flag, crew add) - Update install output to use 'gt mayor attach' consistently - Clarify "Next steps" wording in rig add output 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
22
README.md
22
README.md
@@ -25,17 +25,27 @@ Multi-agent orchestrator for Claude Code. Track work with convoys; sling to agen
|
||||
# Install
|
||||
go install github.com/steveyegge/gastown/cmd/gt@latest
|
||||
|
||||
# Create workspace
|
||||
gt install ~/gt
|
||||
# Create workspace (--git auto-initializes git repository)
|
||||
gt install ~/gt --git
|
||||
cd ~/gt
|
||||
|
||||
# Add a project
|
||||
gt rig add myproject https://github.com/you/repo.git
|
||||
|
||||
# Enter the Mayor's office (recommended)
|
||||
gt mayor attach
|
||||
# Create your personal workspace
|
||||
gt crew add <yourname> --rig myproject
|
||||
|
||||
# Start working
|
||||
cd myproject/crew/<yourname>
|
||||
```
|
||||
|
||||
Once inside the Mayor session, you're talking to Claude with full town context. Just tell it what you want:
|
||||
For advanced multi-agent coordination, use the Mayor session:
|
||||
|
||||
```bash
|
||||
gt mayor attach # Enter the Mayor's office
|
||||
```
|
||||
|
||||
Inside the Mayor session, you're talking to Claude with full town context:
|
||||
|
||||
> "Help me fix the authentication bug in myproject"
|
||||
|
||||
@@ -78,7 +88,7 @@ The primary Gas Town experience. Agents run in tmux sessions with the Mayor as y
|
||||
|
||||
```bash
|
||||
gt start # Start Gas Town (daemon + Mayor session)
|
||||
cd ~/gt && gt prime # Enter Mayor session
|
||||
gt mayor attach # Enter Mayor session
|
||||
|
||||
# Inside Mayor session, just ask:
|
||||
# "Create a convoy for issues 123 and 456 in myproject"
|
||||
|
||||
@@ -242,7 +242,7 @@ func runInstall(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
fmt.Printf(" %d. Add a rig: %s\n", step, style.Dim.Render("gt rig add <name> <git-url>"))
|
||||
step++
|
||||
fmt.Printf(" %d. Start the Mayor: %s\n", step, style.Dim.Render("cd "+absPath+" && gt prime"))
|
||||
fmt.Printf(" %d. Enter the Mayor's office: %s\n", step, style.Dim.Render("gt mayor attach"))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -399,8 +399,8 @@ func runRigAdd(cmd *cobra.Command, args []string) error {
|
||||
fmt.Printf(" └── polecats/\n")
|
||||
|
||||
fmt.Printf("\nNext steps:\n")
|
||||
fmt.Printf(" gt crew add <name> --rig %s # Create your workspace\n", name)
|
||||
fmt.Printf(" cd %s/crew/<name> # Work in your clone\n", filepath.Join(townRoot, name))
|
||||
fmt.Printf(" gt crew add <name> --rig %s # Create your personal workspace\n", name)
|
||||
fmt.Printf(" cd %s/crew/<name> # Start working\n", filepath.Join(townRoot, name))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -266,6 +266,7 @@ func (m *Manager) AddRig(opts AddRigOptions) (*Rig, error) {
|
||||
// Create shared bare repo as source of truth for refinery and polecats.
|
||||
// This allows refinery to see polecat branches without pushing to remote.
|
||||
// Mayor remains a separate clone (doesn't need branch visibility).
|
||||
fmt.Printf(" Cloning repository (this may take a moment)...\n")
|
||||
bareRepoPath := filepath.Join(rigPath, ".repo.git")
|
||||
if localRepo != "" {
|
||||
if err := m.git.CloneBareWithReference(opts.GitURL, bareRepoPath, localRepo); err != nil {
|
||||
@@ -280,6 +281,7 @@ func (m *Manager) AddRig(opts AddRigOptions) (*Rig, error) {
|
||||
return nil, fmt.Errorf("creating bare repo: %w", err)
|
||||
}
|
||||
}
|
||||
fmt.Printf(" ✓ Created shared bare repo\n")
|
||||
bareGit := git.NewGitWithDir(bareRepoPath, "")
|
||||
|
||||
// Detect default branch (main, master, etc.)
|
||||
@@ -293,6 +295,7 @@ func (m *Manager) AddRig(opts AddRigOptions) (*Rig, error) {
|
||||
// Create mayor as regular clone (separate from bare repo).
|
||||
// Mayor doesn't need to see polecat branches - that's refinery's job.
|
||||
// This also allows mayor to stay on the default branch without conflicting with refinery.
|
||||
fmt.Printf(" Creating mayor clone...\n")
|
||||
mayorRigPath := filepath.Join(rigPath, "mayor", "rig")
|
||||
if err := os.MkdirAll(filepath.Dir(mayorRigPath), 0755); err != nil {
|
||||
return nil, fmt.Errorf("creating mayor dir: %w", err)
|
||||
@@ -310,6 +313,7 @@ func (m *Manager) AddRig(opts AddRigOptions) (*Rig, error) {
|
||||
return nil, fmt.Errorf("cloning for mayor: %w", err)
|
||||
}
|
||||
}
|
||||
fmt.Printf(" ✓ Created mayor clone\n")
|
||||
|
||||
// Check if source repo has .beads/ with its own prefix - if so, use that prefix.
|
||||
// This ensures we use the project's existing beads database instead of creating a new one.
|
||||
@@ -347,6 +351,7 @@ func (m *Manager) AddRig(opts AddRigOptions) (*Rig, error) {
|
||||
// Create refinery as worktree from bare repo on default branch.
|
||||
// Refinery needs to see polecat branches (shared .repo.git) and merges them.
|
||||
// Being on the default branch allows direct merge workflow.
|
||||
fmt.Printf(" Creating refinery worktree...\n")
|
||||
refineryRigPath := filepath.Join(rigPath, "refinery", "rig")
|
||||
if err := os.MkdirAll(filepath.Dir(refineryRigPath), 0755); err != nil {
|
||||
return nil, fmt.Errorf("creating refinery dir: %w", err)
|
||||
@@ -354,6 +359,7 @@ func (m *Manager) AddRig(opts AddRigOptions) (*Rig, error) {
|
||||
if err := bareGit.WorktreeAddExisting(refineryRigPath, defaultBranch); err != nil {
|
||||
return nil, fmt.Errorf("creating refinery worktree: %w", err)
|
||||
}
|
||||
fmt.Printf(" ✓ Created refinery worktree\n")
|
||||
// Create refinery CLAUDE.md (overrides any from cloned repo)
|
||||
if err := m.createRoleCLAUDEmd(refineryRigPath, "refinery", opts.Name, ""); err != nil {
|
||||
return nil, fmt.Errorf("creating refinery CLAUDE.md: %w", err)
|
||||
@@ -414,9 +420,11 @@ Use crew for your own workspace. Polecats are for batch work dispatch.
|
||||
}
|
||||
|
||||
// Initialize beads at rig level
|
||||
fmt.Printf(" Initializing beads database...\n")
|
||||
if err := m.initBeads(rigPath, opts.BeadsPrefix); err != nil {
|
||||
return nil, fmt.Errorf("initializing beads: %w", err)
|
||||
}
|
||||
fmt.Printf(" ✓ Initialized beads (prefix: %s)\n", opts.BeadsPrefix)
|
||||
|
||||
// Create agent beads for this rig (witness, refinery) and
|
||||
// global agents (deacon, mayor) if this is the first rig.
|
||||
|
||||
Reference in New Issue
Block a user