* fix: auto-detect free port in ao start <url> config generation
When generating a new config via `ao start <url>`, auto-detect a free
port instead of hardcoding 3000. Reuses `findFreePort` (extracted to
shared web-dir.ts from init.ts). When port was auto-selected, skip the
strict preflight port check and silently find another free port if
needed (race condition).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: add polling to listIssues integration test for Linear API consistency
The listIssues test was failing because Linear's API has eventual
consistency — a just-created issue may not appear in list queries
immediately. Other tests in this file already use pollUntilEqual for
the same reason. Use pollUntil to retry until the issue appears.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: restore coupling between MAX_PORT_SCAN and findFreePort
MAX_PORT_SCAN was decoupled from findFreePort after extraction to
web-dir.ts — init.ts kept a local constant only used in messages while
findFreePort had its own default, and start.ts hardcoded 99. Export
MAX_PORT_SCAN from web-dir.ts as the single source of truth, use it as
findFreePort's default parameter, and import it in both callers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Extract isPRMergeReady() helper that checks pr.state === "open" before
evaluating merge criteria, preventing the badge from appearing alongside
the 'Merged' chip on already-merged PRs.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
HTTPS clone fails on private repos without credentials. Now tries
three strategies in order:
1. gh repo clone (handles GitHub auth via gh auth token)
2. git clone with SSH URL (works with SSH keys)
3. git clone with HTTPS URL (public repos fallback)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix: URL start handles multi-project configs and cross-platform browser open
When `ao start <url>` loads an existing config with multiple projects,
resolve the correct project by matching the URL's owner/repo against
each project's `repo` field instead of failing with "Multiple projects".
Also fix browser open to use platform-appropriate command (open/xdg-open/start)
instead of hardcoded macOS `open`.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: use shallow clone (--depth 1) for faster repo onboarding
Full clones of large repos can take minutes. Shallow clone with
depth 1 fetches only the latest commit, making `ao start <url>`
near-instant for any repo size.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: use cmd.exe /c start for Windows browser open
`start` is a cmd.exe builtin, not a standalone executable — spawn
would fail with ENOENT. Run via cmd.exe /c with empty title arg.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add `ao start <url>` one-command project onboarding
When `ao start` receives a repo URL instead of a project ID, it now:
1. Parses the URL (supports GitHub, GitLab, Bitbucket — HTTPS and SSH)
2. Clones the repo (or reuses if already present with matching remote)
3. Auto-generates agent-orchestrator.yaml with sensible defaults:
- SCM/tracker plugins inferred from URL host
- Default branch detected from local refs
- Project type detected (language, package manager)
- Post-create install commands set based on package manager
4. Starts the orchestrator + dashboard as usual
New core module `config-generator.ts` handles URL parsing, SCM detection,
project info detection, and config generation. All logic is in core (not
CLI) for reusability. 36 unit tests cover URL parsing, SCM detection,
default branch detection, project info, config generation, and clone
target resolution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address bugbot review feedback
1. Non-JS postCreate fix: Only set postCreate install commands for JS
package managers (pnpm/yarn/bun/npm). Rust/Go/Python projects no
longer get an incorrect "npm install" command.
2. Deduplicate startup logic: Extract shared `runStartup()` helper used
by both URL-mode and normal-mode start flows. Eliminates ~100 lines
of duplicated dashboard+orchestrator startup code.
3. SSH URL matching: Normalize SSH URLs to HTTPS format in
`isRepoAlreadyCloned()` so repos cloned via SSH
(git@github.com:owner/repo) are correctly detected as matching.
4. SCM/tracker always explicit: Always set scm and tracker fields in
generated config so `applyProjectDefaults()` doesn't silently
override with github defaults for non-GitHub repos.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: sanitize repo names for project IDs and session prefixes
Address remaining bugbot comments:
- Add sanitizeProjectId() to handle dots/special chars in repo names
(e.g. "my.app" → "my-app" instead of failing Zod validation)
- Preserve original case for generateSessionPrefix() so CamelCase
detection works (e.g. "DevOS" → prefix "dos", not "dev")
- Strip invalid chars before prefix generation to prevent dots
leaking into sessionPrefix
Also update README and SETUP docs with `ao start <url>` quick
onboarding flow.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: auto-open browser to orchestrator page on `ao start`
Opens the orchestrator session page (/sessions/{id}) instead of the
root dashboard, since the Kanban board is empty on first startup
with no worker sessions yet.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: replace fixed 3s delay with port polling for browser open
Poll the dashboard port via TCP connection attempts (300ms intervals,
30s timeout) instead of a hardcoded setTimeout. Opens the browser only
once the server is actually accepting connections — deterministic
regardless of how long Next.js takes to compile.
Applied to both `ao start` and `ao dashboard` commands.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: add CLI tests for start/stop commands
12 new tests covering:
- Project resolution: single project, explicit arg, missing project,
multi-project ambiguity, empty config
- URL argument: reuse existing clone, git clone flow, existing config
detection, clone failure error handling
- Port polling: waitForPortAndOpen polls isPortAvailable before opening
browser (proves deterministic behavior vs fixed delay)
- Stop command: session kill + dashboard stop, graceful missing session
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: deduplicate waitForPortAndOpen into shared utility
Move waitForPortAndOpen to lib/web-dir.ts (alongside isPortAvailable)
so both start.ts and dashboard.ts share a single cancellation-aware
implementation. start.ts now uses AbortSignal like dashboard.ts —
polling stops immediately if the dashboard process exits early.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Android blocks plain HTTP by default. Enable usesCleartextTraffic
so the app can connect to http://100.x.x.x:3000 (Tailscale) and
http://192.168.x.x:3000 (LAN) backends.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- 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>