Skip to content

feat(tui): add Config tab and surface daemon staleness on the Dashboard - #189

Merged
chrisleekr merged 2 commits into
mainfrom
feat/tui-config
Jun 20, 2026
Merged

feat(tui): add Config tab and surface daemon staleness on the Dashboard#189
chrisleekr merged 2 commits into
mainfrom
feat/tui-config

Conversation

@chrisleekr

@chrisleekr chrisleekr commented Jun 20, 2026

Copy link
Copy Markdown
Owner

Why

The TUI was sold as "the fastest way in" but couldn't change a single setting — toggling an agent or tuning the daemon meant hand-editing agentsync.toml in the vault. And the daemon health it showed didn't surface the last-sync/stuck signals PR #188 added. This makes the UI configurable (the headline ask) and surfaces the reliability work.

Sixth and final PR in the series (follows #184, #185, #186, #187, #188).

What

  • New Config tab (6) — view and change agents.*, sync.*, claudePlugins.*, and security.* with ↑↓ to move, space to toggle a boolean, ←→ to cycle an enum (secretScan) or adjust a number (debounceMs, ±50 clamped). Every write goes through the same performConfigSet core as agentsync config set (reconcile + commit + push) — no forked logic, honoring the "TUI reuses command logic" invariant. The tab also lists the recipients who can decrypt the vault read-only (surfacing key list).
  • Dashboard daemon health — now shows the last successful sync age and a loud red ⚠ STUCK banner when the vault diverged, read from the daemon's IPC status (the fields PR feat(daemon): durable health state, divergence escalation, staleness checks, watcher pre-filter #188 added).

Scope note

This PR delivers the explicit "make the UI configurable" requirement plus the daemon-health surfacing and the recipient list. The in-TUI init wizard and Machines per-artifact diff/selective-copy are larger interactive-input features (free-text modals, a new diff surface) and are left as clear follow-ups; the Dashboard already points to agentsync init for first-run, and the Machines tab's whole-namespace copy is unchanged.

Review fixes (caught in senior review)

The first cut guarded the un-init case with a stat, but loadVaultConfigOrExit also process.exits on a v1/unsupported vault — which would have killed the entire TUI. Replaced with a peekVaultVersion check that throws a catchable error (rendered as a tab error state), which also makes the edit path unreachable on a bad vault. Plus: a concurrency guard so two rapid edits can't race the git working tree; DaemonStatusSchema timestamps tightened to ISO datetime() so a malformed value can't render "NaN ago"; enum cycle handles an out-of-options current value.

Tests

config-tab.test.ts (11): navigation + bounds, read-only no-op, lower-bound number clamp, load (rows + recipients + kinds), error-not-crash on un-init vault, and edits persisting through performConfigSet (toggle boolean, cycle enum both directions, adjust number). Full suite: 976 pass / 0 fail.

CI note

bun test exits non-zero on the per-file coverage floor; CI treats 0-fail as success.

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Added a new "Config" tab to the TUI for viewing and modifying settings
    • Dashboard now displays the timestamp of the last successful sync and shows alerts when the vault is stuck or diverged
  • Documentation

    • Updated documentation and README to reflect the new Config tab and revised global key mappings for tab navigation (now supporting tabs 1–6)

@coderabbitai

coderabbitai Bot commented Jun 20, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@chrisleekr, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 51 minutes and 7 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

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 credits.

🚦 How do rate limits work?

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

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, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: aaed2451-4bbf-48cd-b02d-3d5193398b33

📥 Commits

Reviewing files that changed from the base of the PR and between 2959a5c and 368a4b7.

📒 Files selected for processing (1)
  • src/commands/tui/app.ts
📝 Walkthrough

Walkthrough

A new "Config" tab is added to the TUI, backed by new state types (ConfigSlice, ConfigRow, ConfigRowKind), a full tab implementation (ensureConfigLoaded, onConfigKey, renderConfig, setConfig), and wiring into app.ts. The Dashboard gains stuck-state display derived from lastSuccessAt. DaemonStatusSchema timestamps are tightened to ISO datetime. Tests, docs, and CLAUDE.md are updated accordingly.

Changes

TUI Config Tab + Dashboard Stuck State

Layer / File(s) Summary
Config tab state model and schema tightening
src/commands/tui/state.ts, src/config/schema.ts
Adds ConfigRowKind, ConfigRow, ConfigSlice interfaces; extends TAB_IDS with "config" and OpKind with "config-load"/"config-set"; initializes the config slice in createInitialState(); tightens DaemonStatusSchema timestamp fields to z.string().datetime().
Config tab load, edit, key handling, and rendering
src/commands/tui/tabs/config.ts
Implements ensureConfigLoaded (vault version probe, concurrent config/recipients load, row classification), setConfig (in-flight guard, performConfigSet call, row update), onConfigKey (cursor navigation, boolean toggle, enum cycle, number bounds adjustment), formatValue, editHintFor, and renderConfig.
App wiring: tab registration, delegation, rendering, help, context actions
src/commands/tui/app.ts
Imports and wires the config tab into TAB_LABELS, delegateTabKey, actionLabelFor, renderActiveTab, the help overlay, and contextActionsForTab.
Dashboard stuck state and Config menu entry
src/commands/tui/tabs/dashboard.ts
Derives lastSync and stuck from DaemonStatus; adds conditional "⚠ STUCK" warning with dynamic box height and border color; appends [6] Config to the hint panel.
Config tab tests and documentation
src/commands/tui/__tests__/config-tab.test.ts, README.md, docs/commands.md, CLAUDE.md
Adds Bun tests covering cursor navigation bounds, read-only row behavior, boolean/enum/number persistence, and error-case handling; updates README, commands.md (Dashboard stuck docs, tab 6 shortcut, Config outcome note), and CLAUDE.md (core function wiring list).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • chrisleekr/agentsync#102: Touches the same actionLabelFor/key-hinting plumbing in app.ts and AppState fields in state.ts that this PR extends with Config tab entries.
  • chrisleekr/agentsync#109: Modifies tab-switching logic in app.ts that this PR extends by adding the config case to the same switch structures.
  • chrisleekr/agentsync#185: Introduces the performConfigSet core command that the new Config tab's setConfig delegates to.

Suggested labels

bot:resolve

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 38.89% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately captures the two main changes: adding a Config tab and surfacing daemon staleness on the Dashboard.
Description check ✅ Passed The description is comprehensive and well-structured, covering all template sections including summary, changes, test evidence, and risks/follow-ups, with clear rationale and implementation details.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@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 `@src/commands/tui/app.ts`:
- Around line 663-668: The global help shortcut range in the help overlay needs
to be updated to account for the newly added Config tab. Locate the "Global
keys" section in the help text (around the area mentioned in the comment) and
find where it currently states the tab range as "1 – 5". Change this to "1 – 6"
to accurately reflect all available tabs including the new Config tab that was
added.
🪄 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: ASSERTIVE

Plan: Pro

Run ID: 6419b8b7-1da2-4919-b8f4-1e8fdd78034c

📥 Commits

Reviewing files that changed from the base of the PR and between ff845c8 and 2959a5c.

📒 Files selected for processing (9)
  • CLAUDE.md
  • README.md
  • docs/commands.md
  • src/commands/tui/__tests__/config-tab.test.ts
  • src/commands/tui/app.ts
  • src/commands/tui/state.ts
  • src/commands/tui/tabs/config.ts
  • src/commands/tui/tabs/dashboard.ts
  • src/config/schema.ts

Comment thread src/commands/tui/app.ts
@chrisleekr
chrisleekr merged commit 1a07530 into main Jun 20, 2026
24 checks passed
@chrisleekr
chrisleekr deleted the feat/tui-config branch June 20, 2026 08:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant