Fix: Unknown subcommands now error instead of silently showing help
Parent commands (mol, mail, crew, polecat, etc.) previously showed help and exited 0 for unknown subcommands like "gt mol foobar". This masked errors in scripts and confused users. Added requireSubcommand() helper to root.go and applied it to all parent commands. Now unknown subcommands properly error with exit code 1. Example before: gt mol unhook → shows help, exits 0 Example after: gt mol unhook → "Error: unknown command "unhook"", exits 1 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
committed by
Steve Yegge
parent
3d09c679e2
commit
df46e75a51
@@ -24,6 +24,7 @@ var accountCmd = &cobra.Command{
|
|||||||
Use: "account",
|
Use: "account",
|
||||||
GroupID: GroupConfig,
|
GroupID: GroupConfig,
|
||||||
Short: "Manage Claude Code accounts",
|
Short: "Manage Claude Code accounts",
|
||||||
|
RunE: requireSubcommand,
|
||||||
Long: `Manage multiple Claude Code accounts for Gas Town.
|
Long: `Manage multiple Claude Code accounts for Gas Town.
|
||||||
|
|
||||||
This enables switching between accounts (e.g., personal vs work) with
|
This enables switching between accounts (e.g., personal vs work) with
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ var convoyCmd = &cobra.Command{
|
|||||||
Use: "convoy",
|
Use: "convoy",
|
||||||
GroupID: GroupWork,
|
GroupID: GroupWork,
|
||||||
Short: "Track batches of work across rigs",
|
Short: "Track batches of work across rigs",
|
||||||
|
RunE: requireSubcommand,
|
||||||
Long: `Manage convoys - the primary unit for tracking batched work.
|
Long: `Manage convoys - the primary unit for tracking batched work.
|
||||||
|
|
||||||
A convoy is a persistent tracking unit that monitors related issues across
|
A convoy is a persistent tracking unit that monitors related issues across
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ var crewCmd = &cobra.Command{
|
|||||||
Use: "crew",
|
Use: "crew",
|
||||||
GroupID: GroupWorkspace,
|
GroupID: GroupWorkspace,
|
||||||
Short: "Manage crew workspaces (user-managed persistent workspaces)",
|
Short: "Manage crew workspaces (user-managed persistent workspaces)",
|
||||||
|
RunE: requireSubcommand,
|
||||||
Long: `Crew workers are user-managed persistent workspaces within a rig.
|
Long: `Crew workers are user-managed persistent workspaces within a rig.
|
||||||
|
|
||||||
Unlike polecats which are witness-managed and transient, crew workers are:
|
Unlike polecats which are witness-managed and transient, crew workers are:
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ var daemonCmd = &cobra.Command{
|
|||||||
Use: "daemon",
|
Use: "daemon",
|
||||||
GroupID: GroupServices,
|
GroupID: GroupServices,
|
||||||
Short: "Manage the Gas Town daemon",
|
Short: "Manage the Gas Town daemon",
|
||||||
|
RunE: requireSubcommand,
|
||||||
Long: `Manage the Gas Town background daemon.
|
Long: `Manage the Gas Town background daemon.
|
||||||
|
|
||||||
The daemon is a simple Go process that:
|
The daemon is a simple Go process that:
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ var deaconCmd = &cobra.Command{
|
|||||||
Aliases: []string{"dea"},
|
Aliases: []string{"dea"},
|
||||||
GroupID: GroupAgents,
|
GroupID: GroupAgents,
|
||||||
Short: "Manage the Deacon session",
|
Short: "Manage the Deacon session",
|
||||||
|
RunE: requireSubcommand,
|
||||||
Long: `Manage the Deacon tmux session.
|
Long: `Manage the Deacon tmux session.
|
||||||
|
|
||||||
The Deacon is the hierarchical health-check orchestrator for Gas Town.
|
The Deacon is the hierarchical health-check orchestrator for Gas Town.
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ var mailCmd = &cobra.Command{
|
|||||||
Use: "mail",
|
Use: "mail",
|
||||||
GroupID: GroupComm,
|
GroupID: GroupComm,
|
||||||
Short: "Agent messaging system",
|
Short: "Agent messaging system",
|
||||||
|
RunE: requireSubcommand,
|
||||||
Long: `Send and receive messages between agents.
|
Long: `Send and receive messages between agents.
|
||||||
|
|
||||||
The mail system allows Mayor, polecats, and the Refinery to communicate.
|
The mail system allows Mayor, polecats, and the Refinery to communicate.
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ var mayorCmd = &cobra.Command{
|
|||||||
Aliases: []string{"may"},
|
Aliases: []string{"may"},
|
||||||
GroupID: GroupAgents,
|
GroupID: GroupAgents,
|
||||||
Short: "Manage the Mayor session",
|
Short: "Manage the Mayor session",
|
||||||
|
RunE: requireSubcommand,
|
||||||
Long: `Manage the Mayor tmux session.
|
Long: `Manage the Mayor tmux session.
|
||||||
|
|
||||||
The Mayor is the global coordinator for Gas Town, running as a persistent
|
The Mayor is the global coordinator for Gas Town, running as a persistent
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ var moleculeCmd = &cobra.Command{
|
|||||||
Aliases: []string{"molecule"},
|
Aliases: []string{"molecule"},
|
||||||
GroupID: GroupWork,
|
GroupID: GroupWork,
|
||||||
Short: "Agent molecule workflow commands",
|
Short: "Agent molecule workflow commands",
|
||||||
|
RunE: requireSubcommand,
|
||||||
Long: `Agent-specific molecule workflow operations.
|
Long: `Agent-specific molecule workflow operations.
|
||||||
|
|
||||||
These commands operate on the current agent's hook and attached molecules.
|
These commands operate on the current agent's hook and attached molecules.
|
||||||
@@ -204,6 +205,7 @@ a permanent (but compact) record.`,
|
|||||||
var moleculeStepCmd = &cobra.Command{
|
var moleculeStepCmd = &cobra.Command{
|
||||||
Use: "step",
|
Use: "step",
|
||||||
Short: "Molecule step operations",
|
Short: "Molecule step operations",
|
||||||
|
RunE: requireSubcommand,
|
||||||
Long: `Commands for working with molecule steps.
|
Long: `Commands for working with molecule steps.
|
||||||
|
|
||||||
A molecule is a DAG of steps. Each step is a beads issue with the molecule root
|
A molecule is a DAG of steps. Each step is a beads issue with the molecule root
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ var mqCmd = &cobra.Command{
|
|||||||
Use: "mq",
|
Use: "mq",
|
||||||
GroupID: GroupWork,
|
GroupID: GroupWork,
|
||||||
Short: "Merge queue operations",
|
Short: "Merge queue operations",
|
||||||
|
RunE: requireSubcommand,
|
||||||
Long: `Manage the merge queue for a rig.
|
Long: `Manage the merge queue for a rig.
|
||||||
|
|
||||||
The merge queue tracks work branches from polecats waiting to be merged.
|
The merge queue tracks work branches from polecats waiting to be merged.
|
||||||
@@ -168,6 +169,7 @@ Example:
|
|||||||
var mqIntegrationCmd = &cobra.Command{
|
var mqIntegrationCmd = &cobra.Command{
|
||||||
Use: "integration",
|
Use: "integration",
|
||||||
Short: "Manage integration branches for epics",
|
Short: "Manage integration branches for epics",
|
||||||
|
RunE: requireSubcommand,
|
||||||
Long: `Manage integration branches for batch work on epics.
|
Long: `Manage integration branches for batch work on epics.
|
||||||
|
|
||||||
Integration branches allow multiple MRs for an epic to target a shared
|
Integration branches allow multiple MRs for an epic to target a shared
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ var polecatCmd = &cobra.Command{
|
|||||||
Aliases: []string{"cat", "polecats"},
|
Aliases: []string{"cat", "polecats"},
|
||||||
GroupID: GroupAgents,
|
GroupID: GroupAgents,
|
||||||
Short: "Manage polecats in rigs",
|
Short: "Manage polecats in rigs",
|
||||||
|
RunE: requireSubcommand,
|
||||||
Long: `Manage polecat lifecycle in rigs.
|
Long: `Manage polecat lifecycle in rigs.
|
||||||
|
|
||||||
Polecats are worker agents that operate in their own git worktrees.
|
Polecats are worker agents that operate in their own git worktrees.
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ var refineryCmd = &cobra.Command{
|
|||||||
Aliases: []string{"ref"},
|
Aliases: []string{"ref"},
|
||||||
GroupID: GroupAgents,
|
GroupID: GroupAgents,
|
||||||
Short: "Manage the merge queue processor",
|
Short: "Manage the merge queue processor",
|
||||||
|
RunE: requireSubcommand,
|
||||||
Long: `Manage the Refinery merge queue processor for a rig.
|
Long: `Manage the Refinery merge queue processor for a rig.
|
||||||
|
|
||||||
The Refinery processes merge requests from polecats, merging their work
|
The Refinery processes merge requests from polecats, merging their work
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ var rigCmd = &cobra.Command{
|
|||||||
Use: "rig",
|
Use: "rig",
|
||||||
GroupID: GroupWorkspace,
|
GroupID: GroupWorkspace,
|
||||||
Short: "Manage rigs in the workspace",
|
Short: "Manage rigs in the workspace",
|
||||||
|
RunE: requireSubcommand,
|
||||||
Long: `Manage rigs (project containers) in the Gas Town workspace.
|
Long: `Manage rigs (project containers) in the Gas Town workspace.
|
||||||
|
|
||||||
A rig is a container for managing a project and its agents:
|
A rig is a container for managing a project and its agents:
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
@@ -85,3 +86,14 @@ func buildCommandPath(cmd *cobra.Command) string {
|
|||||||
}
|
}
|
||||||
return strings.Join(parts, " ")
|
return strings.Join(parts, " ")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// requireSubcommand returns a RunE function for parent commands that require
|
||||||
|
// a subcommand. Without this, Cobra silently shows help and exits 0 for
|
||||||
|
// unknown subcommands like "gt mol foobar", masking errors.
|
||||||
|
func requireSubcommand(cmd *cobra.Command, args []string) error {
|
||||||
|
if len(args) == 0 {
|
||||||
|
return fmt.Errorf("requires a subcommand\n\nRun '%s --help' for usage", buildCommandPath(cmd))
|
||||||
|
}
|
||||||
|
return fmt.Errorf("unknown command %q for %q\n\nRun '%s --help' for available commands",
|
||||||
|
args[0], buildCommandPath(cmd), buildCommandPath(cmd))
|
||||||
|
}
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ var sessionCmd = &cobra.Command{
|
|||||||
Aliases: []string{"sess"},
|
Aliases: []string{"sess"},
|
||||||
GroupID: GroupAgents,
|
GroupID: GroupAgents,
|
||||||
Short: "Manage polecat sessions",
|
Short: "Manage polecat sessions",
|
||||||
|
RunE: requireSubcommand,
|
||||||
Long: `Manage tmux sessions for polecats.
|
Long: `Manage tmux sessions for polecats.
|
||||||
|
|
||||||
Sessions are tmux sessions running Claude for each polecat.
|
Sessions are tmux sessions running Claude for each polecat.
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ var swarmCmd = &cobra.Command{
|
|||||||
GroupID: GroupWork,
|
GroupID: GroupWork,
|
||||||
Short: "[DEPRECATED] Use 'gt convoy' instead",
|
Short: "[DEPRECATED] Use 'gt convoy' instead",
|
||||||
Deprecated: "Use 'gt convoy' for work tracking. A 'swarm' is now just the ephemeral workers on a convoy.",
|
Deprecated: "Use 'gt convoy' for work tracking. A 'swarm' is now just the ephemeral workers on a convoy.",
|
||||||
|
RunE: requireSubcommand,
|
||||||
Long: `DEPRECATED: Use 'gt convoy' instead.
|
Long: `DEPRECATED: Use 'gt convoy' instead.
|
||||||
|
|
||||||
The term "swarm" now refers to the ephemeral set of workers on a convoy's issues,
|
The term "swarm" now refers to the ephemeral set of workers on a convoy's issues,
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ var witnessCmd = &cobra.Command{
|
|||||||
Use: "witness",
|
Use: "witness",
|
||||||
GroupID: GroupAgents,
|
GroupID: GroupAgents,
|
||||||
Short: "Manage the polecat monitoring agent",
|
Short: "Manage the polecat monitoring agent",
|
||||||
|
RunE: requireSubcommand,
|
||||||
Long: `Manage the Witness monitoring agent for a rig.
|
Long: `Manage the Witness monitoring agent for a rig.
|
||||||
|
|
||||||
The Witness monitors polecats for stuck/idle state, nudges polecats
|
The Witness monitors polecats for stuck/idle state, nudges polecats
|
||||||
|
|||||||
Reference in New Issue
Block a user