feat(conductor): local-first conductor support#1362
Conversation
The wizard now explains that conductors work locally by default and gates all channel prompts (Telegram/Slack/Discord) behind a single "Add remote channels?" question that defaults to N. When no channels are configured the bridge and heartbeat daemon are not installed, and the "next steps" output focuses on TUI and CLI usage. Heartbeat is still installable in local-only mode via explicit --heartbeat flag for users who want periodic nudges without a bridge. 🤖 Generated with Claude Code
The conductor doesn't need to know HOW escalations reach the user. Whether via TUI or a remote channel bridge is transparent — the conductor asks its question and enters a waiting state. 🤖 Generated with Claude Code
…aming Merge docs/CONDUCTOR-SETUP.md and documentation/CONDUCTOR.md into a single authoritative guide at docs/conductor/README.md that leads with a two-minute local quickstart (no Telegram required). Channel-specific setup extracted into sibling files (telegram.md, slack.md, discord.md). All cross-references in README.md, WATCHER-SETUP.md, and SKILL.md updated. Images moved to docs/conductor/assets/. 🤖 Generated with Claude Code
- Fix wrong CLI command in local-only next-steps: `conductor send` → `session send` - Restructure heartbeat skip condition to positive form for readability - Extract yesAnswer() helper for repeated y/yes check pattern 🤖 Generated with Claude Code
The summary printed `Heartbeat: true` even when the heartbeat was skipped due to no remote channels being configured. Move the effective heartbeat decision to after the wizard completes so meta.json and the summary reflect whether the daemon will actually run. 🤖 Generated with Claude Code
The `--heartbeat=false` flag installed heartbeat anyway because fs.Visit set heartbeatExplicit=true regardless of the flag value. Replace with direct value checks so --no-heartbeat actually disables heartbeat. Update templates and docs to not assume remote channels (Telegram/Slack) are always present — local-first conductors interact via TUI/CLI. 🤖 Generated with Claude Code
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThe PR refactors the conductor setup command to gate remote-channel configuration behind an initial yes/no gateway prompt, tightens heartbeat enablement logic to respect explicit forcing and channel presence, updates post-setup guidance, adds three architecture diagrams, and aligns conductor instruction templates to describe direct user interaction via TUI/CLI/remote channels rather than legacy bridge forwarding. ChangesConductor Setup Refinement and Documentation
Conductor Instruction Template Updates
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested reviewers
🚥 Pre-merge checks | ✅ 6 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (6 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Replace opaque PNGs with d2 source files and rendered SVGs. Diagrams now reflect the local-first model: User connects via TUI/CLI (direct) or remote channels (optional). 🤖 Generated with Claude Code
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
internal/session/conductor_templates.go (1)
93-93: ⚡ Quick winConsider depersonalizing "the bridge" reference for local-only accuracy.
Line 93 states "The bridge parses your response" but in local-only mode (with
--heartbeatflag), there is no bridge—an OS daemon (launchd/systemd) triggers heartbeats and the conductor's output remains in the TUI/task-log. While the conductor's behavior is unchanged, the architectural description is imprecise.📝 Suggested rewording for architectural accuracy
-The bridge parses your response: if it contains ` + "`" + `NEED:` + "`" + ` lines, those get forwarded to the user (via remote channels if configured, or visible in the TUI/task-log). +Your response is parsed: if it contains ` + "`" + `NEED:` + "`" + ` lines, those get forwarded to the user (via remote channels if configured, or visible in the TUI/task-log).🤖 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 `@internal/session/conductor_templates.go` at line 93, Replace the phrase "The bridge parses your response" in the template (the exact string "The bridge parses your response: if it contains `NEED:` lines, those get forwarded to the user...") with a depersonalized description such as "Responses are parsed: if they contain `NEED:` lines, those get forwarded to the user (via remote channels if configured, or visible in the TUI/task-log)." Update the string in internal/session/conductor_templates.go so it no longer references "the bridge" but preserves the rest of the sentence and meaning.
🤖 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 `@cmd/agent-deck/conductor_cmd.go`:
- Around line 292-430: The gateway/channel prompt block must run not only when
settings.Enabled is false but also when the conductor is enabled yet has no
remote channels configured; move the entire prompt sequence (the code
interacting with reader and setting telegram/slack/discord and the boolean flags
telegramConfigured/slackConfigured/discordConfigured) out of the strict if
!settings.Enabled guard and wrap it in a condition like if !settings.Enabled ||
!(settings.TelegramConfigured || settings.SlackConfigured ||
settings.DiscordConfigured); after collecting answers, merge non-empty
session.TelegramSettings, session.SlackSettings, session.DiscordSettings back
into the existing settings object (updating settings.TelegramSettings,
settings.SlackSettings, settings.DiscordSettings and settings.Enabled as
appropriate) instead of creating new local-only values so the config persists
for later runs.
- Around line 147-148: printConductorHelp() still describes "setup <name>" as
creating a “bridge” and thus advertises the old pre-local-first behavior; update
the help strings inside printConductorHelp() (the function that prints the
top-level conductor --help) to reflect the new local-first behavior (replace
language like "create a bridge" with the new behavior description for setup
<name>) and scan other hard-coded help lines in that function to ensure they
match the updated setup subcommand text (including any mention of heartbeat or
remote channels).
- Around line 694-696: The printed CLI example for sending to a session omits
the profile flag, which will mis-target non-default profiles: update the usage
message that references sessionTitle so it includes the resolvedProfile flag
(use resolvedProfile and sessionTitle from this function) — replace the current
fmt.Printf that prints "agent-deck session send %s ..." with one that includes
"-p %s" before "session send" and formats both resolvedProfile and sessionTitle
accordingly so the example targets the same profile used to register the
conductor.
---
Nitpick comments:
In `@internal/session/conductor_templates.go`:
- Line 93: Replace the phrase "The bridge parses your response" in the template
(the exact string "The bridge parses your response: if it contains `NEED:`
lines, those get forwarded to the user...") with a depersonalized description
such as "Responses are parsed: if they contain `NEED:` lines, those get
forwarded to the user (via remote channels if configured, or visible in the
TUI/task-log)." Update the string in internal/session/conductor_templates.go so
it no longer references "the bridge" but preserves the rest of the sentence and
meaning.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: b4e0df03-fa36-4beb-816c-ef032ba2622c
⛔ Files ignored due to path filters (13)
README.mdis excluded by!**/*.mdconductor/conductor-claude.mdis excluded by!**/*.mddocs/CONDUCTOR-SETUP.mdis excluded by!**/*.mddocs/WATCHER-SETUP.mdis excluded by!**/*.mddocs/conductor/README.mdis excluded by!**/*.mddocs/conductor/assets/channels-topology.svgis excluded by!**/*.svgdocs/conductor/assets/conductor-overview.svgis excluded by!**/*.svgdocs/conductor/assets/fleet-topology.svgis excluded by!**/*.svgdocs/conductor/discord.mdis excluded by!**/*.mddocs/conductor/slack.mdis excluded by!**/*.mddocs/conductor/telegram.mdis excluded by!**/*.mddocumentation/CONDUCTOR.mdis excluded by!**/*.md,!documentation/**skills/agent-deck/SKILL.mdis excluded by!**/*.md
📒 Files selected for processing (5)
cmd/agent-deck/conductor_cmd.godocs/conductor/assets/channels-topology.d2docs/conductor/assets/conductor-overview.d2docs/conductor/assets/fleet-topology.d2internal/session/conductor_templates.go
- Add missing -p profile flag in local-only CLI example - Remove stale "bridge" reference in help and template text - Allow re-running setup to add channels when none configured 🤖 Generated with Claude Code
The channel-configured flags are now set after the merge logic at the end of the setup block, making the mid-wizard assignments dead code. 🤖 Generated with Claude Code
|
🤖 autopilot: CI green + Claude review clean; FLAGGED for local Codex dual-review before merge (data-sensitive area). This PR touches conductor template generation, heartbeat config writing, and Generated by Claude Code |
|
Maintainer design decision: local-first conductor support is an architectural direction call rather than a routine fix, so it's outside tonight's merge batch and awaiting maintainer sign-off. Labeled |
|
🤖 autopilot: CI is green, but this PR carries a Generated by Claude Code |
Summary
Make conductors work without remote channels (Telegram/Slack/Discord). A conductor is just a session — you interact with it in the TUI or via
session sendfrom the CLI. Remote channels become optional add-ons configured behind a setup gateway question.Changes
--heartbeatforce-enables it for local use.--no-heartbeatactually disables it (previously--heartbeat=falsewas ignored due to afs.Visitbug).docs/CONDUCTOR-SETUP.mdanddocumentation/CONDUCTOR.md, replaced withdocs/conductor/README.md(local-first framing) plus per-channel pages (telegram, slack, discord).Design decisions
condDircomputation moved inside channels-configured branch (dead code in local path).Test plan
go buildpassesgo test ./cmd/agent-deck/ -run Conductorpassesconductor setup local-test(answer N to channels) — clean output, no heartbeat installedconductor setup remote-testwith channels — heartbeat installed, bridge logs path shown--no-heartbeatflag actually disables heartbeat--heartbeatforce-enables heartbeat without channels🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Documentation