Skip to content

feat(tui): first-run experience — launch decision tree, welcome readiness check, detected agents#598

Merged
bborn merged 5 commits into
mainfrom
feat/tui-first-run
Jun 12, 2026
Merged

feat(tui): first-run experience — launch decision tree, welcome readiness check, detected agents#598
bborn merged 5 commits into
mainfrom
feat/tui-first-run

Conversation

@bborn

@bborn bborn commented Jun 12, 2026

Copy link
Copy Markdown
Owner

Summary

Ships the first-run / first-folder experience plan (docs/superpowers/plans/2026-06-05-first-run-experience.md, included with all checkboxes ticked) plus two Welcome-view additions from competitor onboarding research: a non-blocking machine-prerequisite check and a detected-agents confidence beat.

The launch decision tree (runs on every startup)

launch (tasksLoadedMsg, first load)
├─ cwd is a project candidate (git repo OR marker file, minus deny-list)
│    └─ "New Project Detected" card, enriched async via `claude -p` inference
│       (name / alias / description; degrades gracefully to basename + imported
│       instructions when claude is unavailable). Per-path dismissable.
├─ no real projects yet (only "personal") + junk folder + first run
│    └─ Welcome fork: [Set up a project] → fuzzy folder picker → enriched card
│                     [Just start a task] → New Task form in "personal"
└─ otherwise → board as usual

Git stays optional: non-git candidates get Worktrees: false and project creation never inits git. Project-form validation always routes through reshowProjectFormWithError, so input is never lost.

Note: plan Tasks 1–9 were found already implemented on main (the feat/fix/test(onboarding) commit range 25a64f8034991e5d). This PR verifies each task against the plan's named commands (see the plan's Execution record section) rather than re-implementing, and contributes:

  • feat(onboarding): Welcome view shows Detected agents: claude, codex, … (reusing the existing availableExecutors detection) and, when tmux or all executor CLIs are missing, clearly visible non-blocking notices with exact install hints (tmux not found — brew install tmux / no coding agent found — npm install -g @anthropic-ai/claude-code), mirroring the desktop SetupCheck. Pure formatting/notice logic TDD-tested in internal/ui/welcome_test.go.
  • fix(qa): the ty-qa harness died on macOS stock bash 3.2 — a failing command tmux … inside || true still aborts under set -e (3.2 command-builtin errexit bug). lib.sh now resolves the tmux binary at source time.
  • docs: the plan, ticked, with an addendum documenting the additions and an execution record.

Test evidence

  • go build ./... clean; gofmt -l internal/ui internal/ai empty; go vet ./internal/ui/... ./internal/ai/... clean.
  • Plan-named tests all PASS: TestIsProjectCandidate, TestParseInferenceJSON, TestInferProjectMetadata_DegradesWhenClaudeMissing (passes with claude unreachable, by design), TestApplyInferredMetadata, TestFuzzyFilterFolders.
  • New TDD tests PASS (red→green): TestFormatDetectedAgents, TestMissingPrereqNotices, TestWelcomeViewShowsEnvironmentStatus (asserts notices never hide the fork).
  • Full go test ./... passes (internal/ui, internal/ai, internal/parity included). Two internal/executor tests fail only when the ambient shell exports CLAUDE_CONFIG_DIR — pre-existing environment sensitivity on main, unrelated to this branch; suite is green with it unset.

Live QA exercised (isolated harness, scripts/qa/ty-qa-firstrun.sh)

  • Scenario A — git repo: enriched card with live claude -p inference (Name: Acme Rocket, Alias: acmerocket, instructions imported from README, Worktrees: true).
  • Scenario B — non-git marker folder: card with Worktrees: false; pressed y → project created (use_worktrees=0 in DB), no .git created.
  • Scenario C — plain folder: Welcome fork with Detected agents: claude, codex, gemini, opencode, pi.
  • Drove fork → fuzzy picker (type-to-filter workflow → 3 git-tagged matches) → esc back to Welcome → "Just start a task" → New Task form in personal.
  • Stripped-PATH launch: both prerequisite notices rendered, fork still fully usable (non-blocking confirmed).
  • Nested-repo sanity: parent repo with nested sub-repo, ty projects create + ty create against the isolated DB, worktree created without error.

Not exercised live

  • Tier-3 full-daemon end-to-end (executor-driven worktree + agent run): the live user daemon holds the global daemon lock, and stopping it was out of bounds. Nested-repo worktree creation was verified via the tier-2 mechanism (git worktree add, the executor's underlying operation) per scripts/qa/README.md.
  • The folder picker can't reach /tmp scenario folders (it seeds from ~/Projects, ~/src, …), so "pick just-a-folder via the picker" was exercised as picker navigation + the same suggestion-card path driven from Scenario B instead.

🤖 Generated with Claude Code

bborn and others added 4 commits June 12, 2026 09:35
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rereq notices

When the Welcome fork renders, surface machine readiness without gating
anything: a confidence beat listing detected executor CLIs ("Detected
agents: claude, codex", reusing availableExecutors detection) and, when
tmux or all executor CLIs are missing, a visible warning line with the
exact install hint (mirroring the desktop SetupCheck wording).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…readiness additions

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…xit bug

macOS stock bash 3.2 aborts a 'set -e' script when a failing command is
prefixed with the 'command' builtin, even inside '|| true' lists. lib.sh's
tmux() wrapper used 'command tmux', so every ty-qa script died at its first
'tmux kill-session' against a not-yet-running QA server. Resolve the real
binary into TY_QA_TMUX_BIN at source time instead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@bborn

bborn commented Jun 12, 2026

Copy link
Copy Markdown
Owner Author

QA screenshots (TUI)

Captured with the real TUI via the VHS QA harness (scripts/qa/ty-qa-shoot.sh) against a fully isolated instance (TY_QA_ROOT=/tmp/ty-qa-598, fresh DB per shot = true first run; live daemon/DB untouched).

Welcome fork — agents detected. First run in a plain (non-project) folder; the new "Detected agents: …" confidence line lists the executor CLIs found on PATH.
welcome

Welcome fork — missing prereqs. Same screen launched through a wrapper that strips Homebrew/npm from PATH (no tmux, no agent CLIs): both non-blocking warning notices show with exact install hints, and the fork stays usable.
welcome-missing-prereqs

Project suggestion card. First run inside a seeded git repo with a README; after the claude -p inference completes (9s sleep), the enriched "New Project Detected" card shows the inferred name/alias, README-imported instructions, and worktrees enabled.
suggestion-card

Fuzzy folder picker. From the Welcome fork: Enter on "Set up a project", then typing ty fuzzy-filters the folder list (git repos badged), with select/open/pick/back keys in the help bar.
folder-picker

🤖 Generated with Claude Code

The first-run folder picker was a bare hand-rolled list: full paths in a
flat column, a ">" cursor, bare "git ●" text, and a wall of dead space.
Rebuild the view on bubbles/list inside a centered bordered panel that
matches the Welcome fork:

- folder basename as the prominent title, dimmed ~-collapsed parent path
  as the description, accent bar + accent color on the selected row
- typing drives the list's built-in fuzzy filter (SetFilterText), so
  matched runes are underlined in place; the custom delegate mirrors
  list.DefaultDelegate but can append a styled green "⏺ git" badge to
  repo titles without mangling ANSI inside the title
- count line ("66 folders · git repos first" / "10 of 66 folders match")
  plus the list's pagination dots when the list overflows
- all behavior preserved: type-to-filter, ↑↓ select, → descend (leaf
  folders still picked with enter), enter pick (folderPickedMsg), esc back

fuzzyFilterFolders is gone (the list's fuzzy filter replaces it); its
test is replaced by coverage of the seeding/sorting logic that remains
(collectCandidateFolders / sortFolderEntries).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@bborn

bborn commented Jun 12, 2026

Copy link
Copy Markdown
Owner Author

Picker restyle

The fuzzy folder picker is rebuilt on bubbles/list — centered bordered panel (matching the Welcome fork), folder basename as the prominent row title with a dimmed ~/-collapsed parent path beneath it, accent bar on the selected row, a green ⏺ git badge on repos, underlined fuzzy-match runes while typing, plus a count line and pagination dots when the list overflows. All behavior is unchanged: type-to-filter, ↑/↓ select, → descend (leaves still picked with enter), enter pick, esc back.

Before

before

After — typing ty (matched runes underlined, count line, pagination)

after-filtered

After — unfiltered (git repos first) and descended into a folder (→)

after-unfiltered
after-descend

Verified end-to-end with the QA harness: enter on the top match still emits folderPickedMsg and lands on the New Project Detected card. go build ./..., go test ./internal/ui ./internal/parity, gofmt/vet clean. (fuzzyFilterFolders is replaced by the list's built-in fuzzy filter; its test now covers the remaining seeding/sorting logic.)

🤖 Generated with Claude Code

@bborn bborn merged commit f5ae5a6 into main Jun 12, 2026
4 checks passed
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.

1 participant