feat(cli): implement full CLI command tree #14
Reference in New Issue
Block a user
Delete Branch "feat/cli-full-command-tree"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Implements the full CLI command tree for molecule-cli, the primary user-facing tool for the Molecule AI platform.
cmd/molecule/main.go: entry point callingcmd.Execute()internal/cmd/root.go: cobra root with global flags (--api-url,--verbose,--output,--config), registers all 4 command groupsinternal/cmd/workspace.go: 7 subcommands (list, create, inspect, delete, restart, audit, delegate)internal/cmd/agent.go: 4 subcommands (list, inspect, send, peers)internal/cmd/platform.go: 2 subcommands (audit, health)internal/cmd/config.go: 5 subcommands (list, get, set, init, view)internal/cmd/http.go:runHTTPhelper shared by agent send and workspace delegateinternal/client/platform.go: control plane HTTP client with workspace/agent/health/audit operationsAll 18 subcommands wire to the platform API via
MOLECULE_API_URL. Binary builds cleanly to./bin/molwith Go 1.23.Resolves: KI-001 (entry point), KI-002 (partial — API client), KI-003 (go.sum).
Test plan
go build -o bin/mol ./cmd/molecule— BUILD OKbin/mol --help— shows all 4 command groupsbin/mol workspace --help— shows all 7 workspace subcommandsbin/mol agent --help— shows all 4 agent subcommandsbin/mol config --help— shows all 5 config subcommandsbin/mol platform --help— shows audit, healthbin/mol --version— shows versionMOLECULE_API_URL=http://localhost:8080 bin/mol workspace list— hits APIbin/mol workspace list --output json— structured output works🤖 Generated with Claude Code
Fix the auth bug FIRST: internal/cmd/http.go runHTTP (and the internal/client Platform HTTP helpers, which had the same gap) sent NO Authorization header, so management calls (workspace create/delete, secrets, tokens, …) 401'd a hardened tenant. Now every request attaches `Authorization: Bearer $MOLECULE_API_KEY` and, when set, `X-Molecule-Org-Id: $MOLECULE_ORG_ID` (the tenant TenantGuard routing gate). Headers are omitted when the env vars are unset so fresh self-host/dev tenants keep working. Regression test TestRunHTTP_SetsAuthHeader asserts the header is set and is proven load-bearing (fails with `Authorization header = ""` when the fix is reverted). Add the management verbs (PLATFORM-MANAGEMENT-API.md §5(b)), each wired to the OpenAPI-documented endpoint at the correct auth tier (verified against the live workspace-server router.go + handlers and controlplane orgs handler, since the parallel feat/openapi-management-spec branch does not exist in molecule-core — reconciled to the actual handler source instead): org list|get|create --slug/--name|create --template|export token list|create|revoke | allowlist workspace list|get|create|delete|restart|pause|resume budget|billing-mode|token mint secret ws list|set|delete org list|set|delete template list|import|refresh bundle export|import events approvals Org-lifecycle verbs target the control plane (MOLECULE_CP_URL, default = api-url); tenant verbs target the tenant host with the Org API Key. All verbs honor --json (and existing -o table|json|yaml). Request/ response shapes match the handler structs (budget USD-cents budget_limits; billing-mode {mode}; org import {dir,mode}; secrets {key,value}; template import {name,files}; etc.). Tests: table-driven request-construction tests (method/path/body/auth) for all 30 management methods against an httptest mock, plus cmd-layer branch tests (budget flag→limits, billing-mode validation, template file mapping, --json resolution, CP-url fallback). Existing workspace/agent/platform commands switched to the authenticated client. go build ./..., go vet ./..., go test ./... all green; gofmt clean on edited files. Binary smoke-tested end-to-end: auth headers reach the server and --json output renders. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>CR2 review finding: MintWorkspaceToken passed nil to postInto, which marshals to JSON null. Pass an empty map so the body is {} as expected by the handler. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>Pull request closed