Files
hyperguild/cmd/hyperguild/main.go
Mathias Bergqvist ab4cfaaeb7 fix(hyperguild): remove redundant subcommand prefixes from error messages
dispatch() already prefixes errors with 'hyperguild <subcmd>: ', so
handlers re-prefixing with their own name produced stuttered output
like 'hyperguild brain: brain query: topic required'. Strip the
redundant prefixes from the seven affected errors.New / fmt.Errorf
calls in brain.go and mode.go.

Also fix the LITELLM_BASE_URL usage text — it's optional (empty
falls through to airplane tier), not required, matching the
README.
2026-05-03 22:06:33 +02:00

72 lines
2.3 KiB
Go

// Package main implements the hyperguild CLI: tier probe, brain HTTP REST
// access, and .mcp.json mode bootstrap. See docs/superpowers/specs/.
package main
import (
"context"
"fmt"
"io"
"os"
)
// subcommand is the contract every hyperguild subcommand satisfies.
// Functions take an explicit context, args (without the subcommand name
// itself), and explicit IO so tests can exercise full flows without
// touching os.Stdin / os.Stdout / os.Exit.
type subcommand func(ctx context.Context, args []string, stdin io.Reader, stdout, stderr io.Writer) error
func subcommands() map[string]subcommand {
return map[string]subcommand{
"tier": runTier,
"brain": runBrain,
"mode": runMode,
}
}
const usage = `Usage: hyperguild <subcommand> [options]
Subcommands:
tier Probe Anthropic + LiteLLM, print current operating tier.
brain query <q> BM25 search the brain (HTTP REST).
brain write <t> <s>
Write stdin as a knowledge entry of type <t>, slug <s>.
mode <name> Bootstrap .mcp.json for a chosen mode:
cloud | client-local | sovereign
Environment:
BRAIN_URL Brain HTTP REST + MCP base URL.
Default: http://koala:30330
ANTHROPIC_PROBE_URL Tier probe URL for the Anthropic API.
Default: https://api.anthropic.com
LITELLM_BASE_URL Tier probe URL for the LiteLLM gateway.
Optional; if empty, falls through to airplane tier.
`
// dispatch routes args to a subcommand and returns the process exit code.
// Split from main() so tests can drive it without process exit.
func dispatch(ctx context.Context, args []string, stdin io.Reader, stdout, stderr io.Writer) int {
if len(args) == 0 {
fmt.Fprint(stderr, usage) //nolint:errcheck
return 2
}
switch args[0] {
case "-h", "--help", "help":
fmt.Fprint(stdout, usage) //nolint:errcheck
return 0
}
cmd, ok := subcommands()[args[0]]
if !ok {
fmt.Fprintf(stderr, "hyperguild: unknown subcommand: %s\n%s", args[0], usage) //nolint:errcheck
return 2
}
if err := cmd(ctx, args[1:], stdin, stdout, stderr); err != nil {
fmt.Fprintf(stderr, "hyperguild %s: %v\n", args[0], err) //nolint:errcheck
return 1
}
return 0
}
func main() {
os.Exit(dispatch(context.Background(), os.Args[1:], os.Stdin, os.Stdout, os.Stderr))
}