Skip to content

Integrate Shelley coding agent as local sidecar#3

Open
acoyfellow wants to merge 6 commits into
mainfrom
claude/review-app-prep-cy6hM
Open

Integrate Shelley coding agent as local sidecar#3
acoyfellow wants to merge 6 commits into
mainfrom
claude/review-app-prep-cy6hM

Conversation

@acoyfellow
Copy link
Copy Markdown
Owner

Summary

This PR integrates Shelley, a local coding agent, as a bundled sidecar process into t2t. When users hold fn+ctrl to enter agent mode, their voice commands are now routed to Shelley first, with fallback to MCP servers and AppleScript if Shelley is unavailable.

Key Changes

  • Shelley sidecar integration: Added startup/shutdown logic for the Shelley binary, which runs on a dynamically allocated local port
  • Agent mode routing: Modified the Fn+Ctrl handler to prioritize Shelley, then fall back to MCP servers, then AppleScript
  • Chat UI tab: Added a new "Chat" settings tab that embeds Shelley's web interface via iframe
  • Visual feedback: Orange status bar with sweep animation indicates Shelley is working; clicking it opens the Chat tab
  • Binary management: Added fetch-shelley.sh script to download pre-built Shelley binaries or build from source via go install
  • Tauri shell plugin: Added tauri-plugin-shell to enable spawning the Shelley sidecar process
  • API integration: Shelley receives ANTHROPIC_API_KEY and OPENROUTER_API_KEY via environment variables; database stored in app data dir
  • Documentation: Updated README with simplified getting started, new usage sections for Shelley, and reference tables for status colors, environment variables, and file locations

Implementation Details

  • Shelley is started automatically on app launch via start_shelley() and stopped on exit
  • Port discovery uses find_available_port() to bind to an available TCP port
  • Voice transcripts are sent to Shelley's HTTP API (POST /conversations and POST /conversation/{id}/chat)
  • Synchronous send_to_shelley_sync() is used in the Fn key handler thread; async send_to_shelley() is available for Tauri commands
  • Status bar color changes to orange (#f97316) with a CSS sweep animation when Shelley is active
  • Pressing Escape dismisses the Shelley indicator; clicking the orange bar opens the Chat tab
  • History entries for Shelley calls include conversation ID and Shelley URL for reference
  • Fallback chain ensures graceful degradation if Shelley is unavailable

Files Modified

  • .gitignore: Ignore Shelley binaries
  • README.md: Comprehensive rewrite with new structure and Shelley documentation
  • desktop/Cargo.toml: Added tauri-plugin-shell
  • desktop/package.json: Added @tauri-apps/plugin-shell
  • desktop/capabilities/default.json: Added shell spawn permissions
  • desktop/tauri.conf.json: Configured Shelley as external binary
  • desktop/src/main.rs: Shelley lifecycle, HTTP client integration, Tauri commands
  • desktop/src/routes/+page.svelte: Orange bar, sweep animation, click-to-chat handler
  • desktop/src/routes/settings/+page.svelte: Chat tab with Shelley iframe
  • desktop/src/lib/components/Nav.svelte: Added "chat" tab type
  • web/src/routes/docs/+page.svelte: Updated visual feedback and agent mode docs
  • desktop/scripts/fetch-shelley.sh: New script for binary management
  • desktop/binaries/.gitkeep: New directory for bundled binaries

https://claude.ai/code/session_019BM8jk4dqoSyrfzrwNAMj3

acoyfellow and others added 6 commits December 29, 2025 19:14
- Enabled window decorations in the Tauri configuration for a more polished UI.
- Refactored screenshot capture logic to streamline handling for vision-capable models.
- Removed redundant image generation model checks from various components to simplify code.
- Enhanced navigation component styles for better visual consistency.
- Revised sections to reflect the new vision capabilities, emphasizing automatic screenshot capture for all agent calls.
- Changed terminology from "image generation models" to "vision support" for clarity.
- Removed outdated references to model-specific screenshot behavior and added details on universal support and privacy measures.
- Updated UI descriptions in the README to align with recent changes in functionality.
Ship Shelley (boldsoftware/shelley) inside the t2t app as a Tauri sidecar
binary. Adds a "Chat" tab in the settings window that embeds Shelley's web UI
via iframe, and routes fn+ctrl agent mode through Shelley when running (falling
back to MCP/AppleScript agents if Shelley is unavailable).

- Add Chat tab with MessageCircle icon to Nav and settings page
- Configure Tauri externalBin for shelley sidecar binary
- Add shell plugin for sidecar process management
- Rust: spawn Shelley on app start, kill on exit, health check API
- Pass ANTHROPIC_API_KEY/OPENROUTER_API_KEY to Shelley via env vars
- SQLite database stored in app data dir (shelley.db)
- fn+ctrl now tries Shelley first, opens Chat tab on success
- Add send_to_shelley command for programmatic conversation creation

https://claude.ai/code/session_019BM8jk4dqoSyrfzrwNAMj3
Visual feedback flow for Shelley agent mode:
- fn held → green bar (typing mode, existing)
- fn+ctrl held → purple bar (agent mode, existing)
- Release → amber bar (transcribing, existing)
- Shelley dispatched → orange bar with sweeping light animation
- Orange bar persists until user clicks it → opens Chat tab
- Escape also dismisses the Shelley indicator

Key changes:
- shelleyActive state: independent of processing, persists after HTTP POST
  returns since Shelley works asynchronously in background
- Orange bar (#f97316) with animated sweep distinguishes from amber processing
- Bar becomes clickable (pointer-events enabled) during agent processing
- open_chat_window Tauri command: opens settings window, switches to Chat tab
- fetch-shelley.sh: auto-download script for the Shelley binary
- .gitignore: exclude large Shelley binary from repo

https://claude.ai/code/session_019BM8jk4dqoSyrfzrwNAMj3
README: restructured as tutorial → how-to → reference → dev setup.
Removed explanation bloat (vision technical details, history schema,
screenshot encoding). Added Shelley, Chat tab, correct status bar
colors, updated agent fallback chain, env vars table, file locations.

docs/+page.svelte: fixed red→green bar, cyan→purple bar, added Shelley
as primary agent with MCP/AppleScript as fallbacks, documented orange
sweep animation and clickable bar behavior.

https://claude.ai/code/session_019BM8jk4dqoSyrfzrwNAMj3
Wrap set_activation_policy calls in open_chat_window and tray menu
handler with #[cfg(target_os = "macos")] so the build compiles on Linux.

https://claude.ai/code/session_019BM8jk4dqoSyrfzrwNAMj3
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9668184096

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +771 to +772
if (result.running && result.port) {
shelleyUrl = `http://localhost:${result.port}`;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Honor Shelley health errors before loading chat iframe

get_shelley_status can report running: true with an error when the port is not ready yet, but this branch treats any running && port as healthy and immediately loads http://localhost:<port>. In that startup window the iframe points at an unavailable endpoint, so users see a broken embedded page instead of the intended “starting up”/error state and retry flow.

Useful? React with 👍 / 👎.

Comment thread desktop/src/main.rs

let conv_id = conv.get("conversation_id")
.or_else(|| conv.get("id"))
.and_then(|v| v.as_str().or_else(|| v.as_i64().map(|_| "")))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Stringify numeric conversation IDs in async Shelley path

The async Shelley command converts numeric IDs with v.as_i64().map(|_| ""), which drops the actual value and builds a chat URL like /conversation//chat whenever Shelley returns an integer id. That causes the follow-up chat request to fail for numeric-ID responses; the synchronous path already handles this correctly by converting numbers to strings.

Useful? React with 👍 / 👎.

Comment thread desktop/src/main.rs
Comment on lines +3455 to +3457
cmd.stdin(Stdio::null())
.stdout(Stdio::null())
.stderr(Stdio::piped());
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Drain or redirect Shelley stderr instead of leaving it piped

This spawns Shelley with stderr piped but never reads from the pipe, so if Shelley emits enough stderr logs, the pipe buffer can fill and block the child process. In that state the sidecar can stall and agent-mode requests will start timing out/failing under verbose logging conditions.

Useful? React with 👍 / 👎.

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