Skip to content

Add aai onboard guided onboarding wizard#46

Merged
alexkroman merged 39 commits into
mainfrom
onboarding-flow
Jun 9, 2026
Merged

Add aai onboard guided onboarding wizard#46
alexkroman merged 39 commits into
mainfrom
onboarding-flow

Conversation

@alexkroman

Copy link
Copy Markdown
Collaborator

Summary

Adds aai onboard — a guided first-run wizard that takes a newcomer from zero to a successful API request and into building, modeled on OpenClaw's onboarding blueprint. Goal: make the CLI the easiest way to onboard to AssemblyAI.

The wizard

Ordered, resumable sections (each self-skips when already satisfied):

  1. Welcome
  2. Sign in — browser login (recommended) or paste an API key; nudges to the signup URL when the account/project is missing.
  3. First transcription — prompts for a file path or YouTube URL, Enter defaults to the hosted sample. Reuses transcribe's resolver (files / URLs / YouTube). A failure degrades to a clean message and FAILED, not a crash.
  4. Environment check — non-blocking (doctor's python/ffmpeg/mic checks).
  5. What do you want to build? — scaffolds an init template (no blocking dev-server launch).
  6. Optional Claude Code wiringaai setup install, skipped silently if claude/npx absent.
  7. Next steps — copy-pasteable commands.

Design notes

  • Prompter abstraction: typer.confirm/typer.prompt for yes-no/text, questionary for arrow-key menus (consistent with aai init); a non-interactive prompter keeps pipes/CI/agent runs from hanging.
  • Bare aai with no credentials in an interactive terminal offers the wizard — never hijacks --help, subcommands, or non-interactive sessions (invoke_without_command=True).
  • onboard is listed first in the Quick Start help panel; install.sh and the post-login hint now point at aai onboard.
  • Terminal cursor is always restored; cancellation exits cleanly.

Also in this branch

  • aai usage now reports dollars derived from line_items[].price (the AMS total field always returns 0) and shows a clear message when no custom rate limits are configured.

Not included

  • A request-progress counter was prototyped and then removed — there's no accurate way to count account-wide requests from the CLI.

Testing

  • Built TDD, task-by-task. Full ./scripts/check.sh passes, including 100% patch coverage and the diff-scoped mutation gate.
  • Design spec and implementation plan live in docs/superpowers/.

🤖 Generated with Claude Code

alexkroman-assembly and others added 25 commits June 8, 2026 15:47
Designs `aai onboard`: a guided first-run wizard (auth → first API
request → env check → build-path picker → Claude Code wiring → progress)
modeled on OpenClaw's onboarding blueprint, plus a local request counter
tracking progress toward 100 requests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
12 TDD tasks: request counter, progress rendering, counter wiring,
prompter abstraction, run_init extraction, seven wizard sections,
orchestrator, aai onboard command, help reordering + bare-aai offer,
hint updates, and snapshot/gate.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Template requirements.txt files listed bare package names (fastapi,
uvicorn, httpx2, python-dotenv, ...). SCA scanners read a starter app's
requirements.txt as a lockfile and report unpinned lines as "missing
versions", blocking vulnerability analysis.

Pin every template dependency to a >= floor matching the project's own
(pyproject deps), and add a _requirements_pin_versions check to both the
template contract gate (the check.sh stage) and the parametrized pytest
contract test so a future unpinned dep fails loudly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds the per-command help snapshot for the new `aai onboard` command. The
root --help ordering and login-success hint are pinned by assertion-based
tests, not syrupy, so only this one snapshot changed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two gate fixes for the onboard work:

- mypy strict (no_implicit_reexport): switch monkeypatch targets to the
  string-target form (e.g. "aai_cli.main.typer.confirm") and import the
  prompter classes from their source module instead of re-importing them
  through the command module.

- mutation gate (diff-scoped): add assertions that kill the surviving
  mutants on changed lines — pin the onboard exit-code guard (code != 0),
  auto_login=False, the request-counter `or 0` fallback,
  _interactive_session's `and`, the bare-aai offer's confirm default and
  json_mode, the prompter confirm defaults, cursor restore (show=True), the
  exact run_init/claude-setup kwargs, the doctor render `ok=True`, and
  init's `api_key is None` launch guard (via a --json step assertion).
  One genuinely-equivalent mutant — the Prompter Protocol stub default — is
  marked `# pragma: no mutate` (not a forbidden escape hatch).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… source

Drop the 'N of 100 requests' counter entirely (no accurate way to track
request counts) and make the wizard's first transcription prompt for a
file path or YouTube URL, defaulting to the hosted sample on Enter.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The AMS usage endpoint returns total:0.0 on every window; derive each
window's spend from line_items[].price (cents) instead and render it as
dollars. Show a clear message when an account has no custom rate limits.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Update the onboard --help snapshot (drops the --status option and its
"progress toward 100 requests" example) and assert the first-transcription
status label so the diff-scoped mutation gate kills the source-vs-sample
Or->And mutant on sections.py:76.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread aai_cli/onboard/sections.py
Comment thread aai_cli/onboard/prompter.py
alexkroman-assembly and others added 3 commits June 8, 2026 18:53
Print an `aai` wordmark + version/tagline header on the bare-command
welcome screen (suppressed by --quiet), retint Typer's cyan option/command
styling to the logo blue, and drop the now-redundant top-level help line.
Swap the theme's remaining cyan accents for a dark blue.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Remove the `samples` command and all related code (module, tests, help
  snapshots, import-linter contract, README/AGENTS/skill docs).
- Remove the `version` command; keep `--version`/`-V`. Repoint smoke,
  __main__, and install-script tests to the flag.
- Shorten the `--show-completion` and `init` help text so they stop wrapping.
- Onboarding: browser-only sign-in (drop the API-key paste path so a secret
  never lands in scrollback/history), fix the duplicated "Environment check"
  heading, space the setup prompt off the banner, and reword the source and
  build-path prompts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rename the "Transcription & AI" panel to "Run AssemblyAI" and give `init`
its own "Build an app" panel, so the help screen distinguishes commands that
use AssemblyAI directly from the one that scaffolds a new project. Reword
init's help to "Scaffold a new project from a template, then launch it."

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
alexkroman-assembly and others added 10 commits June 8, 2026 19:26
Move the doctor/setup panel beneath the Run AssemblyAI commands so the help
screen flows onboard → build → run → maintain.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Match the casing of the other multi-word panels (Quick Start, Setup & Tools).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Implements the prioritized recommendations from the persona journey review:

- transcribe: add --out FILE to save a clean text artifact; annotate -o
  values; document the human-by-default --json policy; lead the docstring
  with the simplest invocation; --show-code now works with no source
  (emits a placeholder path).
- usage: show the per-product breakdown in dollars (from line_items[].price),
  aggregated by product and reconciling to the window total — no more raw
  quantities mixed with dollars.
- env: the mismatch warning now also fires for AAI_ENV (not just --env) and
  names the source, catching silent sandbox/prod key swaps.
- errors: root-callback failures (e.g. bad --env) honor a --json/-o json
  request and emit the uniform {"error": ...} shape; soften the not-signed-in
  message and point it at `aai onboard`.
- stream/agent: document stdin raw-PCM streaming (`aai stream -` + ffmpeg),
  cross-reference the in-process vs piped LLM paths, surface the headphones
  caveat in `agent --help`.
- setup: enumerate the three installed artifacts (docs MCP, AssemblyAI skill,
  bundled aai-cli skill) in help.
- limits: clarify the empty state (standard limits apply).
- root help: document that global options go before the subcommand.
- templates: comment the intentional httpx2 import so integrators don't "fix" it.
- AGENTS.md: fix the stale `aai claude` reference (now `aai setup`).

Snapshots regenerated; new tests added; full gate (ruff/mypy/pyright/vulture/
deptry/import-linter/diff-cover 100%/diff-scoped mutation) green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Audited every command's `--help` Examples panel and reworked them to
surface high-value capabilities that were previously undiscoverable:

- root: lead with breadth (transcribe/stream/agent) + a `--llm` one-liner
- transcribe: add YouTube input, speaker labels, PII redaction,
  summarization, and `--llm` Q&A; drop the redundant `-o text` example
- stream: add file/URL source, speaker labels, and keyterm prompts
- agent: show `--system-prompt` persona
- llm: add model + `--system` example, reword transcript-id example
- transcripts/sessions: add `--json | jq` pipelines and id-chaining
- account/keys/audit: add `--json | jq` scripting recipes; fix the
  `audit --limit 20` example that showed the default as if required
- init: show the voice-agent template and `--no-install`
- doctor/setup: add `--json` and `--force`/`--scope` examples

No piping into `aai llm` and no `--sandbox` examples per review.
Snapshots regenerated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: aikido-pr-checks[bot] <169896070+aikido-pr-checks[bot]@users.noreply.github.com>
The starter-app requirements.txt pins used floors low enough to admit
known-vulnerable releases (python-multipart>=0.0.9, python-dotenv>=1.0.0),
and fastapi>=0.115.0 transitively pins starlette<0.39.0 — pulling a
starlette with CVE-2024-47874 / CVE-2025-54121 / CVE-2026-48710.

Raise fastapi/dotenv/multipart/httpx2 floors to current patched releases
and add an explicit starlette>=1.2.1 pin (FastAPI's own starlette>=0.46.0
floor still admits CVE'd versions).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…--out

Move the transcription-execution + output-shaping helpers out of the
transcribe command into a new core module aai_cli/transcribe_exec.py
(run_transcription, out_payload, render_transform_steps). This keeps the
command a thin option surface, drops it back under the 500-line gate, and
lets onboard import run_transcription from a core module instead of
reaching into the command's private _transcribe_audio (removing a
reportPrivateUsage suppression).

Also harden the merged-in --out path-traversal guard: replace the bare
`raise Exception` with a clean UsageError (exit 2, no traceback) and check
`".." in out.parts` (path components) instead of a substring match, so a
filename merely containing ".." isn't wrongly rejected.

Tests: split the --out cluster into tests/test_transcribe_out.py (keeps
test_transcribe.py under 500) and add a path-traversal rejection test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nternals

The onboard wizard reused command internals by reaching into private
functions with reportPrivateUsage suppressions. Promote exactly the
reused functions to public API and call those instead:

- doctor: check_python / check_ffmpeg / check_audio / render
- setup:  install_mcp / install_skill / install_cli_skill / render

(_check_api_key, _check_coding_agent and the install helpers onboard
doesn't use stay private — minimal public surface.) Removes all eight
reportPrivateUsage suppressions in onboard/sections.py; the wizard now
depends only on each command module's intended public surface. Test
patch targets updated to the public names.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread aai_cli/onboard/sections.py
The `version` subcommand was removed; the root callback exposes
`--version`. Update the brew-install CI step and the formula's `test do`
block (plus the explanatory comments) so the smoke test stops failing
with "No such command 'version'".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@alexkroman alexkroman merged commit fd85338 into main Jun 9, 2026
11 checks passed
@alexkroman alexkroman deleted the onboarding-flow branch June 9, 2026 04:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants