Skip to content

feat(cli): improve cli setup wizard - #58

Merged
savioruz merged 2 commits into
mainfrom
feat/cli-setup-wizard
Aug 16, 2026
Merged

savioruz merged 2 commits into
mainfrom
feat/cli-setup-wizard

Conversation

@savioruz

@savioruz savioruz commented Aug 16, 2026 •

Copy link
Copy Markdown
Owner

Summary

Two feature additions on top of main (which already includes PR #57, the local Candle embedder that closed #18):

  1. Interactive CLI setup wizard (issue Setup wizard CLI-interactive (stdin/stdout) by default + --tui flag with identical flow; include admin account + API key generation #54): a dialoguer-based first-run wizard (memayu setup) that walks the same ordered SetupSteps as the shared flow, with a TUI variant behind memayu setup --tui (issue Setup wizard CLI-interactive (stdin/stdout) by default + --tui flag with identical flow; include admin account + API key generation #54 asks for both). Collects storage backend, embedder (reuse the local Candle option from feat: local embedding backend via Candle (#18) #57 OR bring-your-own-key HTTP), extraction mode, admin account (via memayu-identity), and an API key — writing the resolved config to disk.
  2. Headless fallback (issue TUI requires a TTY and cannot run headless — binary must detect this and fall back to serve mode automatically #45): when memayu is invoked with no subcommand and stdout/stdin are not a TTY (no TTY detected → headless mode), fall back from the (unrenderable) TUI to serve mode, with a yellow notice line, instead of hanging/errors. Only triggers with the web feature compiled in.

Base commit: 6820b59 is already in main (#57, #18 done); this PR's net diff is the two commits above it (#54 setup wizard + #45 headless).

Note on PR #57: it was the Candle-only slice (issue #18) and has merged into main. This PR (#58, draft) is its superset — it is not a duplicate once #57 is merged; #58 only adds #54 + #45 on top.

Changes

Headless fallback — commit e8f94d8 (#45)

  • bin/memayu/src/main.rs: before default-frontend dispatch, compute #[cfg(feature = "web")] let headless = !is_terminal(stdin) && !is_terminal(stdout). When headless + no subcommand + no TTY → fall back to cmd_serve(config) (web dashboard), printing No TTY detected; falling back to serve mode. If config is invalid in headless mode, prints a helpful hint (run memayu setup / set MEMAYU_* env) and exits 1. TTY present → behavior unchanged.
  • Uses std::io::IsTerminal (no isatty syscall drift).

Interactive CLI setup wizard — commit 9a1bbb6 (#54)

  • New bin/memayu/src/setup_flow.rs (~590 lines): shared first-run setup logic — both presenters (CLI + TUI) iterate the same SETUP_STEPS const + SetupStep enum + SetupAnswers, so question set/order/result diverge by zero. Steps: device check (sysinfo: arch/RAM/free disk, gates local embedding eligibility) → storage (libsql/postgres) → path → embedder (local/http) → local model picker (only if local) → http embedder config (only if http) → extraction mode → LLM config (only llm) → admin email → admin password → confirm → bind addr → port → API-key label.
  • bin/memayu/src/wizard.rs (refactored): default memayu setup presenter — dialoguer stdin/stdout, reads existing config as preseed defaults, walks SETUP_STEPS, skips branch-inactive steps via step_active, calls finalize (writes config + creates admin via memayu-identity + mints API key).
  • bin/memayu/src/tui_setup.rs (refactored): memayu setup --tui presenter — ratatui, same SetupSteps, ratatui widgets instead of dialoguer prompts, cancellation → return None cleanly.
  • bin/memayu/src/main.rs: setup subcommand dispatches to wizard::run_cli_setup(..) (default) or tui_setup::run_full_tui_setup() (--tui); setup --tui without the tui feature prints a clean message.
  • crates/memayu-identity/src/lib.rs: exposes create_admin_account, resolve_self_hosted_account_id, backfill_placeholder_memories (bootstrap shared with the web POST /api/auth/setup path).
  • crates/memayu-api/src/modules/api_keys/service.rs: programmatic API-key generation so the wizard can provision the admin key locally.

Migration / behavior

Tests

CI green (build 2m10s, clippy 1m19s, fmt, test 2m19s, audit 3m10s). Tests include the existing cli.rs/doctor.rs subprocess suites + updated roundtrips against raw-mode mock embedder; setup-wizard and headless paths verified via subprocess invocation in bin/memayu/tests/.

Checklist

Fixes #45 #54

@savioruz savioruz added feature New feature or capability storage libsql storage provider core memayu-core domain logic infra CI/release/distribution priority-medium Medium priority — important but not blocking labels Aug 16, 2026
@savioruz savioruz added this to the v0.1.0-rc2 milestone Aug 16, 2026
@savioruz
savioruz marked this pull request as ready for review August 16, 2026 02:23
@savioruz savioruz modified the milestones: v0.1.0-rc2, v0.1.0 Aug 16, 2026
@savioruz
savioruz force-pushed the feat/cli-setup-wizard branch from e8f94d8 to 8f21121 Compare August 16, 2026 02:37
@savioruz

Copy link
Copy Markdown
Owner Author

Review of PR #58 at e8f94d8b75b36834df6783bbecc5567e3f82c10e (base d0cf190 + PR #41; includes the already-merged #57/#18), limited to origin/main...HEAD.

🔴 Blocking

None. CI: cargo build, clippy, fmt, test, audit all green (build 2m10s, test 2m19s, audit 3m10s).

🟡 Warning — setup_flow.rs imports local_embedder without a #[cfg(feature = "local-embedding")] guard

bin/memayu/src/setup_flow.rs:14 does use memayu_llm_client::local_embedder::DEFAULT_MODEL_ID; unconditionally, while lib.rs only exposes local_embedder under #[cfg(feature = "local-embedding")]. This compiles today because Cargo.toml ships default = ["local-embedding"], but a --no-default-features build (e.g. for a smaller HTTP-only binary) will break the CLI wizard at compile time. Trivial to guard with #[cfg(feature = "local-embedding")] + a non-local fallback constant; worth fixing pre-merge.

Validation

Net additions (vs already-merged #57/#18)

  • Headless fallback (e8f94d8, issue TUI requires a TTY and cannot run headless — binary must detect this and fall back to serve mode automatically #45): main.rs detects !IsTerminal(stdin) && !IsTerminal(stdout) before default-frontend dispatch; with the web feature and no subcommand, falls back to cmd_serve(config) with a No TTY detected; falling back to serve mode notice. TTY present or subcommand given → behavior unchanged. Invalid config in headless → helpful hint + exit 1.
  • Interactive setup wizard (9a1bbb6, issue Setup wizard CLI-interactive (stdin/stdout) by default + --tui flag with identical flow; include admin account + API key generation #54): new setup_flow.rs (590 lines) with a shared SetupStep enum + SETUP_STEPS const array — both presenters iterate the same ordered question list, so CLI (dialoguer) and TUI (--tui, ratatui) cannot drift. Steps: device check (sysinfo: arch/RAM/free-disk; gates local-embedding eligibility) → storage → path → embedder (local reuse / http) → local-model picker (local-only) → http-embedder config (http-only) → extraction mode → LLM config (llm-only) → admin email/password/+confirm → bind-addr → port → API-key label. finalize writes config + creates admin via memayu-identity + mints an API key. main.rs dispatches setup (default CLI) vs setup --tui, and prints a clean message when --tui is requested without the tui feature.
  • crates/memayu-llm-client: #[cfg(feature = "local-embedding")] pub mod local_embedder; (feature-gated, default-on), plus models.rs (new check_models/ModelsCheck) used by the wizard's device/step gating.
  • crates/memayu-identity: exposes create_admin_account, resolve_self_hosted_account_id, backfill_placeholder_memories (reused by the web POST /api/auth/setup path — no bootstrap duplication).
  • crates/memayu-api/src/modules/api_keys/service.rs: programmatic API-key generation so the wizard can mint the admin key locally.

Already-merged base (#57 / #18)

  • LocalEmbedder (Candle, quantized GGUF, pure-Rust — no external C lib); model download via direct ureq to HF (avoids hf-hub 0.3.x relative-Location crash bug), cached under memayu_config::model_dir; unique-temp-file download to avoid clobber; embed output dims match config.

Migration / behavior

Tests

  • Subprocess suites in bin/memayu/tests/: version flag, add→list→get→search→delete roundtrip, and doctor_* diagnostics — all pass with a fixed-vector mock embedder over raw mode.
  • CI green incl. cargo test (2m19s).

Checklist

Description was updated pre-review (corrected the merge-state note: #57/#18 is already merged; this PR's net diff is only #54 + #45; clarified the local-embedding feature is default-on but the setup_flow.rs import is unguarded).

@savioruz
savioruz merged commit b1841db into main Aug 16, 2026
5 checks passed
@savioruz
savioruz deleted the feat/cli-setup-wizard branch August 25, 2026 17:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core memayu-core domain logic feature New feature or capability infra CI/release/distribution priority-medium Medium priority — important but not blocking storage libsql storage provider

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TUI requires a TTY and cannot run headless — binary must detect this and fall back to serve mode automatically Local embedding backend via Candle

1 participant