package cmd import ( "github.com/spf13/cobra" ) // Crew command flags var ( crewRig string crewBranch bool crewJSON bool crewForce bool crewNoTmux bool crewDetached bool crewMessage string crewAccount string ) var crewCmd = &cobra.Command{ Use: "crew", GroupID: GroupWorkspace, Short: "Manage crew workspaces (user-managed persistent workspaces)", Long: `Crew workers are user-managed persistent workspaces within a rig. Unlike polecats which are witness-managed and transient, crew workers are: - Persistent: Not auto-garbage-collected - User-managed: Overseer controls lifecycle - Long-lived identities: recognizable names like dave, emma, fred - Gas Town integrated: Mail, handoff mechanics work - Tmux optional: Can work in terminal directly Commands: gt crew add Create a new crew workspace gt crew list List crew workspaces with status gt crew at Attach to crew workspace session gt crew remove Remove a crew workspace gt crew refresh Context cycling with mail-to-self handoff gt crew restart Kill and restart session fresh (alias: rs) gt crew status [] Show detailed workspace status`, } var crewAddCmd = &cobra.Command{ Use: "add ", Short: "Create a new crew workspace", Long: `Create a new crew workspace with a clone of the rig repository. The workspace is created at /crew// with: - A full git clone of the project repository - Mail directory for message delivery - CLAUDE.md with crew worker prompting - Optional feature branch (crew/) Examples: gt crew add dave # Create in current rig gt crew add emma --rig gastown # Create in specific rig gt crew add fred --branch # Create with feature branch`, Args: cobra.ExactArgs(1), RunE: runCrewAdd, } var crewListCmd = &cobra.Command{ Use: "list", Short: "List crew workspaces with status", Long: `List all crew workspaces in a rig with their status. Shows git branch, session state, and git status for each workspace. Examples: gt crew list # List in current rig gt crew list --rig gastown # List in specific rig gt crew list --json # JSON output`, RunE: runCrewList, } var crewAtCmd = &cobra.Command{ Use: "at [name]", Aliases: []string{"attach"}, Short: "Attach to crew workspace session", Long: `Start or attach to a tmux session for a crew workspace. Creates a new tmux session if none exists, or attaches to existing. Use --no-tmux to just print the directory path instead. When run from inside tmux, the session is started but you stay in your current pane. Use C-b s to switch to the new session. When run from outside tmux, you are attached to the session (unless --detached is specified). Role Discovery: If no name is provided, attempts to detect the crew workspace from the current directory. If you're in /crew//, it will attach to that workspace automatically. Examples: gt crew at dave # Attach to dave's session gt crew at # Auto-detect from cwd gt crew at dave --detached # Start session without attaching gt crew at dave --no-tmux # Just print path`, Args: cobra.MaximumNArgs(1), RunE: runCrewAt, } var crewRemoveCmd = &cobra.Command{ Use: "remove ", Short: "Remove a crew workspace", Long: `Remove a crew workspace from the rig. Checks for uncommitted changes and running sessions before removing. Use --force to skip checks and remove anyway. Examples: gt crew remove dave # Remove with safety checks gt crew remove dave --force # Force remove`, Args: cobra.ExactArgs(1), RunE: runCrewRemove, } var crewRefreshCmd = &cobra.Command{ Use: "refresh ", Short: "Context cycling with mail-to-self handoff", Long: `Cycle a crew workspace session with handoff. Sends a handoff mail to the workspace's own inbox, then restarts the session. The new session reads the handoff mail and resumes work. Examples: gt crew refresh dave # Refresh with auto-generated handoff gt crew refresh dave -m "Working on gt-123" # Add custom message`, Args: cobra.ExactArgs(1), RunE: runCrewRefresh, } var crewStatusCmd = &cobra.Command{ Use: "status []", Short: "Show detailed workspace status", Long: `Show detailed status for crew workspace(s). Displays session state, git status, branch info, and mail inbox status. If no name given, shows status for all crew workers. Examples: gt crew status # Status of all crew workers gt crew status dave # Status of specific worker gt crew status --json # JSON output`, RunE: runCrewStatus, } var crewRestartCmd = &cobra.Command{ Use: "restart ", Aliases: []string{"rs"}, Short: "Kill and restart crew workspace session", Long: `Kill the tmux session and restart fresh with Claude. Useful when a crew member gets confused or needs a clean slate. Unlike 'refresh', this does NOT send handoff mail - it's a clean start. The command will: 1. Kill existing tmux session if running 2. Start fresh session with Claude 3. Run gt prime to reinitialize context Examples: gt crew restart dave # Restart dave's session gt crew rs emma # Same, using alias`, Args: cobra.ExactArgs(1), RunE: runCrewRestart, } var crewRenameCmd = &cobra.Command{ Use: "rename ", Short: "Rename a crew workspace", Long: `Rename a crew workspace. Kills any running session, renames the directory, and updates state. The new session will use the new name (gt--crew-). Examples: gt crew rename dave david # Rename dave to david gt crew rename madmax max # Rename madmax to max`, Args: cobra.ExactArgs(2), RunE: runCrewRename, } var crewPristineCmd = &cobra.Command{ Use: "pristine []", Short: "Sync crew workspaces with remote", Long: `Ensure crew workspace(s) are up-to-date. Runs git pull and bd sync for the specified crew, or all crew workers. Reports any uncommitted changes that may need attention. Examples: gt crew pristine # Pristine all crew workers gt crew pristine dave # Pristine specific worker gt crew pristine --json # JSON output`, RunE: runCrewPristine, } var crewNextCmd = &cobra.Command{ Use: "next", Short: "Switch to next crew session in same rig", Long: `Switch to the next crew session in the same rig. Cycles through crew sessions alphabetically. When you reach the last crew, wraps around to the first. This command is bound to C-b n in crew sessions for quick switching. Examples: gt crew next # Switch to next crew in same rig`, RunE: runCrewNext, } var crewPrevCmd = &cobra.Command{ Use: "prev", Short: "Switch to previous crew session in same rig", Long: `Switch to the previous crew session in the same rig. Cycles through crew sessions in reverse alphabetical order. When you reach the first crew, wraps around to the last. This command is bound to C-b p in crew sessions for quick switching. Examples: gt crew prev # Switch to previous crew in same rig`, RunE: runCrewPrev, } func init() { // Add flags crewAddCmd.Flags().StringVar(&crewRig, "rig", "", "Rig to create crew workspace in") crewAddCmd.Flags().BoolVar(&crewBranch, "branch", false, "Create a feature branch (crew/)") crewListCmd.Flags().StringVar(&crewRig, "rig", "", "Filter by rig name") crewListCmd.Flags().BoolVar(&crewJSON, "json", false, "Output as JSON") crewAtCmd.Flags().StringVar(&crewRig, "rig", "", "Rig to use") crewAtCmd.Flags().BoolVar(&crewNoTmux, "no-tmux", false, "Just print directory path") crewAtCmd.Flags().BoolVarP(&crewDetached, "detached", "d", false, "Start session without attaching") crewAtCmd.Flags().StringVar(&crewAccount, "account", "", "Claude Code account handle to use (overrides default)") crewRemoveCmd.Flags().StringVar(&crewRig, "rig", "", "Rig to use") crewRemoveCmd.Flags().BoolVar(&crewForce, "force", false, "Force remove (skip safety checks)") crewRefreshCmd.Flags().StringVar(&crewRig, "rig", "", "Rig to use") crewRefreshCmd.Flags().StringVarP(&crewMessage, "message", "m", "", "Custom handoff message") crewStatusCmd.Flags().StringVar(&crewRig, "rig", "", "Filter by rig name") crewStatusCmd.Flags().BoolVar(&crewJSON, "json", false, "Output as JSON") crewRenameCmd.Flags().StringVar(&crewRig, "rig", "", "Rig to use") crewPristineCmd.Flags().StringVar(&crewRig, "rig", "", "Filter by rig name") crewPristineCmd.Flags().BoolVar(&crewJSON, "json", false, "Output as JSON") crewRestartCmd.Flags().StringVar(&crewRig, "rig", "", "Rig to use") // Add subcommands crewCmd.AddCommand(crewAddCmd) crewCmd.AddCommand(crewListCmd) crewCmd.AddCommand(crewAtCmd) crewCmd.AddCommand(crewRemoveCmd) crewCmd.AddCommand(crewRefreshCmd) crewCmd.AddCommand(crewStatusCmd) crewCmd.AddCommand(crewRenameCmd) crewCmd.AddCommand(crewPristineCmd) crewCmd.AddCommand(crewRestartCmd) crewCmd.AddCommand(crewNextCmd) crewCmd.AddCommand(crewPrevCmd) rootCmd.AddCommand(crewCmd) }