feat(cli): implement full CLI command tree #14

Closed
core-be wants to merge 2 commits from feat/cli-full-command-tree into main
Member

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 calling cmd.Execute()
  • internal/cmd/root.go: cobra root with global flags (--api-url, --verbose, --output, --config), registers all 4 command groups
  • internal/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: runHTTP helper shared by agent send and workspace delegate
  • internal/client/platform.go: control plane HTTP client with workspace/agent/health/audit operations

All 18 subcommands wire to the platform API via MOLECULE_API_URL. Binary builds cleanly to ./bin/mol with 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 OK
  • bin/mol --help — shows all 4 command groups
  • bin/mol workspace --help — shows all 7 workspace subcommands
  • bin/mol agent --help — shows all 4 agent subcommands
  • bin/mol config --help — shows all 5 config subcommands
  • bin/mol platform --help — shows audit, health
  • bin/mol --version — shows version
  • MOLECULE_API_URL=http://localhost:8080 bin/mol workspace list — hits API
  • bin/mol workspace list --output json — structured output works
  • Run CI (go test ./..., go build)

🤖 Generated with Claude Code

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 calling `cmd.Execute()` - `internal/cmd/root.go`: cobra root with global flags (`--api-url`, `--verbose`, `--output`, `--config`), registers all 4 command groups - `internal/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`: `runHTTP` helper shared by agent send and workspace delegate - `internal/client/platform.go`: control plane HTTP client with workspace/agent/health/audit operations All 18 subcommands wire to the platform API via `MOLECULE_API_URL`. Binary builds cleanly to `./bin/mol` with 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 OK - [ ] `bin/mol --help` — shows all 4 command groups - [ ] `bin/mol workspace --help` — shows all 7 workspace subcommands - [ ] `bin/mol agent --help` — shows all 4 agent subcommands - [ ] `bin/mol config --help` — shows all 5 config subcommands - [ ] `bin/mol platform --help` — shows audit, health - [ ] `bin/mol --version` — shows version - [ ] `MOLECULE_API_URL=http://localhost:8080 bin/mol workspace list` — hits API - [ ] `bin/mol workspace list --output json` — structured output works - [ ] Run CI (go test ./..., go build) 🤖 Generated with [Claude Code](https://claude.ai/claude-code)
core-be added 2 commits 2026-06-01 06:43:20 +00:00
feat(cli): fix runHTTP auth bug + add management verbs
Release Go binaries / release (pull_request) Blocked by required conditions
CI / Test / test (pull_request) Successful in 1m51s
Release Go binaries / test (pull_request) Successful in 1m11s
a002b412e9
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>
fix(cli): repoint org create/list to CP-admin bearer; fail-fast get/export
CI / Test / test (pull_request) Waiting to run
Release Go binaries / release (pull_request) Blocked by required conditions
Release Go binaries / test (pull_request) Waiting to run
442d1ebaf4
Review fix for #13. The CP org verbs targeted /api/v1/orgs*, which is gated by
RequireSession() (WorkOS cookie-only) — a bearer-token CLI can't authenticate
and these 401 in prod; the tenant Org API Key has no standing on the CP at all.

- org create/list now target the CP ADMIN routes (POST/GET /api/v1/admin/orgs,
  AdminGate bearer), authenticated with a DISTINCT credential MOLECULE_CP_ADMIN_TOKEN
  (never the tenant MOLECULE_API_KEY). create now requires --owner-user-id, per
  controlplane adminCreateOrgRequest{slug,name,owner_user_id}. ListOrgs decodes
  the {limit,offset,orgs[]} admin-summary envelope. Two-credential split is
  documented in `org`/`org create` help text; the org key is never sent to the CP.
- org get/export have NO AdminGate-reachable route on the CP (session-only), so
  they fail fast with a clear "session-only, use the dashboard" error instead of
  shipping verbs that 401.
- cpAdminClient() fails fast with guidance when MOLECULE_CP_ADMIN_TOKEN is unset
  (wrong-credential path), rather than silently sending the org key to the CP.
- Wire Execute() through handleErr so SilenceErrors'd exitError messages actually
  print (they were previously swallowed by main's bare os.Exit(1)) — required for
  the fail-fast guidance to reach the user.
- Optional cleanup: extract resolveBillingMode()/budgetLimitsFromFlags() so prod
  and tests share one definition.
- Tests: client + cmd assert org verbs hit /api/v1/admin/orgs with the CP-admin
  bearer (no org-id header, no org-key leak), the missing-owner and
  missing-admin-token fail-fast paths, get/export fail-fast, and an e2e CLI test
  that `org list` without the admin token exits non-zero naming MOLECULE_CP_ADMIN_TOKEN.

Budget shape (budget_limits) left unchanged — confirmed correct; the OpenAPI
spec is the stale one (fixed separately on #2056).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
core-be added 1 commit 2026-06-01 07:12:48 +00:00
fix(cli): sync viper config values into globals after ReadInConfig
CI / Test / test (pull_request) Waiting to run
Release Go binaries / test (pull_request) Waiting to run
Release Go binaries / release (pull_request) Blocked by required conditions
d882cdd1ee
CR2 review finding: config file values were read but not applied to
the CLI globals (apiURL, outputFormat, verbose, jsonOutput). Add
viper.BindPFlag for all persistent flags and sync values back from
viper after ReadInConfig() so the full precedence chain works:
flag > env > config > default.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
core-be added 1 commit 2026-06-01 07:14:37 +00:00
fix(cli): send empty object {} instead of null for workspace token mint
CI / Test / test (pull_request) Waiting to run
Release Go binaries / release (pull_request) Has been cancelled
Release Go binaries / test (pull_request) Has been cancelled
a73c20e2e5
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>
core-be closed this pull request 2026-06-01 07:27:38 +00:00
Some checks are pending
CI / Test / test (pull_request) Waiting to run
Required
Details
Release Go binaries / release (pull_request) Has been cancelled
Release Go binaries / test (pull_request) Has been cancelled

Pull request closed

Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: molecule-ai/molecule-cli#14