JuliusBrussee/caveman · error
unknown usage subcommand
Error message
unknown usage subcommand: %s
What it means
Thrown by runUsage's default branch when the first positional argument is not one of import|link|refresh|unlink. The usage command has exactly those four subcommands; anything else — including empty args, which are caught earlier with a usage line — produces this error.
Solutions
- Use one of: `caveman-proxy usage import|link|refresh|unlink <provider>`.
- For spend/report views use the `stats` command instead of `usage`.
- Run `caveman-proxy --help` (or bare `caveman-proxy usage`) to see the accepted subcommands.
Example fix
// before caveman-proxy usage status // after caveman-proxy stats
Defensive patterns
Strategy: validation
Validate before calling
// shell case "$SUB" in import|link|refresh|unlink) ;; *) echo "usage subcommands: import|link|refresh|unlink" >&2; exit 2;; esac caveman-proxy usage "$SUB" "$@"
Prevention
- Memorize the four subcommands: import, link, refresh, unlink.
- Spend/report views live under the stats command, not usage.
- Use tab completion or --help rather than guessing names.
When it happens
Trigger: `caveman-proxy usage show`, `usage importx` (typo), `usage status`, or passing flags where a subcommand is expected.
Common situations: Guessing subcommand names from other CLI tools (e.g. `usage report`, `usage stats` — those belong to other top-level commands); typos; old scripts written before a subcommand was renamed.
Understand the failure class
Background: "Unknown argument", "Invalid value", and "must be one of": invalid CLI argument errors explained — this error's family across 35 libraries.
Related errors
- unknown trial subcommand
- unknown learn subcommand
- usage: caveman-agent doctor [--json]
- usage: caveman-proxy trial promote
- usage: caveman-proxy usage import|link|refresh|unlink
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/c5c6c8a9e9f81688.
Report an issue: GitHub.
Appendix: source
Thrown at proxy/cmd/caveman-proxy/main.go:655
fatalJSON(logger, fmt.Errorf("unknown usage link source: %s", provider))
}
case "unlink":
switch provider {
case "claude", "anthropic":
if err := spend.DeleteQuotaProvider("anthropic"); err != nil {
fatalJSON(logger, err)
}
printJSON(map[string]any{"unlinked": "claude"})
case "codex", "openai":
if err := spend.DeleteQuotaProvider("openai"); err != nil {
fatalJSON(logger, err)
}
printJSON(map[string]any{"unlinked": "codex"})
default:
fatalJSON(logger, fmt.Errorf("usage unlink needs claude|codex"))
}
default:
fatalJSON(logger, fmt.Errorf("unknown usage subcommand: %s", sub))
}
}
func runLearn(logger *slog.Logger, args []string) {
sub := "scan"
if len(args) > 0 {
sub = args[0]
args = args[1:]
}
home := mustHome(logger)
spend := mustStore(logger, home)
defer spend.Close()
cwd, _ := os.Getwd()
// Empty default defers to the store's normalizeSources default set, so new
// session sources (gemini/opencode/aider) are scanned without this flag
// needing to chase the adapter list.
sources := strings.Split(argFlag(args, "--sources", ""), ",")
since := argFlag(args, "--since", "30d")View on GitHub (pinned to 3ee70a1026)