- New arc-tracker crate defines the Tracker trait and shared Issue/BlockerRef types
- arc-linear: replace Issue/BlockerRef with arc-tracker re-exports, add LinearTracker struct implementing Tracker, remove free functions
- arc-github: add GitHubTracker implementing Tracker via Projects V2 GraphQL API, with lazy project node ID resolution (org → user fallback) and create_installation_access_token_for_projects helper
- 47 tests in arc-github (15 new), 24 tests in arc-linear (updated to use LinearTracker)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
GraphQL client with 6 public functions: execute_graphql, fetch_viewer_id,
create_comment, update_issue_state, fetch_candidate_issues, and
fetch_issues_by_ids. Includes Issue/BlockerRef domain types with manual
normalization from GraphQL JSON responses.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a generic SSH sandbox that connects to any user-provided host via
openssh, without VM lifecycle management. Supports git clone with GitHub
App credentials, configurable working directory, and arc cp reconnection.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Enable serde_json's preserve_order feature so Map uses insertion-order
IndexMap instead of sorted BTreeMap. Extract build_event_envelope()
from the on_event closure to deduplicate the envelope construction.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When `devcontainer = true` in TOML sandbox config, Arc now resolves
devcontainer.json from the repo, uses its Dockerfile for the Daytona
snapshot, runs lifecycle hooks (on_create, post_create, post_start)
in the sandbox, and merges devcontainer env vars under TOML env.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Activate the dormant Segment-based telemetry infrastructure by wiring
lifecycle events in main.rs. Each CLI invocation now emits a "Command Run"
or "Command Error" event with sanitized args, duration, hashed repo
identifier, and CI detection.
- Add sanitize.rs: redacts sensitive CLI args (paths, values) while
keeping flags, booleans, and numeric patterns
- Add git.rs: MD5-hashes normalized origin remote URL so HTTPS/SSH
variants produce the same identifier
- Extend command_name to include nested subcommands (e.g. "pr create",
"llm prompt", "system prune", "model list")
- Restructure main/main_inner to capture timing and return command name
alongside result for telemetry
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Covers run, validate, cp, preview, ssh, model, doctor, init, install,
pr, and system. Each test verifies --help exits 0 and produces output.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace assert_eq!/contains() chains with insta::assert_snapshot! in
dockerfile unit tests (11 inline snapshots) and CLI model/help tests
(7 file-based snapshots), making test output easier to read and update.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When the codex binary is found on PATH, arc install now offers browser-based
OpenAI OAuth login before the standard provider picker. Falls back to manual
API key entry if OAuth fails or user declines.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Standalone library implementing OpenAI's OAuth PKCE flow (browser + device)
for authenticating with ChatGPT subscriptions instead of API keys.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a temporary local HTTP server in `arc install` that handles the
GitHub App manifest registration flow, enabling standalone users to
register a GitHub App without running the arc-web server.
Also gates server-only install steps (pre-flight checks, server.toml,
secrets/certs, start servers) behind #[cfg(feature = "server")] and
removes the `gh` CLI from system dependency checks. Reloads .env before
running arc doctor so it picks up freshly written credentials.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a switchable tracing layer that writes to ~/.arc/logs/{run-dir}/cli.log,
so all diagnostic info for a run is co-located with its other artifacts instead
of buried in the shared daily log file.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds McpTransport::Sandbox variant that starts an MCP server inside the
sandbox, waits for it to listen, gets a Daytona preview URL, and rewrites
to HTTP transport for the MCP client connection.
Key changes:
- Sandbox trait: add get_preview_url(port) for authenticated port access
- DaytonaSandbox: implement get_preview_url via Daytona SDK preview links
- McpTransport::Sandbox: new variant with command, port, env fields
- Session: resolve_sandbox_mcp_servers() starts servers and rewrites to HTTP
- Integration test: end-to-end Playwright MCP in Daytona - navigates to
example.com and verifies "Example Domain" in accessibility snapshot
Config example:
[mcp_servers.playwright]
type = "sandbox"
command = ["npx", "@playwright/mcp@latest", "--port", "3100", "--headless"]
port = 3100
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Centralizes config types (ServerConfig, CliConfig, expand_tilde) into a
new arc-config crate. Makes arc-api an optional dependency of arc-cli
behind a default-on "server" feature flag, so CLI-only builds skip heavy
server deps (axum, tower, hyper, sqlx, arc-db, arc-types).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Show colored "error:" prefix with cause chain for all CLI errors. When a
workflow name isn't found in a project with arc.toml, list available
workflows and suggest the closest match using Levenshtein distance.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move GitHub App authentication (types, JWT signing, token creation,
credential resolution) into a new leaf crate `arc-github`. ExeSandbox
now owns `github_app` directly and resolves clone credentials on-demand,
eliminating the GitCredentialSandbox decorator and its wrapping code in
cli/run.rs. GitCloneParams simplified to a single clean `url` field.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Introduces sandbox reconnection via persisted SandboxRecord, adds
upload_file_from_local to the Sandbox trait, and migrates arc-sprites
shell quoting to shlex::try_quote.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace ad-hoc replace('\'', "'\\''") escaping and unquoted interpolation
with a shell_quote() helper backed by shlex::try_quote to prevent command
injection via branch names, clone URLs, image names, env vars, file paths,
and grep patterns. Covers both arc-exe (SSH transport) and arc-workflows
(Daytona sandbox).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Recursively compares serialized ServerConfig keys against the
OpenAPI ServerConfiguration schema properties. Also fixes 7 fields
that were missing from the spec: log, checkpoint, git.slug,
git.author, git.webhooks, sandbox.exe, sandbox.env.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a webhook subsystem that receives GitHub App webhooks when configured
in server.toml with [git.webhooks] strategy = "tailscale_funnel". On startup,
it binds a local HTTP listener on a random port, exposes it via `tailscale funnel`,
and patches the GitHub App webhook URL. Incoming webhooks are verified with
HMAC-SHA256 before processing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The toolbox API does not support envs in /process/execute, so the
SDK now matches the Go SDK: accepts env in options but does not send
it. Arc uses export prepending as the workaround.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The upstream SDK now passes env vars through ExecuteRequest.envs,
so we no longer need to prepend export statements to commands.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Server is long-lived on a fixed host, so a persisted UUID at ~/.arc/.id is
appropriate. CLI runs ephemerally, so an MD5 of the MAC address avoids file
I/O and is stable per-machine. CLI falls back to ~/.arc/.id if it exists
for migration.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a telemetry library for product analytics with Segment integration.
Includes Track/User wire types, persistent anonymous ID (~/.arc/anonymous_id),
OS/arch/locale context, fire-and-forget sender via tokio::spawn, and
ARC_TELEMETRY env var control (off/errors/all). No CLI or server integration yet.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a completions API endpoint that supports both streaming (SSE) and
non-streaming (JSON) modes, with structured output via JSON Schema.
Wires up the CLI `arc llm prompt` command to use the server when
`--mode server` is specified.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements the Sandbox trait backed by the `sprite` CLI binary.
Includes 29 unit tests with mock runner and an e2e integration test
against the live Sprites service.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Commands can now delegate to a running Arc API server instead of
executing in-process. Adds ExecutionMode, ServerDefaults, and
ClientTlsConfig to cli.toml parsing with CLI flag > config > default
precedence. The models list command fetches from GET /models when in
server mode, with mTLS client certificate auth when [server.tls] is
configured.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New `arc-exe` crate that runs agent tool operations inside ephemeral
exe.dev VMs via SSH. Uses two SSH connections: a management plane
(`ssh exe.dev`) for VM lifecycle and a data plane (`ssh vmname.exe.xyz`)
for command execution and file I/O.
Includes SshRunner trait with MockSshRunner for unit tests and
OpensshRunner for real SSH, with raw_mode for the exe.dev management
plane's custom command handler.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace apt-get/NodeSource install (requires root) with direct Node.js
binary download to ~/.local (works as non-root daytona user)
- Run node install + npm install in single shell so PATH persists
- Add ~/.local/bin to PATH in env file and version check
- Fall back to stdout for error details when stderr is empty (Daytona
always returns empty stderr)
- Add e2e assertion that cli_stdout.log is written during poll
- Verified on Daytona with haiku: ensure_cli installs in 2s, full
workflow succeeds
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add updated_at to CreateSessionResponse for consistency with SessionListItem/SessionDetail
- Add format: uuid to session ID fields and parameter across the OpenAPI spec
- Remove SessionEvent discriminated union and SessionEvent* wrapper schemas that conflated
SSE transport-level event names with JSON data payload fields
- Update demo data to use proper UUIDs instead of string IDs
- Add uuid dependency to arc-types crate
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Refactor SessionTurn into discriminated union (UserTurn, AssistantTurn, ToolTurn)
using oneOf + discriminator so invalid states are unrepresentable
- Add format: date-time to all timestamp fields for proper codegen types
- Rename CreateSessionRequest.prompt to .content for consistency with SendMessageRequest
- Change sendSessionMessage from 200 to 202 (async processing via SSE)
- Extract inline response to SendMessageResponse schema
- Add updated_at to SessionListItem for sort-by-activity support
- Extract SessionId parameter to components/parameters (DRY)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace `gh auth token` with GitHub App IATs scoped to `contents: read` for
Daytona sandbox git cloning. Public repos are auto-detected and cloned without
credentials. Private repos get short-lived, repo-scoped tokens. Clear error
messages for each failure mode (app not installed, suspended, no repo access,
auth failure). Falls back gracefully when no GitHub App is configured.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Use thiserror for SlackApiError and ConnectionError (project convention)
- Remove misleading PartialEq/Eq on DispatchAction; use matches!() in tests
- Remove unused _slack_client and _default_channel params from event loop
- Extract check_ok() helper to deduplicate 3 ok-check sites in client.rs
- Make bot_token private on SlackClient; add http() accessor
- Make SlackClient Clone; eliminate duplicate instance in e2e example
- Reuse reqwest::Client in open_socket_url instead of creating a new one
- Filter empty env vars in resolve_credentials; remove redundant is_enabled
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements a complete Slack integration for the interviewer system using
Socket Mode (WebSocket-based, no public URL required). Supports all five
question types: YesNo, Confirmation, MultipleChoice, MultiSelect, and
Freeform (via thread replies with @mention).
Modules: config, client, blocks, interaction, socket, dispatch,
connection, threads. 72 unit tests + e2e example.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
HTTP hooks (type = "http") now actually execute instead of failing with
"no command specified". The executor POSTs the hook context as JSON,
parses HookDecision from the response, and fails open on errors.
Header values support $VAR/${VAR} interpolation gated by an
allowed_env_vars whitelist on the hook definition. Renames
CommandHookExecutor to HookExecutorImpl since it now handles both
command and HTTP hook types.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Users who always use the same provider/model/permissions no longer need
to pass flags every time. Precedence: CLI flag > cli.toml > hardcoded default.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Install ring CryptoProvider at CLI startup to prevent rustls panic
- Skip TLS in demo mode so the server uses plain HTTP
- Add ARC_DEMO=1 env var to web app config to bypass GitHub OAuth
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
LLM responses were printing raw Markdown (bold markers, table pipes,
heading hashes). Use termimad to render with proper ANSI formatting
when color is enabled, falling back to plain text when NO_COLOR is set.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sandbox cleanup was spawned fire-and-forget in a scopeguard, causing DNS
resolution to be cancelled when the tokio runtime shut down before the
HTTP request completed. Now cleanup is awaited explicitly before
returning, with the scopeguard kept only as a safety net for panics.
Also: add blank line before the warning and color-code it yellow to
match other warnings. Update daytona-sdk to include full error source
chain in error messages.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace plain dimmed text output with cargo/BuildKit-style progress bars
using indicatif MultiProgress. Shows spinners during active stages and
tool calls, right-aligned timers, green/red glyphs for completion status,
and stage costs. Falls back to simple eprintln for non-TTY. Verbose mode
is unchanged.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Automates first-time setup: generates server.toml, Ed25519 JWT keypair,
mTLS CA+server certificates, session secret, and .env file with proper
permissions. Includes pre-flight system dependency checks shared with
doctor, LLM provider API key collection, and optional doctor verification.
Also renames config file from arc.toml to server.toml across the codebase,
and loads ~/.arc/.env before CWD .env for centralized secret management.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
HumanCount's comma-separated output (1,234) is less scannable for token
counts. Restore k/m suffix formatting with added millions support. Remove
indicatif dependency from arc-agent since it no longer uses it.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace hand-rolled format_duration_human, format_tokens_human, and
format_token_count with indicatif's HumanDuration, HumanCount, and
HumanBytes. Token counts now display as comma-separated (e.g. "1,234")
instead of abbreviated (e.g. "1.2k"), and byte counts show units
(e.g. "1.50 KiB").
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use the semver crate's Version type instead of manual (u32, u32, u32)
tuples for version comparison and display, eliminating the custom
format_version helper in favor of Version's built-in Display and Ord.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>