docs/architecture.md

Architecture

System architecture, monorepo layout, language choices, build and release pipeline, and the package boundaries a subagent fleet builds against.

What ships today (2026-11). Two surfaces: the CLI/TUI (@picassohq/cli, not yet on npm) and Picasso for Mac 1.0.54 (Apple silicon, macOS 14+). Both run the agent loop in the pinned engine (0.2.2-rc.1, kept current by a gated background updater) with Picasso's plugins (packages/picasso-*); the CLI talks to it over stdio (tui-architecture.md) and the Mac app through the local relay in apps/desktop-helper (mac-relay.md). The engine's home is ~/.picasso/dsh-home. The stack choices below are the original plan; where they differ, tui-architecture.md and mac-relay.md describe the shipped system.

Stack decisions

Monorepo layout

Single repo, pnpm workspaces, Turborepo for the build graph.

picasso/
├── apps/
│   ├── cli/                    The npm-published CLI binary. Entrypoint.
│   ├── mac/                    Native macOS desktop app (SwiftUI) + local helper.
│   ├── marketing/             Next.js marketing/waitlist site.
│   ├── dashboard/              Next.js companion web app.
│   ├── api/                    Backend service (Fastify) for sessions, ads, telemetry.
│   ├── admin/                  Next.js master-backend admin console.
│   └── docs/                   Docs site source.
├── packages/
│   ├── core/                   Agent loop, plan/act/observe/reflect.
│   ├── tools/                  Built-in tool catalog.
│   ├── subagents/              Subagent orchestration.
│   ├── plan-mode/              Plan generation and approval flow.
│   ├── mcp/                    MCP client + server + registry.
│   ├── sessions/               Persist, resume, fork, replay.
│   ├── providers/              Provider abstraction. Per-provider adapters.
│   ├── sandbox/                OS-level sandboxing wrappers.
│   ├── hooks/                  Hook runtime.
│   ├── commands/               Slash + user-defined commands.
│   ├── tui/                    Ink components, status line, diff renderer.
│   ├── auth/                   Auth abstraction.
│   ├── telemetry/              Opt-in event collection.
│   ├── ads-sdk/                Ad surface SDK. ZeroClick + TryGravity adapters.
│   ├── memory/                 Persistent memory layer. Vector + graph store.
│   ├── goals/                  /goal long-horizon mode.
│   ├── cache-harness/          V2 cache-aware prompt/context harness.
│   ├── secrets/               Secret detection and redaction.
│   ├── admin/                  Master-backend admin domain logic.
│   ├── admin-client/          Typed client for the admin/control-plane API.
│   ├── control-plane/         Control-plane service logic (orgs, budgets, flags).
│   ├── desktop-agent/         Mac local-helper agent runtime bridge.
│   ├── desktop-browser/       In-app browser preview engine.
│   ├── desktop-git/           Git operations for the desktop app.
│   ├── desktop-ipc/           Desktop <-> local-helper IPC.
│   ├── desktop-projects/      Workspace/project management for the desktop app.
│   ├── desktop-schedules/     Scheduled/automation runs for the desktop app.
│   ├── desktop-sponsors/      Sponsored-surface logic for the desktop app.
│   ├── desktop-voice/         Voice/dictation for the desktop app.
│   └── shared/                 Shared types, errors, logging.
├── crates/
│   ├── indexer/                Rust repo indexer (tree-sitter).
│   ├── memdb/                  Rust vector + graph store for memory layer.
│   └── sandbox-native/         Rust shims for seatbelt / Landlock / Job Objects.
├── scripts/                    Release, signing, codegen scripts.
└── infra/                      Terraform for Postgres, Qdrant, S3, Vercel.
The desktop-* packages and the apps/mac SwiftUI app make up the native macOS surface; the CLI/TUI and the desktop app share core, providers, memory, goals, sessions, and the rest of the engine.

Package boundaries

Each package has one job and a single owner role. Cross-package imports go through public entry points (index.ts) only — no deep imports. Dependency direction is strict and one-way:

cli, mac, marketing, dashboard, api, admin, docs (apps)
        │
        ▼
   memory, goals  ◄── highest-level packages
        │
        ▼
core, subagents, plan-mode, sessions
        │
        ▼
tools, mcp, providers, sandbox, hooks, commands, ads-sdk
        │
        ▼
   tui, auth, telemetry
        │
        ▼
       shared

Violations of the direction are caught by eslint-plugin-boundaries on CI.

Build and release pipeline

Runtime topology

When a user runs picasso:

  1. CLI binary starts in their terminal.
  2. CLI authenticates via cached device-code token, or prompts for login.
  3. CLI loads project context: picasso.yaml config, .picasso/commands/, project memory profile (see 15-memory.md).
  4. User issues a command (interactive turn, picasso run "...", picasso goal "...").
  5. The CLI starts (or reuses) the pinned engine; the engine builds the prompt envelope: system prompt + injected memory + project rules + tool catalog (lean-context-architecture.md).
  6. The engine calls the provider route the person chose (picasso provider, picasso models; see 07-providers.md).
  7. Tool calls execute locally in the sandbox; results stream back to the model.
  8. Session events stream to the API for persistence; telemetry events ship if opted in.
  9. On /goal mode, the loop continues autonomously until the completion contract is met.
  10. The web dashboard reads from the API and renders sessions, replays, ads, and account settings.

Local dev environment

pnpm i && pnpm dev brings up:

Distribution

See 14-distribution.md for the full surface. Channels at launch: npm (npm i -g @picassohq/cli, publish pending) and the notarized Mac DMG with Sparkle updates. Homebrew, a curl installer and Windows or Linux binaries are not shipped.

Security posture

What we are not building in v1

Listed so the surface is honest: