Skip to content

refactor(min): unify interactive prompts on inquire with a brand theme - #1114

Merged
0chroma merged 4 commits into
mainfrom
refactor/unify-prompts-inquire
Jul 31, 2026
Merged

refactor(min): unify interactive prompts on inquire with a brand theme#1114
0chroma merged 4 commits into
mainfrom
refactor/unify-prompts-inquire

Conversation

@0chroma

@0chroma 0chroma commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Summary

The CLI had two prompt stacks: the session attach picker used inquire, the activation policy prompt used dialoguer. Both are single-select prompts, so this standardizes on inquire and drops dialoguer from the dependency tree. It also adds a process-wide prompt theme matching the website branding: monochrome, white on near-black with gray secondary text, no color accents.

Two picker legibility fixes ride along:

  • Unnamed sessions rendered as full UUIDs, making same-path rows indistinguishable; they now show (unnamed) · <id-prefix>, matching the dash TUI.
  • The keybind help line ([↑↓ to move, ...]) inherits the terminal default color, the same as the prompt message, instead of hard-to-read dark gray.

Changes

File Change
crates/minimal/src/theme.rs New module: monochrome RenderConfig (bold white selection, gray options, default-color help text), installed via inquire::set_global_render_config
crates/minimal/src/prompt.rs DialoguerPrompter becomes InquirePrompter behind the existing Prompter seam; filtering off for the fixed six-choice policy prompt (without_filtering()); UserChoice gains Display
crates/minimal/src/attach.rs Picker rows for unnamed sessions show a short id prefix instead of the full UUID
crates/minimal/src/lib.rs TTY probe uses std::io::IsTerminal instead of dialoguer::console; ActivationInterrupt docs updated
crates/minimal/src/main.rs Theme installed at startup
Cargo.toml, crates/minimal/Cargo.toml, Cargo.lock dialoguer removed
crates/sessions/docs/COMPOSITION.md References updated to inquire

One behavior note: inquire's crossterm backend captures Ctrl-C at a prompt as an error return instead of re-raising SIGINT, so dismissing the policy prompt now flows through the normal activation error path, which runs the abort cleanup. The SIGINT guard still covers the non-prompt phases.

Verification

  • cargo test -p minimal: 137 pass, including a new test for the short-id picker row.
  • cargo clippy -p minimal --all-targets -- -D warnings: clean.
  • cargo fmt --all -- --check: clean.
  • dialoguer no longer appears in Cargo.lock.

Summary by CodeRabbit

  • New Features
    • Updated interactive prompts with improved keyboard handling and consistent monochrome styling.
    • Added clearer prompt behavior for terminal and non-terminal environments.
    • Applied the prompt theme consistently when the application starts.
  • Bug Fixes
    • Improved interrupt handling for interactive prompts and non-prompt phases.
    • Simplified unnamed session labels by showing a shortened identifier.
  • Documentation
    • Updated session composition guidance to reflect current prompt and keypress behavior.

The session attach picker used inquire while the activation policy
prompt used dialoguer. Both are single-select prompts, so standardize
on inquire: the policy prompt moves behind the existing Prompter seam,
the TTY probe switches to std::io::IsTerminal, and dialoguer leaves the
dependency tree. A new theme module installs a monochrome inquire
RenderConfig (white on near-black, gray secondary text) matching the
website branding, applied process-wide at startup. Filtering stays on
for the attach picker but off for the fixed six-choice policy prompt.

Ctrl-C at the policy prompt no longer re-raises SIGINT (inquire's
crossterm backend captures it as an error return), so prompt dismissal
now flows through the normal activation error path; the SIGINT guard
still covers the non-prompt phases.
@0chroma
0chroma requested a review from a team as a code owner July 30, 2026 23:56
@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 18 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7d9cd344-e368-4a64-9b34-c9b83de561f9

📥 Commits

Reviewing files that changed from the base of the PR and between 257ceda and 352b789.

📒 Files selected for processing (1)
  • crates/minimal/src/lib.rs
📝 Walkthrough

Walkthrough

The minimal CLI replaces dialoguer with inquire, adds a globally installed monochrome prompt theme, updates terminal detection and startup initialization, revises related documentation, and shortens unnamed session labels to the first UUID segment.

Changes

Minimal CLI updates

Layer / File(s) Summary
Prompt backend and theme
Cargo.toml, crates/minimal/src/{lib.rs,main.rs,prompt.rs,theme.rs}
Interactive selection now uses inquire::Select, UserChoice implements Display, the global monochrome theme is installed before tracing setup, and the shared dialoguer dependency is removed.
Terminal detection and documentation
crates/minimal/src/lib.rs, crates/sessions/docs/COMPOSITION.md
Prompt eligibility checks stdin and stderr terminal status, while interrupt and TTY documentation reflects inquire behavior.
Unnamed session display formatting
crates/minimal/src/attach.rs
Unnamed session labels show (unnamed) with only the first UUID segment, covered by a test.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested reviewers: twitchyliquid64, norrietaylor, msample

Poem

I’m a bunny with prompts bright,
Inquire guides my hops just right.
Gray options bloom, the cursor gleams,
Short names tidy session dreams.
Hop, hop—cleaner CLI streams!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly and concisely summarizes the primary change: standardizing interactive prompts on inquire with a shared theme.
Description check ✅ Passed The description thoroughly covers the changes and verification results, though it omits the template checklist section.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/unify-prompts-inquire

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/minimal/src/theme.rs`:
- Around line 9-24: Use RenderConfig::empty() instead of RenderConfig::default()
when initializing config, while preserving the existing explicit monochrome
style overrides and placeholder assignment.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6f1ac066-0c72-4f5a-bebf-1182a7d09f8b

📥 Commits

Reviewing files that changed from the base of the PR and between 957c076 and 37d1dcc.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (7)
  • Cargo.toml
  • crates/minimal/Cargo.toml
  • crates/minimal/src/lib.rs
  • crates/minimal/src/main.rs
  • crates/minimal/src/prompt.rs
  • crates/minimal/src/theme.rs
  • crates/sessions/docs/COMPOSITION.md
💤 Files with no reviewable changes (2)
  • Cargo.toml
  • crates/minimal/Cargo.toml

Comment thread crates/minimal/src/theme.rs Outdated
Comment on lines +9 to +24
let mut config = RenderConfig::default()
.with_prompt_prefix(Styled::new("▸").with_fg(Color::White))
.with_highlighted_option_prefix(Styled::new("▸").with_fg(Color::White))
.with_selected_option(Some(
StyleSheet::new()
.with_fg(Color::White)
.with_attr(Attributes::BOLD),
))
.with_option(StyleSheet::new().with_fg(Color::Grey))
.with_answer(
StyleSheet::new()
.with_fg(Color::White)
.with_attr(Attributes::BOLD),
)
.with_help_message(StyleSheet::new().with_fg(Color::DarkGrey));
config.placeholder = StyleSheet::new().with_fg(Color::DarkGrey);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- relevant files ---'
git ls-files | rg '(^|/)(Cargo.toml|Cargo.lock|rust-toolchain.toml|theme\.rs)$'
printf '%s\n' '--- theme source ---'
f=$(git ls-files 'crates/minimal/src/theme.rs')
cat -n "$f"
printf '%s\n' '--- inquire dependency declarations ---'
rg -n -C 3 '(^|[^[:alnum:]_])inquire([^[:alnum:]_]|$)' --glob 'Cargo.toml' --glob 'Cargo.lock'
printf '%s\n' '--- local inquire sources, if vendored ---'
git ls-files | rg '(^|/)inquire(/|$)' || true

Repository: gominimal/minimal

Length of output: 2750


🌐 Web query:

inquire RenderConfig default empty source version-specific unhighlighted option prefix answered prompt prefix

💡 Result:

In the context of the Rust library inquire, RenderConfig is a struct used to customize the visual appearance of prompts [1][2]. The configuration options you mentioned are specific fields within this struct: unhighlighted_option_prefix: This field allows you to customize the prefix used for options in Select and MultiSelect prompts that are not currently highlighted [2][3]. It is defined as a Styled<&'a str> [1][2]. answered_prompt_prefix: This field allows you to set a custom prefix (such as a check mark) for prompts that have already been answered [3]. Regarding the "default" and "empty" source configurations: RenderConfig::empty returns a RenderConfig instance where no colors or attributes are applied (essentially a baseline configuration) [1][4]. RenderConfig::default returns a RenderConfig instance with standard default colors and attributes applied [4]. You can customize these by using methods like with_highlighted_option_prefix or by manually creating a RenderConfig instance [1][5]. When using prefix options, note that the library typically adds a space character automatically to separate the prefix from the option value [1][5][2].

Citations:


🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- workspace and minimal manifests ---'
cat -n Cargo.toml | sed -n '1,180p'
cat -n crates/minimal/Cargo.toml | sed -n '1,180p'
printf '%s\n' '--- locked inquire package ---'
awk '
  /^\[\[package\]\]/ { block=0 }
  /^\[\[package\]\]/ { block=1; buf=$0 "\n"; next }
  block { buf=buf $0 "\n" }
  block && /^name = "inquire"$/ { print buf; block=0 }
' Cargo.lock
printf '%s\n' '--- all inquire references ---'
rg -n -i 'inquire|render_config|unhighlighted_option_prefix|answered_prompt_prefix' --glob '!target/**' .

Repository: gominimal/minimal

Length of output: 14783


🏁 Script executed:

#!/bin/bash
set -eu
python3 - <<'PY'
import json, urllib.request
for url in [
    "https://raw.githubusercontent.com/mikael-mello/inquire/main/src/ui/render_config.rs",
    "https://api.github.com/repos/mikaelmello/inquire/contents/src/ui/render_config.rs",
]:
    print("URL", url)
    try:
        with urllib.request.urlopen(url, timeout=15) as r:
            data = r.read().decode()
        print(data[:30000])
    except Exception as e:
        print(type(e).__name__, e)
PY

Repository: gominimal/minimal

Length of output: 617


🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- Cargo.lock inquire entry ---'
sed -n '2908,2945p' Cargo.lock
printf '%s\n' '--- inquire RenderConfig source at likely v0.9 tags ---'
for tag in v0.9.0 v0.9.1 v0.9.2 v0.9.3 v0.9.4 v0.9.5; do
  url="https://raw.githubusercontent.com/mikaelmello/inquire/$tag/src/ui/render_config.rs"
  body="$(curl -kfsSL "$url" 2>/dev/null || true)"
  if [ -n "$body" ]; then
    printf '\n### %s\n' "$tag"
    printf '%s\n' "$body" | sed -n '1,260p'
  fi
done

Repository: gominimal/minimal

Length of output: 1119


🏁 Script executed:

#!/bin/bash
set -eu
tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT
curl -kfsSL "https://crates.io/api/v1/crates/inquire/0.9.4/download" -o "$tmp/inquire.tgz"
tar -xzf "$tmp/inquire.tgz" -C "$tmp"
src="$tmp/inquire-0.9.4"
printf '%s\n' '--- RenderConfig symbols ---'
rg -n -C 8 'struct RenderConfig|impl.*RenderConfig|fn empty|fn default|unhighlighted_option_prefix|answered_prompt_prefix|highlighted_option_prefix' "$src/src"
printf '%s\n' '--- relevant source ---'
f="$src/src/ui/render_config.rs"
if [ -f "$f" ]; then cat -n "$f" | sed -n '1,320p'; else find "$src/src" -type f -maxdepth 4 -print; fi

Repository: gominimal/minimal

Length of output: 257


🏁 Script executed:

#!/bin/bash
set -eu
python3 - <<'PY'
import io, ssl, tarfile, urllib.request
url = "https://crates.io/api/v1/crates/inquire/0.9.4/download"
ctx = ssl._create_unverified_context()
with urllib.request.urlopen(url, context=ctx, timeout=30) as r:
    archive = r.read()
with tarfile.open(fileobj=io.BytesIO(archive), mode="r:gz") as t:
    names = t.getnames()
    candidates = [n for n in names if n.endswith(("render_config.rs", "api.rs"))]
    print("archive members:", len(names))
    for name in candidates:
        print(f"\n--- {name} ---")
        text = t.extractfile(name).read().decode()
        lines = text.splitlines()
        for i, line in enumerate(lines):
            if any(x in line for x in (
                "struct RenderConfig", "impl Default for RenderConfig",
                "fn empty", "fn default", "unhighlighted_option_prefix",
                "answered_prompt_prefix", "highlighted_option_prefix",
            )):
                lo, hi = max(0, i-8), min(len(lines), i+55)
                print("\n".join(f"{j+1:4}: {lines[j]}" for j in range(lo, hi)))
PY

Repository: gominimal/minimal

Length of output: 50375


Use RenderConfig::empty() as the base.

RenderConfig::default() retains colored defaults for unoverridden fields such as answered_prompt_prefix and unhighlighted_option_prefix, so this theme is not fully monochrome.

Proposed fix
-    let mut config = RenderConfig::default()
+    let mut config = RenderConfig::empty()
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let mut config = RenderConfig::default()
.with_prompt_prefix(Styled::new("▸").with_fg(Color::White))
.with_highlighted_option_prefix(Styled::new("▸").with_fg(Color::White))
.with_selected_option(Some(
StyleSheet::new()
.with_fg(Color::White)
.with_attr(Attributes::BOLD),
))
.with_option(StyleSheet::new().with_fg(Color::Grey))
.with_answer(
StyleSheet::new()
.with_fg(Color::White)
.with_attr(Attributes::BOLD),
)
.with_help_message(StyleSheet::new().with_fg(Color::DarkGrey));
config.placeholder = StyleSheet::new().with_fg(Color::DarkGrey);
let mut config = RenderConfig::empty()
.with_prompt_prefix(Styled::new("▸").with_fg(Color::White))
.with_highlighted_option_prefix(Styled::new("▸").with_fg(Color::White))
.with_selected_option(Some(
StyleSheet::new()
.with_fg(Color::White)
.with_attr(Attributes::BOLD),
))
.with_option(StyleSheet::new().with_fg(Color::Grey))
.with_answer(
StyleSheet::new()
.with_fg(Color::White)
.with_attr(Attributes::BOLD),
)
.with_help_message(StyleSheet::new().with_fg(Color::DarkGrey));
config.placeholder = StyleSheet::new().with_fg(Color::DarkGrey);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/minimal/src/theme.rs` around lines 9 - 24, Use RenderConfig::empty()
instead of RenderConfig::default() when initializing config, while preserving
the existing explicit monochrome style overrides and placeholder assignment.

DarkGrey help messages and placeholders were near-invisible on the
near-black terminal backgrounds the theme targets.
@norrietaylor

Copy link
Copy Markdown
Member

Niiiiiicee!

Unnamed sessions in the attach picker rendered as full UUIDs, so
same-path rows were indistinguishable; they now show `(unnamed) ·
<id-prefix>` like the dash TUI. The prompt help line now inherits the
terminal default color, matching the prompt message.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/minimal/src/attach.rs`:
- Around line 486-503: Add a regression test alongside
unnamed_session_shows_short_id_not_full_uuid that creates two unnamed entries
with IDs sharing the same initial segment, renders both through
format_candidate, and asserts their labels are different. Preserve the existing
short-ID truncation assertions while verifying colliding IDs receive distinct
rendered labels.
- Around line 140-149: The unnamed-session label logic in format_candidate must
produce collision-safe labels instead of using only the first UUID segment;
derive the shortest prefix that uniquely identifies each candidate or retain
sufficient ID text. In crates/minimal/src/attach.rs lines 140-149, update
format_candidate and its callers as needed to use the candidate set for
uniqueness. In crates/minimal/src/attach.rs lines 486-503, add two unnamed
sessions sharing a first UUID segment and assert their rendered labels differ.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 821ee04e-10a1-4dbf-83be-0e8b61ae7696

📥 Commits

Reviewing files that changed from the base of the PR and between f778cc7 and 257ceda.

📒 Files selected for processing (2)
  • crates/minimal/src/attach.rs
  • crates/minimal/src/theme.rs

Comment on lines +140 to +149
/// a glance even in the "pick over all sessions" case. Unnamed sessions
/// render as `(unnamed) · <id-prefix>` — the first id segment is enough to
/// tell same-path rows apart without a full UUID.
fn format_candidate(entry: &ListSessionsEntry, cwd: &paths::HostAbsPath) -> String {
let glyph = state_glyph(entry.status);
let name = entry.name.clone().unwrap_or_else(|| entry.id.to_string());
let name = entry.name.clone().unwrap_or_else(|| {
let id = entry.id.to_string();
let short = id.split('-').next().unwrap_or(&id);
format!("(unnamed) · {short}")
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Make shortened unnamed-session labels collision-safe.

The first UUID segment is not guaranteed to distinguish sessions; the provided fixtures already contain IDs sharing that segment. Ensure labels remain unique, then add coverage for two IDs with a shared first segment.

  • crates/minimal/src/attach.rs#L140-L149: derive a unique prefix from the candidate set or retain enough ID text to distinguish every row.
  • crates/minimal/src/attach.rs#L486-L503: add two unnamed sessions with colliding prefixes and assert their labels differ.
📍 Affects 1 file
  • crates/minimal/src/attach.rs#L140-L149 (this comment)
  • crates/minimal/src/attach.rs#L486-L503
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/minimal/src/attach.rs` around lines 140 - 149, The unnamed-session
label logic in format_candidate must produce collision-safe labels instead of
using only the first UUID segment; derive the shortest prefix that uniquely
identifies each candidate or retain sufficient ID text. In
crates/minimal/src/attach.rs lines 140-149, update format_candidate and its
callers as needed to use the candidate set for uniqueness. In
crates/minimal/src/attach.rs lines 486-503, add two unnamed sessions sharing a
first UUID segment and assert their rendered labels differ.

Comment on lines +486 to +503

#[test]
fn unnamed_session_shows_short_id_not_full_uuid() {
let e = entry(
"019f5d0f-0a99-78b1-9165-0809440f0052",
"/a",
SessionStatus::Active,
);
let label = format_candidate(&e, &cwd("/a"));
assert!(
label.contains("(unnamed) · 019f5d0f"),
"short id form: {label}"
);
assert!(
!label.contains("0a99-78b1"),
"full uuid must not appear: {label}"
);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Add a regression test for colliding short IDs.

This test covers truncation for one session but does not catch duplicate labels. Add two unnamed entries whose IDs share the first segment and assert their rendered labels differ.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/minimal/src/attach.rs` around lines 486 - 503, Add a regression test
alongside unnamed_session_shows_short_id_not_full_uuid that creates two unnamed
entries with IDs sharing the same initial segment, renders both through
format_candidate, and asserts their labels are different. Preserve the existing
short-ID truncation assertions while verifying colliding IDs receive distinct
rendered labels.

@0chroma
0chroma enabled auto-merge (squash) July 31, 2026 00:19
@0chroma
0chroma merged commit 019d7c4 into main Jul 31, 2026
30 checks passed
@0chroma
0chroma deleted the refactor/unify-prompts-inquire branch July 31, 2026 00:29
norrietaylor added a commit that referenced this pull request Jul 31, 2026
Un-clobber the theme module, TTY predicate, and doc comments the stale
base reverted, and complete the issue's second half: min daemon stop is
canonical with min stop kept as the visible top-level alias, mirroring
the session list / ls pattern.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KyZLpkRf9G4A2hUDgDvn5f
norrietaylor added a commit that referenced this pull request Jul 31, 2026
The upload-gate change was authored against a pre-#1114 file state and
reverted the theme module, the TTY predicate, and two doc comments.
Restore main's versions; the gate logic is untouched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KyZLpkRf9G4A2hUDgDvn5f
norrietaylor added a commit that referenced this pull request Jul 31, 2026
* fix(minimal): skip non-VCS-root upload in headless activate

A headless `min session activate` (--no-prompt, --no-input, or a
non-TTY) from a directory that is not a VCS root uploaded the whole
directory with no confirmation, because the non-VCS-root gate treated
the impossibility of a prompt as consent.

Split the gate's TTY-free decision into `file_upload::upload_gate` and
invert the headless arm: a headless caller with an implicit --sync now
skips the upload and warns on stderr with the `--sync tarball` escape
hatch, starting the session with an empty workspace. A VCS root or an
explicit --sync tarball still uploads; the interactive confirm (default
No) is unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix: restore #1114 prompt unification clobbered by a stale base

The upload-gate change was authored against a pre-#1114 file state and
reverted the theme module, the TTY predicate, and two doc comments.
Restore main's versions; the gate logic is untouched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KyZLpkRf9G4A2hUDgDvn5f

---------

Co-authored-by: gominimal-aw-bot[bot] <281738952+gominimal-aw-bot[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Norrie Taylor <norrie@minimal.dev>
norrietaylor added a commit that referenced this pull request Jul 31, 2026
)

* fix(min): add canonical `min session list` command

`min session list` did not exist: `SessionCommand` had no `List`
variant, so the guessable `<noun> list` form of the flagship session
noun errored under clap where every other noun (e.g. `min loadout
list`) accepts it.

Add `SessionCommand::List`, delegating to the existing `cmd_ls` so
output is byte-identical, with `ls` as a visible noun-level alias.
`min ls` keeps its bare top-level form as a visible alias. Docs now
present `min session list` as canonical.

* fix: restore #1114 content and add the daemon-stop half

Un-clobber the theme module, TTY predicate, and doc comments the stale
base reverted, and complete the issue's second half: min daemon stop is
canonical with min stop kept as the visible top-level alias, mirroring
the session list / ls pattern.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KyZLpkRf9G4A2hUDgDvn5f

* refactor(minimal): drop the daemon-noun stop spelling from this change

Keep the PR to the session-list half: `min session list` canonical with
`min ls`/`min session ls` as visible aliases. `min stop` stays the bare
top-level command it is on main, unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KyZLpkRf9G4A2hUDgDvn5f

---------

Co-authored-by: gominimal-aw-bot[bot] <281738952+gominimal-aw-bot[bot]@users.noreply.github.com>
Co-authored-by: Norrie Taylor <norrie@minimal.dev>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Norrie Taylor <91171431+norrietaylor@users.noreply.github.com>
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