Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@
# Allowed: nonempty.
# DRIGA_SUMMARIES_MODEL=

# assistant.provider: string; default=auto; optional. Answering assistant; auto prefers Claude, Codex, then Copilot independently of session discovery.
# Allowed: auto, claude, codex or copilot.
# DRIGA_ASSISTANT_PROVIDER=

# cleanup.worktree_idle: duration; default=168h; optional. Idle worktree cleanup eligibility.
# Allowed: 0..2562047h47m16.854775807s; zero = no idle minimum.
# DRIGA_CLEANUP_WORKTREE_IDLE=
Expand Down Expand Up @@ -162,7 +166,7 @@
# DRIGA_CHAT_READ_ONLY: marker; default=unset; optional. 1 keeps the Chat MCP child read-only.
# DRIGA_CHAT_READ_ONLY=

# DRIGA_INTERNAL: marker; default=unset; optional. 1 suppresses recursive hooks from Driga-owned Claude subprocesses.
# DRIGA_INTERNAL: marker; default=unset; optional. 1 suppresses recursive hooks from Driga-owned assistant subprocesses.
# DRIGA_INTERNAL=

# DRIGA_FIXTURE_OUTPUT: path; default=unset; optional. Fixture generator output directory (tests only).
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,9 @@ Collection stays local unless you configure fleet peers. Fleet sharing defaults
to metadata and titles; the serving peer controls text sharing. Optional OTLP
intake listens on loopback. The desktop app opens no network port.

Optional summaries and Chat run Claude through your installed CLI and its
existing vendor connection. Explicit questions and permitted context can leave
Chat automatically selects a compatible installed Claude, Codex or Copilot CLI;
optional project summaries use Claude. Both use the CLI's existing login and
vendor connection. Explicit questions and permitted context can leave
the machine through that connection. Agent configuration changes only through
explicit setup and hook commands. See [privacy and configuration](docs/usage.md#privacy-and-configuration)
for paths, capture settings, and the fleet sharing table.
Expand Down
1 change: 1 addition & 0 deletions cmd/driga-docgen/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ var settingGroups = []struct{ prefix, title, intro string }{
{"orphans", "Orphans", "The `[orphans]` table."},
{"machine", "Machine health", "The `[machine]` table."},
{"summaries", "Summaries", "The `[summaries]` table. Summaries run your installed Claude CLI on demand."},
{"assistant", "Answering assistant", "The `[assistant]` table selects the answering CLI independently of monitored agents."},
{"cleanup", "Cleanup", "The `[cleanup]` table."},
{"fleet", "Fleet", "The `[fleet]` table for paired machines."},
{"inbox", "Inbox and alerts", "The `[inbox]` table."},
Expand Down
91 changes: 91 additions & 0 deletions docs/specs/2026-11-10-assistant-providers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# Assistant providers

Issue: https://github.com/labstack/driga/issues/103

Chat and `driga ask` must work when only one supported assistant CLI is installed.
Collection must remain independent of assistant installation and login.

## Selection and identity

`assistant.provider` defaults to `auto`, selecting the first compatible CLI in
Claude → Codex → Copilot order. `DRIGA_ASSISTANT_PROVIDER` or the config file can
select one explicitly. Selection runs only when creating a conversation; no
background probes, installation, login, or model requests are performed.
Compatibility probes inspect CLI metadata. Users authenticate with their CLI.
Authentication or quota errors do not trigger automatic replay elsewhere.

CLI clients pass their resolved preference when requesting a new conversation,
including through an already-running service. This is a per-conversation choice,
not a mutation of the service's setting. Desktop Chat uses the service preference;
restart the service after changing its configuration.

The selected provider is persisted before the first prompt. Resumption always
uses that provider and exact session ID, even if the preferred CLI changes.
Missing/incompatible CLIs produce an actionable error and leave monitoring alive.
Internal-session exclusion keys are `(provider, session ID)`, including hooks,
so equal vendor IDs cannot hide another provider's workload. Unknown identities
are handled conservatively.

## Provider adapters

The existing `chat.Agent.Run` interface remains the seam. Requests carry the
persisted provider. The broker owns conversation state, cancellation, capture,
trust modes and command approvals for every provider.

Claude keeps its strict MCP configuration and permission bridge. Codex uses
config-free `exec`, retaining authentication in `CODEX_HOME`, ignoring user exec
rules and project configuration through a private working directory. Provider
and model configuration is not loaded; this adapter uses the default OpenAI
connection rather than user-defined model providers. Its native
execution environment is disabled with `CODEX_EXEC_SERVER_URL=none`, including
runtime filesystem/command backstops. The adapter accepts the audited 0.167.0
release; unknown registries fail closed. Only Driga's read catalog and, for action
chat, `list_prompts` and broker-gated `run_command` are enabled. Credentials and
prompts stay out of process arguments. Dashboard edits are currently unavailable
through this Codex adapter; read and panel tools remain available.

Copilot uses framed SDK protocol 3 and a host-owned MCP tool bridge. It retains
the CLI's authentication home but uses a private session config directory and
working directory. Session configuration disables ambient hooks, plugins,
instructions, skills, MCP servers and host Git operations. Before sending a
prompt, Driga requires the safety-options acknowledgment and an exact tool
catalog containing only its custom declarations. Permission requests for native
operations are denied. Unsupported protocol/options/catalogs fail closed.

The host bridge exposes read tools and a bounded action subset. It excludes
model-direct approval, Claim tools and dashboard replace/restore/delete calls.
`run_command` performs approval and execution through the existing broker.
Duplicate host-dispatched provider call IDs, foreign sessions, oversized frames
and incomplete streams fail the turn; children are canceled together. Codex owns
its MCP dispatch; Driga validates its reported tool catalog and call identities
in the output stream, while command authorization remains inside the MCP broker.

Project summaries remain Claude-specific because their model and USD budget
contract needs a separate provider-specific design. Selecting a Chat provider
does not change summary behavior or monitoring-adapter enablement.

## Product presentation

Reference lock: retain the existing Chat and TUI typography, muted status text,
trust-mode controls and layout. The bundled Refero copywriting reference's
orientation/status rule applies: show the actual answering provider, avoid a
Claude label on Codex/Copilot answers. No new provider picker or onboarding flow
is needed; the existing config mechanism provides the explicit override.

## Validation

Tests use disposable homes and synthetic executable/protocol fixtures only.
Cover ordered automatic selection, explicit failures, lazy initialization,
provider-pinned resume after restart, cancellation without replay, config/env
precedence, provider-ID collisions, hook/spool exclusion, native tool rejection,
permission denial, frame limits and child cleanup. Story fixtures verify provider
labels. Live authentication/model turns are deliberately outside test execution;
metadata checks alone are not an end-to-end vendor-service certification.

Primary protocol evidence:

- [Codex environment-disabled tools and runtime backstops](https://github.com/openai/codex/commit/a504d8f0fa70c88f38cbf6c5dae26a1e1223fd63)
- [Codex app-server protocol](https://learn.chatgpt.com/docs/app-server)
- [Codex CLI source/configuration](https://github.com/openai/codex)
- [Copilot SDK protocol and empty mode](https://github.com/github/copilot-sdk)
- [Copilot CLI command reference](https://docs.github.com/en/copilot/reference/copilot-cli-reference/cli-command-reference)
87 changes: 87 additions & 0 deletions docs/specs/2026-11-10-provider-review.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Assistant provider review

Base: `affa6e64807cb775181af3d4a2d6f4ae3bc35aa5` (released main).
Source candidate: `3f8caa7` (including `2b89669`).
Spec: [Assistant providers](2026-11-10-assistant-providers.md), issue #103.

## Scope

Reviewed the entire feature diff: provider routing, Claude/Codex/Copilot
adapters, host MCP forwarding, subprocess environment/lifetimes, config,
provider-qualified store and collector exclusion, hook/spool handling, CLI/service
transport, TUI/UI labels, stories, generated docs and host bundle. No migration,
agent-settings edits, real vendor turns or production cleanup were performed.

## Standards

A fresh independent reviewer checked repository standards and the code-review
skill's smell baseline. Initial findings were resolved:

- Removed the variadic `Open` compatibility signature; callers supply one
preference explicitly.
- Normalize inherited environment keys before filtering, including on Windows.
Hostile mixed-case approval, permissive Copilot and Node settings are covered.

Final candidate and the service-override follow-up have no remaining standards
blocker. The reviewer performed read-only review; execution evidence is below.

## Spec

A separate fresh reviewer checked implementation against the issue and spec.
Missing/null Copilot plugin-hook acknowledgment previously looked like zero;
the adapter now requires a present, non-null zero count before sending a prompt.
Regression fixtures prove missing/null/nonzero responses never receive it.

Provider choice is stored before dispatch, resumes retain provider/session IDs,
and failures are not replayed elsewhere. The final service override is scoped to
new conversations, validates requests before persistence, and leaves the daemon
default and existing sessions unchanged. Its additive acknowledgment rejects
older services before a prompt is submitted. No remaining spec blocker.

## Astra and user checks

Astra audited tool/approval ownership and independently reviewed the transports.
Resolved findings include per-turn Codex tool-name checks, call identity checks,
panel capture/result mapping, and inherited `CODEX_EXEC_SERVER_NOISE_*` settings
that could override a disabled execution environment. The launcher now strips
the entire inherited namespace before explicitly setting `URL=none`.

Official tag `rust-v0.167.0` resolves to `086ccc833bc9cf01024ad2dd6af7dbd421b6bf9a`
and contains the environment-disable implementation. The adapter accepts only
that exact release; future patches require another audit.

A separate agent exercised isolated help/config and fake-provider workflows as
a user. It found that the service silently ignored CLI preferences and that help
did not explain selection. Both are fixed and independently re-reviewed. The
user agent reran provider/remote/old-service cases and found no new blocker.

## Validation and limits

- Isolated Go suite; affected-package race checks across chat, llm, collector,
config, store and TUI; targeted remote-override normal/race checks.
- Native and Windows vet; Linux build; generated-doc consistency.
- 212 UI unit tests and 1,224 browser-story tests; UI bundles regenerated.
- Gitleaks and diff whitespace checks pass.
- An initial macOS open-file timeout passed when retried and in the subsequent
full suite. The collector heap-budget check passed in that full run.

Synthetic subprocess and protocol fixtures establish Driga's routing and refusal
behavior, not live vendor-service certification. No real authentication/model
turns were run. Copilot requires protocol 3, safety acknowledgment and an exact
custom-tool catalog. Codex requires 0.167.0 and default OpenAI configuration.
Codex/Copilot expose a smaller action catalog than Claude; direct MCP cleanup,
acknowledgment, jump, delegated prompt and summary actions remain Claude-only.
Project summaries retain their existing Claude model and budget contract.

## Final merge review

A second fresh Standards/Spec review of `03d380a` found one additional incomplete
stream case: Codex accepted `turn.completed` while an MCP call lacked its result.
A fake-provider regression reproduced it for read and panel tools. Completion
now rejects unfinished calls, while unresolved panel outcomes remain visible as
unknown. No approval bypass was found. The Standards review found no blockers.

Linux CI additionally exposed a fallback-transport test that depended on an
installed assistant for its new capability probe. It now uses the existing
synthetic CLI fixture with a private PATH. The failure was reproduced with an
agent-free PATH before fixing it; production behavior was unchanged.
51 changes: 37 additions & 14 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -798,8 +798,8 @@ read-only MCP tool.

## Summaries and Chat

Both run your installed `claude` CLI, on demand only; Driga never calls a model in
the background and has no API key.
Chat selects an installed assistant CLI on demand; project summaries use Claude.
Driga never calls a model in the background and requires no separate API key.

```sh
driga projects summarize <project>... | --all # needs [summaries] enabled = true
Expand All @@ -813,10 +813,27 @@ contents or paths. It runs `claude -p --safe-mode --no-session-persistence --too
with a $0.05 budget cap. A summary built from handoff text is shared with fleet
viewers only at `fleet.share_text = "snippets"`.

`driga ask` is a one-shot Chat broker client. Chat uses your installed Claude CLI
and login; Codex and Copilot are listed as coming. Required flags are probed on
the first turn, and an unsupported CLI fails with the missing flag and version.
No real agent CLI is run by tests.
`driga ask` is a one-shot, read-only Chat broker client. Chat defaults to
`assistant.provider = "auto"`: Claude Code, then Codex, then GitHub Copilot CLI,
skipping missing or incompatible CLIs. Install and sign in through your chosen
CLI. Set `provider = "claude"`, `"codex"` or `"copilot"` under `[assistant]` in
TOML (or set `DRIGA_ASSISTANT_PROVIDER`) to select one explicitly. Selection is lazy;
monitoring works without an assistant. Conversations stay with their original
provider. Authentication, quota and turn failures are never replayed with another
provider. Start a new conversation after changing providers.

CLI preferences apply to new conversations even when the service is already
running. Desktop Chat uses the service's preference; restart the service after
changing its configuration. Existing conversations always keep their provider.

Codex currently requires the audited 0.167.0 CLI release and supports Driga reads,
panels and broker-gated commands; dashboard edits are unavailable through that
adapter. It uses Codex's default OpenAI connection and existing authentication;
custom provider/model settings in `config.toml` are not loaded. Copilot requires
headless SDK protocol 3 and an exact Driga-only tool
catalog. Unsupported versions fail with an error rather than loosening approval
or configuration controls. No real agent CLI is run by tests. Project summaries
retain their Claude-specific model and budget cap regardless of this setting.

In the app, press **c** on any page, or choose View → Chat (Cmd+K, Ctrl+K on
Windows and Linux), to dock Chat on the right.
Expand All @@ -828,7 +845,7 @@ Context chips describe the current page, selected session/project and machine;
remove a chip to leave it out.
Session references in answers select the session on the current page. Tool calls
appear in a collapsed **Tools used** list. Driga replies are rendered as Markdown
and marked **answered by Claude Code**. A timed indicator shows thinking, writing
and show the selected provider. A timed indicator shows thinking, writing
or the current read tool. Streaming follows the bottom until you scroll up; reduced
motion uses a static dot.

Expand All @@ -845,19 +862,25 @@ starts a conversation, Ctrl+T toggles tool details, Ctrl+X clears context and
Alt+0 returns to Flow. Thinking/writing/tool status includes elapsed time and a
streaming cursor; NoColor uses a static indicator. Flow's copy-resume key is **C**.

Chat can acknowledge inbox items, jump to a session terminal, kill an agent or
orphan, clean up a candidate and refresh project summaries. It also has Claude’s
built-in shell and file tools. Actions are local-only and keep the CLI’s process,
cleanup and jump safety checks. Chat never types into a live agent terminal.
Chat provides Driga read tools, panels and local commands through `run_command`.
Commands use the broker's approval cards, process identity checks and sandbox.
Claude additionally retains its permission-gated native read tools and existing
action bridge. Copilot exposes a bounded subset of dashboard edits. Vendor-native
shell and file editing tools are disabled. Chat never types into a live agent terminal.

Direct MCP cleanup, inbox acknowledgment, terminal jumps, delegated prompt answers
and project-summary actions remain Claude-only. Codex and Copilot use the shared
broker command tool for supported local commands; their action catalogs are
deliberately smaller than Claude's permission-bridged catalog.

Each conversation starts in **Confirm**. Change trust mode with the app's Chat
header buttons or **m** in TUI navigate mode:

| Mode | Runs without asking | Asks |
|---|---|---|
| Confirm | Driga read tools and reads inside the working directory | Reads elsewhere and every other call |
| Auto | Auto allows driga read tools, reads inside the working directory, inbox acknowledgments, jumps and summaries, and allows Edit/Write only inside a git project working directory that is neither home, the driga data directory nor an ancestor of either, with no hidden components or agent instruction names (`claude*.md`, `agents*.md`, `gemini*.md`, `copilot-instructions.md`, case-insensitive) in the given or resolved relative path after trimming trailing dots and spaces, and always asks on colons. | Everything else asks |
| Full auto | Everything | Nothing |
| Confirm | Driga read tools | Every local command |
| Auto | Driga read tools and commands classified Read | Other, Process and Destructive commands |
| Full auto | Driga read tools, Read commands and sandboxed Other commands | Process and Destructive commands, plus Other when sandboxing is unavailable |

Full auto requires confirmation and is shown in red with its remaining time.
The TUI warning stays visible while replies and action cards update; press **m**
Expand Down
Loading
Loading