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",
|
||||
GroupID: GroupConfig,
|
||||
Short: "Manage Claude Code accounts",
|
||||
RunE: requireSubcommand,
|
||||
Long: `Manage multiple Claude Code accounts for Gas Town.
|
||||
|
||||
This enables switching between accounts (e.g., personal vs work) with
|
||||
|
||||
@@ -37,6 +37,7 @@ var convoyCmd = &cobra.Command{
|
||||
Use: "convoy",
|
||||
GroupID: GroupWork,
|
||||
Short: "Track batches of work across rigs",
|
||||
RunE: requireSubcommand,
|
||||
Long: `Manage convoys - the primary unit for tracking batched work.
|
||||
|
||||
A convoy is a persistent tracking unit that monitors related issues across
|
||||
|
||||
@@ -24,6 +24,7 @@ var crewCmd = &cobra.Command{
|
||||
Use: "crew",
|
||||
GroupID: GroupWorkspace,
|
||||
Short: "Manage crew workspaces (user-managed persistent workspaces)",
|
||||
RunE: requireSubcommand,
|
||||
Long: `Crew workers are user-managed persistent workspaces within a rig.
|
||||
|
||||
Unlike polecats which are witness-managed and transient, crew workers are:
|
||||
|
||||
@@ -17,6 +17,7 @@ var daemonCmd = &cobra.Command{
|
||||
Use: "daemon",
|
||||
GroupID: GroupServices,
|
||||
Short: "Manage the Gas Town daemon",
|
||||
RunE: requireSubcommand,
|
||||
Long: `Manage the Gas Town background daemon.
|
||||
|
||||
The daemon is a simple Go process that:
|
||||
|
||||
@@ -26,6 +26,7 @@ var deaconCmd = &cobra.Command{
|
||||
Aliases: []string{"dea"},
|
||||
GroupID: GroupAgents,
|
||||
Short: "Manage the Deacon session",
|
||||
RunE: requireSubcommand,
|
||||
Long: `Manage the Deacon tmux session.
|
||||
|
||||
The Deacon is the hierarchical health-check orchestrator for Gas Town.
|
||||
|
||||
@@ -46,6 +46,7 @@ var mailCmd = &cobra.Command{
|
||||
Use: "mail",
|
||||
GroupID: GroupComm,
|
||||
Short: "Agent messaging system",
|
||||
RunE: requireSubcommand,
|
||||
Long: `Send and receive messages between agents.
|
||||
|
||||
The mail system allows Mayor, polecats, and the Refinery to communicate.
|
||||
|
||||
@@ -21,6 +21,7 @@ var mayorCmd = &cobra.Command{
|
||||
Aliases: []string{"may"},
|
||||
GroupID: GroupAgents,
|
||||
Short: "Manage the Mayor session",
|
||||
RunE: requireSubcommand,
|
||||
Long: `Manage the Mayor tmux session.
|
||||
|
||||
The Mayor is the global coordinator for Gas Town, running as a persistent
|
||||
|
||||
@@ -14,6 +14,7 @@ var moleculeCmd = &cobra.Command{
|
||||
Aliases: []string{"molecule"},
|
||||
GroupID: GroupWork,
|
||||
Short: "Agent molecule workflow commands",
|
||||
RunE: requireSubcommand,
|
||||
Long: `Agent-specific molecule workflow operations.
|
||||
|
||||
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{
|
||||
Use: "step",
|
||||
Short: "Molecule step operations",
|
||||
RunE: requireSubcommand,
|
||||
Long: `Commands for working with molecule steps.
|
||||
|
||||
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",
|
||||
GroupID: GroupWork,
|
||||
Short: "Merge queue operations",
|
||||
RunE: requireSubcommand,
|
||||
Long: `Manage the merge queue for a rig.
|
||||
|
||||
The merge queue tracks work branches from polecats waiting to be merged.
|
||||
@@ -168,6 +169,7 @@ Example:
|
||||
var mqIntegrationCmd = &cobra.Command{
|
||||
Use: "integration",
|
||||
Short: "Manage integration branches for epics",
|
||||
RunE: requireSubcommand,
|
||||
Long: `Manage integration branches for batch work on epics.
|
||||
|
||||
Integration branches allow multiple MRs for an epic to target a shared
|
||||
|
||||
@@ -33,6 +33,7 @@ var polecatCmd = &cobra.Command{
|
||||
Aliases: []string{"cat", "polecats"},
|
||||
GroupID: GroupAgents,
|
||||
Short: "Manage polecats in rigs",
|
||||
RunE: requireSubcommand,
|
||||
Long: `Manage polecat lifecycle in rigs.
|
||||
|
||||
Polecats are worker agents that operate in their own git worktrees.
|
||||
|
||||
@@ -25,6 +25,7 @@ var refineryCmd = &cobra.Command{
|
||||
Aliases: []string{"ref"},
|
||||
GroupID: GroupAgents,
|
||||
Short: "Manage the merge queue processor",
|
||||
RunE: requireSubcommand,
|
||||
Long: `Manage the Refinery merge queue processor for a rig.
|
||||
|
||||
The Refinery processes merge requests from polecats, merging their work
|
||||
|
||||
@@ -26,6 +26,7 @@ var rigCmd = &cobra.Command{
|
||||
Use: "rig",
|
||||
GroupID: GroupWorkspace,
|
||||
Short: "Manage rigs in the workspace",
|
||||
RunE: requireSubcommand,
|
||||
Long: `Manage rigs (project containers) in the Gas Town workspace.
|
||||
|
||||
A rig is a container for managing a project and its agents:
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
@@ -85,3 +86,14 @@ func buildCommandPath(cmd *cobra.Command) string {
|
||||
}
|
||||
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"},
|
||||
GroupID: GroupAgents,
|
||||
Short: "Manage polecat sessions",
|
||||
RunE: requireSubcommand,
|
||||
Long: `Manage tmux sessions for polecats.
|
||||
|
||||
Sessions are tmux sessions running Claude for each polecat.
|
||||
|
||||
@@ -40,6 +40,7 @@ var swarmCmd = &cobra.Command{
|
||||
GroupID: GroupWork,
|
||||
Short: "[DEPRECATED] Use 'gt convoy' instead",
|
||||
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.
|
||||
|
||||
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",
|
||||
GroupID: GroupAgents,
|
||||
Short: "Manage the polecat monitoring agent",
|
||||
RunE: requireSubcommand,
|
||||
Long: `Manage the Witness monitoring agent for a rig.
|
||||
|
||||
The Witness monitors polecats for stuck/idle state, nudges polecats
|
||||
|
||||
Reference in New Issue
Block a user