Skip to content

First Run

Z-M-Huang edited this page Apr 30, 2026 · 5 revisions

First Run

The first time a user invokes stud-cli on a fresh machine, they have no global scope set up: no provider configured, no extensions picked, no trust list. This flow covers how core reaches a runnable session without silently assuming on the user's behalf.

Covers two orthogonal first-run checks:

  1. Provider setup — global scope has no provider; core cannot compose a request. The bundled TUI walks the user through adding one.
  2. Project trust — the user launched inside a directory with <cwd>/.stud/ and the path is not on the global trust list. Core runs the standard Project Trust prompt.

Both checks run every startup; the first-run case is when both fire on the same invocation. Subsequent runs usually pass both checks silently.


Setup

  • Fresh machine. ~/.stud/ either does not exist or contains no provider config.
  • User invokes stud-cli in some working directory.
  • The machine has network access.
  • Core ships with the bundled TUI as the default subscriber + interactor UI and a bundled set of Provider extensions (see Providers contract).

Sequence

sequenceDiagram
    autonumber
    actor User
    participant CLI as stud-cli startup
    participant Core
    participant Settings as global settings<br/>(~/.stud/)
    participant Trust as trust list<br/>(~/.stud/)
    participant TUI as bundled TUI
    participant Prov as Provider
    participant Backend as LLM backend

    User->>CLI: "stud-cli"
    CLI->>Core: bootstrap
    Core->>Settings: load providers
    Settings-->>Core: none configured

    Core->>TUI: "InteractionRequest<br/>(Select: provider)"
    TUI->>User: list bundled providers
    User-->>TUI: pick provider
    TUI-->>Core: chosen provider

    Core->>TUI: "InteractionRequest<br/>(Select: auth path)"
    Note over Core,TUI: paths offered depend on what<br/>the chosen Provider's init drives
    TUI->>User: offer env-backed apiKeyRef /<br/>Auth.DeviceCode / Auth.Password
    User-->>TUI: pick path

    alt env-backed apiKeyRef
        TUI->>User: "Ask: env-var name"
        User-->>TUI: env name
        TUI-->>Core: env reference
    else Auth.DeviceCode / Auth.Password
        Core->>Prov: init
        Prov->>Core: drive Auth.DeviceCode or<br/>Auth.Password via Interaction Protocol
        Core->>TUI: render prompt (code + URL or password entry)
        User->>Backend: complete auth
        Backend-->>Prov: token
        Prov-->>Core: auth complete
    end

    Core->>Settings: ensure ~/.stud/ exists<br/>(if just created, scaffold system.md)
    Core->>Settings: write provider config<br/>(reference, never literal secret)

    Core->>Core: resolve project root (cwd/.stud)
    alt project/.stud exists
        Core->>Trust: lookup path
        Trust-->>Core: not listed
        Core->>TUI: run Project-Trust prompt<br/>(see dedicated flow)
        Note over Core,Trust: see Project First-Run Trust flow —<br/>outcome feeds the loader below
    else no project/.stud
        Note over Core: nothing to trust at project scope
    end

    Core->>Core: load bundled + global + (maybe) project
    Core->>Core: open session
    Core-->>TUI: ready
Loading

The two arms are independent: missing provider alone still runs the Project Trust check, and an already-configured provider still runs the Project Trust check when landing in a fresh project.


Provider setup detail

Provider setup writes to the global scope under ~/.stud/. It never writes to project scope — the project may not even be trusted yet.

Choosing a provider

The TUI lists every provider extension loaded from bundled + global scope. In a truly fresh setup only the bundled providers are visible. The user picks one by id.

Choosing an auth path

A Provider's config-schema (apiKeyRef behavior) and init code together determine which auth paths make sense for it — see Providers § Configuration schema and Providers § Lifecycle. The TUI offers only the paths the chosen provider supports; core does not invent an auth path the provider does not handle.

The paths bundled providers use:

Path What the TUI collects What is written to global settings
Env-backed apiKeyRef The name of an environment variable the user will export (e.g., OPENAI_API_KEY). A credential reference ({ kind: "env", name }) — the variable name — resolved at request time via the Env Provider. No literal secret is ever written to settings.
Literal API key The key value. Warned against. Core writes a literal only if the user insists; the warning cites Secrets Hygiene and recommends the env-backed path.
Auth.DeviceCode Nothing to type; the provider renders a code + URL through the Interaction Protocol. A token reference — resolved through the env provider or a provider-owned state slot. Never the literal token.
Auth.Password Password via secure input; the value never echoes and is never logged. A token reference, same rule.

The driving rule: the global settings.json never stores a resolved secret. Only references. Same rule the session manifest follows; see Secrets Hygiene.

Provider init

Providers that need interactive auth drive the Interaction Protocol from their init hook — see Providers § Lifecycle. In a fresh default setup, the bundled TUI is the only active interactor and answers those requests. A provider that cannot complete init (bad key, network failure, backend down) raises a validation diagnostic; the TUI shows it and offers the user a chance to retry or pick a different provider.

System-prompt scaffold

If the global config directory was just created in this run, core also writes the bundled default system.md into it. The trigger is directory-first-creation, not file existence — on every subsequent launch the directory already exists, and a system.md the user has since deleted stays gone. Failure semantics, audit event, and content categories are normative on SystemPromptFile § First-run scaffold; this flow does not restate them.


Project trust detail

Independent of provider setup. Runs whenever <cwd>/.stud/ exists and the path is not on the user-global trust list.

The prompt, the decision options, what is shown, and the re-prompt triggers are all normative on the Project Trust page. This flow does not restate them; the canonical sequence is Project First-Run Trust.

What matters here is the rule a first-run flow must honour:

No silent trust write. Entering a new project always prompts the user. The user's decision is the only thing that lands in the trust list.

Core never adds the current directory to the trust list "because stud-cli is running here". Launching stud-cli in a project .stud/ without a prior trust decision always opens the prompt.


What happens if the user declines or aborts

User action Effect
Abort provider setup Session does not start. Nothing is written. Next invocation re-runs the provider-setup prompt.
Decline project trust Session starts with bundled + global only. No project extensions, no project MCP, no project ordering-manifest. /tools and /providers still show the global set.
"Trust once" on project Project layer loads this session; nothing is written to the trust list. Next invocation in this path re-prompts.

A provider that fails its own init after the user completed the TUI flow (e.g., a typo in the env var name) surfaces as a validation diagnostic and the TUI offers to edit or re-pick. The session does not start with a broken provider.


Audit

Provider setup emits:

  • ProviderRegistered{id, protocol, authPath} — note: authPath (the shape chosen, e.g., env-api-key, Auth.DeviceCode, Auth.Password), not credentials.
  • ExtensionSetRevised if the provider rewrote settings.json.
  • SystemPromptScaffolded{path, byteCount} if the bundled default system.md was written during global-config-dir first creation. The content of the default is not duplicated into the audit record. See SystemPromptFile § First-run scaffold.

Project trust emits the records documented in Project First-Run Trust § Audit.

No audit record contains a resolved secret; see Audit Trail and Secrets Hygiene.


After the first run

On the next invocation:

  • If the user stays in the same directory, neither prompt fires — the provider is configured and the project is on the trust list.
  • If the user cd's into another fresh project, only the Project-Trust prompt fires.
  • If the user deletes ~/.stud/ or the provider stanza, the provider-setup prompt fires again. A fully deleted ~/.stud/ also re-arms the system-prompt scaffold, because the trigger is directory-first-creation; deleting only system.md does not.
  • Clearing the trust list re-arms the Project-Trust prompt for every project; see Project Trust § Re-prompt triggers.

Related pages

Introduction

Reading

Core runtime

Contracts

Category contracts

Context

Security

Runtime behavior

Operations

Providers (bundled)

Integrations

Reference extensions

Tools

UI

Session Stores

Loggers

Providers

Hooks

Context Providers

Commands

Case studies

Flows

Maintainers

Clone this wiki locally