Files
galaxy/specs/APP-3680/PRODUCT.md
T

10 KiB
Raw Blame History

Onboarding Tab Config Modal — Product Spec

Linear: APP-3680 Figma: House of Agents — node 7077-23101

Problem

After completing onboarding, users land in an empty terminal tab with no guidance on configuring their first working session. There is no streamlined way to pick a session type (terminal vs. agent), choose a project directory, enable worktree support, and optionally persist that setup as a reusable tab config — all in a single flow.

Summary

A new modal ("Create your default tab config") appears after onboarding completes, overlayed on the terminal. It collects three inputs — session type, directory, and worktree preference — then creates a persistent tab config TOML in ~/.warp/tab_configs/ and opens it in the current tab.

Goals

  • Let users configure their first session immediately after onboarding in a single modal.
  • Support Built in agent (Oz), third-party CLI agents (Claude, Codex, Gemini), and Terminal as session types.
  • Always persist the configuration as a reusable tab config TOML in ~/.warp/tab_configs/.
  • Keep the modal implementation reusable so it can be surfaced in other contexts later (e.g., from a menu or command palette).

Non-goals

  • Worktree name generation (Moira is handling this in parallel; hardcode the branch name for now).
  • Editing or managing existing tab configs from this modal.
  • Showing this modal on every new tab — it only appears post-onboarding in the open source onboarding rev.
  • Web/WASM support — this is local-only (local_fs).

User Experience

When the modal appears

The modal appears once, immediately after the user completes the onboarding slide flow. It only appears when OpenWarpNewSettingsModes is enabled — this is the new onboarding path. Users on the old onboarding flow never see this modal. It is rendered as a centered overlay on top of the terminal workspace (not as a full-screen onboarding slide). The user cannot interact with the terminal behind it while the modal is open.

Modal layout (per Figma)

  • Title: "Create your default tab config"
  • Subtitle: "Select if you'd like to work in the terminal versus with an agent of your choosing."
  • Session type: A row of selectable pill-style buttons that wrap. Options (in order): Built in agent, Claude, Codex, Gemini, Terminal. Only one can be selected at a time. Built in agent is selected by default.
  • Select directory: A button that opens a native OS folder picker. Displays the selected path left-aligned (defaults to ~). Text is semibold, no folder icon.
  • Enable worktree support: A checkbox. Disabled with a tooltip ("Select a git repository to enable worktree support") when the selected directory is not a git repository. Unchecked by default.
  • "Get warping" button: Primary action button with Enter keyboard shortcut.

Session type behavior

Each session type determines what happens when the user clicks "Get warping":

  • Terminal: Opens a terminal session in the selected directory. No command is auto-run.
  • Oz: Opens the tab into agent view / Oz agent mode (not a CLI command). The tab starts in the selected directory with the Oz agent UI active.
  • Claude / Codex / Gemini: Opens a terminal session in the selected directory and auto-runs the corresponding CLI command (claude, codex, gemini).

Directory selection

Clicking the directory button opens a native OS folder picker (folders only, same as the existing project slide picker). After selection, the button text updates to show the selected path. The default before any selection is ~ (the user's home directory).

Enable worktree support

When checked and a git repo is selected, the session (and tab config, if saved) will include git worktree creation commands. The worktree branch name is hardcoded for now (e.g., "my-feature-branch").

Disabled state: The checkbox is visually disabled and non-interactive when the selected directory does not contain a .git directory (or is not inside a git repo). A tooltip explains: "Select a git repository to enable worktree support." If the user changes the directory from a git repo to a non-git directory, the checkbox unchecks automatically and becomes disabled.

"Get warping"

Clicking "Get warping" always saves a tab config and opens it:

  1. Writes a new TOML file to ~/.warp/tab_configs/. The file is named startup_config.toml (or startup_config_1.toml, startup_config_2.toml, etc. if the name is taken).
  2. The TOML file contains:
    • name = "Startup Config" (or with a numeric suffix matching the file name).
    • A single [[panes]] entry with type, cwd, and optional commands (see "Tab config TOML generation" below).
    • If worktree is enabled, [params] section with worktree_branch_name (type text, default "my-feature-branch").
  3. Dismisses the modal.
  4. Opens the newly created tab config in the current tab (replacing it), using the same flow as open_tab_config — which means if the config has params (worktree case), the params modal appears first.
  5. If write fails, falls back to opening the tab config without persisting it.

Tab config TOML generation

The TOML structure depends on the combination of selections:

Terminal only (no worktree):

name = "Startup Config"

[[panes]]
id = "main"
type = "terminal"
cwd = "/absolute/path/to/dir"

CLI agent (e.g., Claude), no worktree:

name = "Startup Config"

[[panes]]
id = "main"
type = "terminal"
cwd = "/absolute/path/to/dir"
commands = ["claude"]

Terminal + worktree:

name = "Startup Config"
title = "{{worktree_branch_name}}"

[[panes]]
id = "main"
type = "terminal"
cwd = "/absolute/path/to/dir"
worktree_name_autogenerated = true
commands = [
  "git worktree add -b {{worktree_branch_name}} ../{{worktree_branch_name}}",
  "cd ../{{worktree_branch_name}}",
]

[params.worktree_branch_name]
type = "text"
description = "New worktree branch name"
default = "my-feature-branch"

CLI agent + worktree:

name = "Startup Config"
title = "{{worktree_branch_name}}"

[[panes]]
id = "main"
type = "terminal"
cwd = "/absolute/path/to/dir"
worktree_name_autogenerated = true
commands = [
  "git worktree add -b {{worktree_branch_name}} ../{{worktree_branch_name}}",
  "cd ../{{worktree_branch_name}}",
  "claude",
]

[params.worktree_branch_name]
type = "text"
description = "New worktree branch name"
default = "my-feature-branch"

Oz session: Uses type = "agent" on the pane, which causes the tab to open in agent view via PaneMode::Agent. The DefaultSessionMode setting is also set to Agent so future new tabs default to agent view. When the feature flag for this new onboarding modal is off, the existing behavior (where selecting AgentDrivenDevelopment sets the mode to Agent) remains unchanged.

name = "Startup Config"

[[panes]]
id = "main"
type = "agent"
cwd = "/absolute/path/to/dir"

Keyboard interaction

  • Enter: Activates "Get warping" (same as clicking the button).
  • Escape: Closes the modal without taking any action — the user lands on an empty terminal tab.
  • Arrow keys / Tab: Navigate between session type pills and checkboxes.

Dismissal

The modal can be dismissed by:

  • Clicking "Get warping" (takes action).
  • Pressing Escape (no action taken).
  • Clicking outside the modal (no action taken).
  • There is no explicit close/X button in the Figma.

Reusability

The modal's core logic (collecting session type, directory, worktree preference, save preference) should be a self-contained view that produces a structured output (e.g., a struct with all selected values). The caller decides what to do with that output. For the onboarding flow, the caller replaces the current tab and optionally writes a tab config. This makes the modal reusable in other contexts.

Success Criteria

  1. After completing onboarding, the modal appears overlayed on the terminal.
  2. Selecting "Terminal" + a directory + "Get warping" writes a tab config TOML to ~/.warp/tab_configs/ and replaces the current tab with a session in that directory.
  3. Selecting a CLI agent + a directory + "Get warping" writes a tab config TOML, replaces the current tab, sets the working directory, and auto-runs the agent CLI command.
  4. Selecting "Built in agent" + a directory + "Get warping" writes a tab config TOML, replaces the current tab, and opens Oz agent view in that directory.
  5. The written TOML appears in the + tab menu.
  6. The worktree checkbox is disabled when the selected directory is not a git repo, and enabled when it is.
  7. Checking worktree + save produces a TOML with {{worktree_branch_name}} params and worktree commands.
  8. File naming avoids collisions (appends _1, _2, etc.).
  9. Escape dismisses the modal without side effects.
  10. The modal does not appear again after the user completes it once (or dismisses via Escape).

Validation

  • Unit tests: TOML generation for each combination of session type × worktree × directory produces the expected output.
  • Manual testing: Walk through the full onboarding flow, verify the modal appears, select each session type, toggle worktree and save, confirm correct tab behavior.
  • Tab config integration: After saving, verify the config appears in the + menu, can be opened, and the params modal works for worktree configs.
  • UI verification: Compare the rendered modal against the Figma mock (session type pills, directory button, checkbox, CTA button).

Resolved Decisions

  1. Oz in tab config TOML: Oz uses type = "agent" on the pane node, which maps to PaneMode::Agent and causes the pane to enter agent view automatically. DefaultSessionMode is also set to Agent so future new tabs default to agent view. This must not break the existing behavior when the feature flag for this modal is disabled.
  2. Worktree base branch: The {{branch}} param is omitted. The git worktree add command uses HEAD implicitly (no base branch argument). The worktree branch name is hardcoded to "my-feature-branch" as a default. TODO(moira): Once worktree name generation is ready, replace the hardcoded "my-feature-branch" default with the generated name and revisit whether a base branch param should be added.
  3. Session type list: Hardcoded to Built in agent, Claude, Codex, Gemini, Terminal (in that order). Not dynamically derived from the CLIAgent enum.