# Desktop AGENTS.md

This file is the AI development guide for the `desktop/` module. It should be a
stable navigation aid, not a complete source tree inventory. For exact files,
APIs, and current implementation details, inspect the code with `rg`, `go list`,
and the source-of-truth documents below.

## Purpose

`desktop/` builds the headless AgentTeam daemon/CLI for every supported platform and
the Electron native host for macOS and Windows. Linux ships the Go daemon/CLI
only. The Go process connects a user's machine to AgentTeam, manages local agent
runtimes, serves the Desktop gateway/API surface, and exposes scoped outbound
tool bridges from agent runtimes back to AgentTeam. Electron packages the root
`web/` Desktop renderer and owns window, tray, menu, deep-link, and
whole-application update behavior.

Use this document to understand:

- the stable desktop module vocabulary;
- package boundaries and dependency direction;
- where to look before changing behavior;
- the verification commands expected for desktop changes.

Do not use this document as an exact file list. File-level structure changes more
often than the architectural boundaries below.

## Source Of Truth

Read in this order when starting desktop work:

1. **Repository guide:** root `AGENTS.md` for repo-wide rules, package map, PR
   expectations, and maintainability guardrails.
2. **Product/spec contracts:** root `SPECS.md`, then the relevant `specs/**/*`
   documents. Desktop daemon work usually starts at
   `specs/daemon/daemon.md`, `specs/daemon/desktop-architecture.md`, and
   `specs/daemon/runtime-outbound-tools.md`.
3. **Current implementation map:** root `docs/tech_design.md` for the latest
   cross-repo implementation status and package ownership notes.
4. **Code:** use `go list ./...`, `rg`, package docs, tests, and commit history.
   Code and tests win over stale prose.

When documents disagree, prefer the most specific active spec for product
behavior, then current code/tests for implementation reality. Update the stale
document if your change intentionally alters the stable contract.

## Module Map

### `internal/daemon`

Owns the desktop process lifecycle: config loading, component wiring, HTTP
server startup, runtime receipt lifecycle, service install/status helpers, and
graceful shutdown. The daemon is headless on every platform. It may wire other
modules together, but domain logic should stay in the owning packages.

### `internal/daemoncontrol`

Owns the canonical per-user daemon receipt, receipt permissions and
reconciliation, owner/process identity checks, control capability, orphaned
Electron-owner adoption, and owner-safe shutdown state. Receipt/control
credentials must stay out of renderer bootstrap, URLs, logs, process arguments,
and generic application APIs.

### `internal/channel`

Defines channel implementations and channel lifecycle management. Channel
packages normalize inbound source messages, send outbound messages, expose
channel-specific MCP tools, and handle source-specific protocol details.

The supported channel family is AgentTeam. The AgentTeam channel handles daemon WebSocket
commands for agent lifecycle, workspace operations, recovery, review context,
tasks, triggers, Exec action forwarding, and knowledge retrieval.

### `internal/dispatcher`

Routes messages from channels into instructions or interactive agent sessions.
It resolves the target agent/runtime, manages session reuse and lifecycle, owns
runtime launch orchestration, maps runtime events to AgentTeam-visible events, and
coordinates recovery restore/GC paths delegated by channels.

Dispatcher should not become a transport-specific package. Channel protocol
details stay in `internal/channel/*`; runtime process details stay in
`internal/agent`.

### `internal/agent`

Owns local agent configuration validation, runtime driver orchestration,
interactive process state, delivery decisions, checkpoint/recovery helpers, and
runtime boundary subpackages.

Important subpackages:

- `drivercontract`: narrow contract between `Process` and concrete runtime
  drivers. Keep it small and intentional.
- `runtimeconfig`: runtime types, detection, command/env/materialization helpers.
- `runtimeevents`: daemon-facing runtime event bus model.
- `runtimeproc`: runtime process tree tracking and cleanup helpers.

Concrete drivers currently live in the root `agent` package. Do not move them to
new driver subpackages until helper ownership and constructor boundaries are
explicitly redesigned; otherwise it is easy to introduce root facades, aliases,
or import cycles.

### `internal/api`

Hosts the Desktop gateway, local business/control APIs, MCP routes, and session
queries. It does not host renderer or SPA assets. The private daemon control
plane issues and revokes renderer UI sessions and authorizes adoption/shutdown;
ordinary local API handlers should call profile/domain services rather than
reimplement persistence or runtime logic inline.

### `internal/profile`

Owns local desktop configuration persistence and reload behavior: agents,
channels, providers, runtimes, external MCP servers, skills, shell environment
imports, and file watching. Keep validation close to the data it protects.

### `internal/api/mcp` and `internal/wire/mcpcheck`

`internal/api/mcp` contains the local AgentTeam MCP tool surface. Channel packages
provide their own tool definitions and dispatch. `internal/wire/mcpcheck`
validates user-managed external MCP servers. Treat MCP and the hidden agent
tools CLI as runtime outbound bridges owned by the communication layer; do not
model them as a fourth product architecture layer.

### Small runtime boundary packages

Desktop `internal/provider` and `internal/promptcompiler` own provider config
and prompt assembly. Root `internal/core/rewindcaps` owns shared server/Desktop
runtime recovery capability declarations. Prefer extending these narrow
packages over growing cross-cutting logic in daemon, dispatcher, or agent
process code.

### `electron/` and root `web/`

`electron/` owns Electron main, preload, shared IPC contracts, packaging, and
native-shell tests. Main owns daemon supervision, the internal `app://agentteam`
renderer protocol, window/tray/menu state, external `agentteam://` dispatch,
settings, quit behavior, and macOS/Windows updater integration. Preload exposes
one exact typed facade; never expose Electron/Node objects, `ipcRenderer`,
channel names, or a generic invoke/send API. Production renderer windows keep
context isolation and sandboxing enabled with Node integration disabled.

The React source of truth is repository root `web/`; it produces separate
Browser and Desktop builds from one business application. Keep Desktop-only
`/api/internal/*` calls and explicit daemon URL construction behind the root Web
runtime adapter. Production Electron packages main, preload, and renderer in
`app.asar`; the Go sidecar and managed first-party runtime are
`extraResources`. Supported Electron targets are macOS arm64/x64 and Windows
arm64/x64. Linux amd64/arm64 stays on the daemon/CLI-only build path.

### `e2e/`

End-to-end tests use the `e2e` build tag. Keep new e2e areas in subdirectories
with shared helpers, and keep specs for test areas under `e2e/specs/` when the
behavior needs design documentation.

## Stable Architecture Boundaries

- **Daemon wires components**; it should not own channel, dispatcher, or runtime
  domain behavior.
- **Daemon is headless**; Electron owns macOS/Windows application/window/tray,
  menus, external navigation, and application updates.
- **Daemon control owns receipt and shutdown authority**; Electron renderer
  receives only a short-lived, revocable UI session.
- **Channels own source protocol details** and expose normalized messages plus
  channel-specific MCP tools.
- **Dispatcher owns routing/session decisions** and delegates runtime mechanics
  to `internal/agent`.
- **Agent process owns runtime interaction** through `drivercontract` and
  concrete drivers.
- **API owns local HTTP surfaces** and should route to profile/channel/agent
  modules instead of duplicating their rules.
- **Preload owns the native renderer boundary** and exposes only validated,
  purpose-specific typed operations; generic IPC and Node integration are
  forbidden.
- **Profile owns persisted desktop configuration** and reload/watch behavior.
- **Shared `types` stay value-oriented**. Avoid turning them into dumping grounds
  for behavior.

Check dependency direction with `go list` when introducing a new import. If a
change requires a package to import its caller or a root package to facade a new
subpackage, stop and redesign the boundary first.

## Runtime And Agent Guidance

Supported runtime types live in `internal/agent/runtimeconfig` and currently
include builtin OpenCode, external OpenCode, Claude, Codex, and Kimi. `builtin`
uses the AgentTeam-managed OpenCode binary shipped with the first-party artifact;
`opencode` means an external OpenCode binary from PATH or manual configuration.
On macOS/Windows the managed runtime is replaced with the whole Electron
application; on Linux it ships with the daemon/CLI payload. External OpenCode,
Claude, Codex, and Kimi are detect/use/configure paths; AgentTeam does not own their
package-manager installation or upgrade flow.

When changing runtimes:

- keep runtime-private parsing/config in the concrete driver;
- add fields to `drivercontract` only when the process or multiple drivers need
  them;
- prefer characterization tests for event translation and delivery behavior;
- keep `runtimeevents` as the daemon event model and `drivercontract.ParsedEvent`
  as the driver-to-process event model;
- avoid compatibility aliases or forwarding packages after package moves.

When changing delivery or lifecycle behavior, inspect the `process_*` tests and
add focused regression coverage for queueing, busy delivery, wake rollback,
recovery, and context cancellation paths.

## Runtime Outbound Tools And AgentTeam Protocol Guidance

MCP and the hidden agent tools CLI are runtime-to-desktop outbound bridges. The
local MCP tool surface lives in `internal/api/mcp`; each channel owns its tool
definitions and call handling. Agent tools CLI uses daemon-issued leases and
must share the same Tool Core semantics as any MCP fallback. AgentTeam channel tools
have the broadest surface and should be treated as security- and
routing-sensitive.

`internal/api/exec` owns the single hidden CLI capability. Its immutable
`RuntimeCatalog` merges fixed built-in domains with the Server-projected
Extension snapshot; one `RuntimeAuthorizationStore`, bearer credential file,
Catalog route, and action route serve both. The System Prompt keeps built-in
and authorized Extension guidance in separate sections, but both use
`agentteam exec <domain-or-extension> <action>`. Do not reintroduce a
`agentteam extension` command, `/api/internal/ext`, `AGENTTEAM_EXTENSION_*`, a second
credential owner, or the retired built-in `pr-watch` domain. Provider
credentials and permission decisions remain on AgentTeam Server; Desktop only
validates and pins the secret-free snapshot.

When changing runtime outbound tools:

- keep tool schemas explicit and stable;
- do not expose hidden owner-private context IDs in public schemas;
- preserve exact AgentTeam targets for channel, DM, and reply-thread replies;
- keep provider/app authorization server-side for Exec-backed PR-watch actions;
- update `specs/daemon/runtime-outbound-tools.md` when changing stable runtime
  outbound tool architecture, transport ownership, or tool visibility rules.

## Development Workflow

Common build commands from the `desktop/` directory; run the unified Desktop
development entry from the repository root:

```bash
make build-daemon       # build the pure Go daemon/CLI without Node or Web assets
make build-renderer     # build root Web renderer into electron/dist/renderer
AGENTTEAM_DESKTOP_PLATFORM=darwin AGENTTEAM_DESKTOP_ARCH=arm64 \
  AGENTTEAM_DESKTOP_VERSION=0.0.0-dev make build-electron
make generate-icons     # regenerate PNG assets plus Electron .icns/.ico files
make -C .. dev:desktop  # run the repo-owned `dev --desktop` stack
make test               # run desktop Go tests; no frontend artifact prerequisite
make test-e2e           # run e2e tests with the e2e build tag
make fmt                # go fmt ./...
make vet                # go vet ./...
make lint               # golangci-lint run

cd electron
npm test                # Electron main/preload/script tests
npm run typecheck
```

`make dev:desktop` is the canonical root wrapper for `dev --desktop`. It builds
the Go sidecar, runs the root `web/` Desktop Vite entry, builds/starts Electron
main and preload, and points Electron at the explicit sidecar and Vite renderer
for the current checkout. Production always loads immutable `app://agentteam`
content; development alone may load the local Vite URL.

Useful repo-level guardrails:

```bash
make check-agent-goimports
make check-agent-drivercontract
make check-electron-cutover
make regression-fast
```

For focused work, run the smallest command that proves the touched behavior, then
run broader gates before PR handoff. For docs-only changes, at minimum run
`git diff --check` and inspect the rendered/changed Markdown for stale claims.

## Coding Guardrails

- Keep changes small and behavior-preserving unless the task explicitly changes
  behavior.
- Prefer focused packages and narrow contracts over large shared abstractions.
- Use `context.Context` for cancellation and time bounds around external I/O.
- Wrap errors with useful context; only ignore errors when they are truly
  best-effort and the reason is obvious or logged.
- Avoid import aliases unless they remove real ambiguity.
- Keep generated/build artifacts out of commits unless the repository explicitly
  tracks them.
- Add characterization tests before refactoring runtime drivers, dispatcher
  routing, recovery, or MCP tool behavior.

## Updating This File

Update `desktop/AGENTS.md` when a change modifies stable desktop development
knowledge:

- module responsibilities or dependency direction;
- daemon/channel/dispatcher/agent/API/MCP architecture boundaries;
- supported runtime or channel families;
- stable runtime outbound tool, MCP, agent tools CLI, or AgentTeam protocol conventions;
- required development, test, or PR verification workflow;
- security, ownership, or permission boundaries relevant to desktop work.

Do **not** update this file for ordinary file splits, new helper files, internal
function moves, one-off endpoints, or dependency additions that do not affect how
agents should understand or work in the module. Prefer package docs, specs,
README files, and tests for detailed local behavior. Long-lived Desktop specs and
AGENTS guidance should state current facts, stable contracts, and ownership; do
not preserve implementation history, phase notes, or retired alternatives in
prose just because they once existed in the repository.

## What Not To Put Here

- Full file-level directory trees.
- Exhaustive endpoint, tool, dependency, or UI component inventories.
- Historical migration notes that are no longer active guidance.
- Instructions that duplicate root `AGENTS.md` without desktop-specific nuance.
- Claims that cannot be kept stable without checking current code each time.
