- Add `enabled` option to useSession hook; OrchestratorScreen passes
enabled: !!orchestratorId to avoid polling /api/sessions/ with an
empty string when no orchestrator is running
- Replace term.onData XDA handler with term.parser.registerCsiHandler
matching the web dashboard implementation — onData only fires for
outgoing user input, not incoming WebSocket data where the CSI > q
query actually arrives
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Show orchestrator session details (status, activity, summary, timing,
terminal button, send message) directly on the Orchestrator page
instead of requiring navigation to a separate SessionDetail page.
Remove the Overview stats section. Commands remain in header button.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Revert 🤖 to navigate to Orchestrator overview (zones, stats,
orchestrator status card). The "Commands" header button on that
page opens the CLI commands reference. Tapping the orchestrator
card navigates to its session detail.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Commands button was on the Orchestrator page header which is
no longer visited when the orchestrator is running. Move it to the
HomeScreen header so it's always accessible.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Robot button (🤖) on HomeScreen now navigates directly to the
orchestrator's session detail when running, or to the Orchestrator
overview when not running
- Move CLI commands to a new CommandsScreen, accessible via a
"Commands" header button on the Orchestrator page
- Remove inline CLI commands from OrchestratorScreen body
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Keep the backend URL hint clean — Tailscale/ngrok/LAN instructions
are already in the setup guide below.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add Tailscale as the recommended connection method in the setup guide
with step-by-step instructions
- Add alternative sections for Local Wi-Fi and ngrok
- Wrap test notification buttons in __DEV__ so they only show during
development and are stripped from production builds
- Update placeholder and hint text to show Tailscale IP format first
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace isMountedRef with generation counter (fetchGenRef) in
useSessions and useSession hooks to prevent stale fetches from
overwriting correct data when the backend URL changes mid-flight
- Fix test review notification using invalid "needs_review" status;
correct value is "review_pending" per core types
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add "review" attention level to notification triggers (background task,
foreground hook, and scheduleNotification)
- Add notification tap handling: tapping a notification navigates directly
to the session detail screen via navigationRef
- Handle cold-start case (app killed) via getLastNotificationResponseAsync
- Add "review" test notification button in Settings screen
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The /api/sessions endpoint was filtering out orchestrator sessions,
so the mobile app could never detect a running orchestrator. Now the
API finds the orchestrator session ID before filtering and includes
it in the response as orchestratorId.
- Add orchestratorId to /api/sessions JSON response
- Add orchestratorId to SessionsResponse type
- Thread orchestratorId through useSessions hook
- Use orchestratorId in OrchestratorScreen instead of searching sessions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- New OrchestratorScreen showing orchestrator status (running/not),
session zone counts (merge/respond/review/pending/working/done),
overview stats, and full CLI command reference
- Add "AO" button in HomeScreen header linking to Orchestrator page
- Replace "Settings" text with gear icon in header
- Register Orchestrator route in navigator
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
scrollEnabled was set to false, which blocked touch scroll gestures
that xterm.js needs to scroll through terminal history.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add extra padding (keyboardHeight + 10) so the input comfortably
clears the keyboard suggestions/accessory bar on all devices.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
KeyboardAvoidingView was causing two issues: scrolling the page to the
top on focus, and not restoring the layout when dismissing the keyboard.
New approach uses Keyboard.addListener to track keyboard height and
applies it as paddingBottom on the message bar directly. This works
reliably on both iOS and Android regardless of softInputMode.
- Removed softwareKeyboardLayoutMode: "pan" from app.json
- Replaced KAV with plain View + dynamic keyboard padding
- Reverted SpawnSession/Settings screens to simple iOS-only KAV
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bump Android keyboardVerticalOffset from 80 to 140 to account for the
suggestions/clipboard bar that sits above the keyboard on many devices.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Set android.softwareKeyboardLayoutMode to "pan" in app.json to prevent
conflict between system adjustResize and KeyboardAvoidingView
- Use behavior="padding" consistently on both platforms
- Add keyboardVerticalOffset on Android to account for nav header
- Applied fix across all screens with keyboard input
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Set KeyboardAvoidingView behavior to "height" on Android (was undefined)
- Add scrollToEnd on TextInput focus so content scrolls up with keyboard
- Add keyboardShouldPersistTaps="handled" for better tap behavior
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add required `type: TIME_INTERVAL` to notification trigger for SDK 53
- Remove phantom statuses from SessionStatus/ActivityState not in core
(removed "running" from SessionStatus; "starting", "thinking", "working"
from ActivityState)
- Handle unhandled promise rejections from scheduleNotification in
useSessionNotifications hook with void + .catch()
- Await scheduleNotification in SettingsScreen test handlers and show
error alert on failure instead of premature "Sent"
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Exclude packages/mobile/** from root eslint config (mobile uses Expo/CJS toolchain)
- Align TERMINAL_STATUSES and NON_RESTORABLE_STATUSES with packages/core/src/types.ts
- Fix isRestorable() to use isTerminal() check matching core logic
- Change notification trigger from null to { seconds: 1 } for Android background task compat
- Add isPRRateLimited guard to merge button to prevent merge when API rate limited
- Await scheduleNotification in background task to ensure notifications are delivered
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds missing action features to match the web dashboard:
- Merge PR button: green button when PR is mergeable, calls /api/prs/:id/merge
- CI checks list: individual checks with status icons and links
- "Ask to fix CI" button: sends "Please fix the failing CI checks" to agent
- Unresolved review comments: per-comment card with author, path, body
- "Ask Agent to Fix" per comment: sends context-specific message with file path
- Alert cards: CI failures, merge conflicts, changes requested warnings
- Spawn Session screen: create new sessions with project ID and optional issue ID
- "+" button on home screen header to spawn sessions
- PR title is now tappable (opens in browser)
- Color-coded CI/review/mergeability status values
- PR blockers list display
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds `packages/mobile` — an Expo SDK 53 React Native app for monitoring
agent sessions from a phone.
Features:
- Home screen: Kanban-style session list sorted by attention level
- Session detail: metadata, PR link, CI status, branch info
- Terminal screen: full xterm.js terminal via WebView (port 14801)
- Settings screen: configurable backend URL (LAN IP or ngrok)
- Push notifications: background polling for attention-level changes
Improvements over PR #235:
- Fixed terminal onmessage handler to filter JSON control messages
(resize echoes no longer render as garbage text)
- Removed duplicate terminal.html (single source of truth in
terminal-html.ts)
- Fixed isDone check to include "cleanup" status using isTerminal()
Tech: Expo SDK 53, React Navigation 6, React Native WebView.
Two server connections: REST API (port 3000) + WebSocket terminal (14801).
The mobile package is excluded from the pnpm workspace to avoid
interfering with the monorepo toolchain.
Closes#265
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>