Survey of 10 mainstream CLIs (gh, lark, stripe, vercel, supabase, aws,
azure, gcloud, openai/codex, github-copilot-cli) showed env-gated
per-command --help blurbs are a Stripe-only pattern; gh uses env detect
for telemetry only, and lark relies on installed agent Skills + MCP.
Our cmd/mcp/serve already covers the dominant 2025/26 path, so
internal/aiclient/ (136 LOC + 38 callsites) is net maintenance burden
without precedent.
- Drop internal/aiclient/ entirely (annotations + detect + tests)
- Remove 38 SetAgentHelp callsites + agentAwareHelpFunc / SetHelpFunc
wiring in cmd/root.go
- Migrate 4 command-level rules to standard Long help (visible to all,
not env-gated): doc upload mode mutex, kb edit at-least-one,
kb pin idempotent, search chunks channel mutex
- Rewrite AGENTS.md as a developer guide (gh-style 6 H2 / 167 lines):
audience preamble + Build / Architecture / Command Structure /
Testing / Code Style / Error Handling. Drops sections absent in
surveyed projects (Commit & PR Conventions, Who Uses This CLI)
- Clean 14 internal doc refs (ADR-N, spec §X, v0.X) in source comments
and docs that pointed at docs/superpowers/ — that directory is
local-only / uncommitted, so refs are dead for outside readers
- Drop forward-looking "once v0.2 ships" from README
Two halves of v0.3 roadmap item 3-2.
(1) `weknora auth refresh` — explicit token renewal:
Reads the stored refresh_token, spends it via POST /api/v1/auth/refresh
(OAuth refresh-token grant), and persists both new tokens. API-key
contexts rejected with input.invalid_argument (no refresh semantic).
NOTE: gh CLI has `gh auth refresh` but with different semantics —
gh's variant is an OAuth scope expansion / re-prompt via the browser
(verified against the gh manual). The two share a name but solve
different problems; there's no direct gh parallel for refresh-token
grant because gh's PAT/OAuth-app model doesn't expose a short-lived
access_token + refresh_token pair to clients.
Error mapping:
- no current context → auth.unauthenticated
- --name unknown → local.context_not_found
- missing refresh in keyring → auth.token_expired (hint: re-login)
- server Success=false → auth.token_expired
- network → network.error
Envelope omits the token values (would leak into agent transcripts).
(2) AuthRetryTransport — transparent retry:
Wraps the SDK http.Client. On a 401 from a non-/auth/* endpoint:
- JWT context: read refresh token, hit /auth/refresh, persist new pair,
replay original request with new bearer.
- API-key context: pass through (no refresh semantic).
- Non-replayable body (req.GetBody == nil): pass through.
- /auth/login or /auth/refresh: pass through (no recursion).
Concurrent 401s are singleflight-coalesced via sync.Mutex — 5 parallel
calls trigger exactly 1 refresh.
SDK additions (additive, non-breaking):
- WithTransport(rt http.RoundTripper) ClientOption.
- PathAuthLogin / PathAuthRefresh constants (cli/internal/cmdutil/authretry
imports them so the CLI and SDK can't drift on path strings).
Refactor surfaced by the post-commit reviewer round:
- cmdutil.RefreshAndPersist(ctx, store, refresher, ctxName) — the
load-refresh → call-SDK → persist-pair sequence was duplicated between
the standalone `auth refresh` and the transport's refresh closure;
collapsed to one canonical implementation.
- refreshFn signature takes context.Context so Ctrl+C during a
transparent refresh cancels.
- AuthRetryTransport.CurrentToken() removed — never called.
8 + 8 + 8 unit tests cover happy path / refresh-fail / auth-endpoint
skip / api-key passthrough / singleflight under concurrency / non-
replayable-body fallback.
Roadmap: 3-2.