Desktop Control × AIDE — Full Integration Doctrine

SkillCommunication

The full architecture for AIDE's desktop control, agent tool bridge, telegram /ask brain, REST routes, grants/panic/pending/verdict safety, grammar-constrained DSL, single-service law, refusal-recovery as training data. Use when wiring any new surface (agent, telegram, future UI) that drives the desktop; when the desktop service is referenced from more than one place; when a new op is added; when the panic/grants semantics need to be explained; when trajectory capture needs a new channel; or when integrating the house model into desktop act().

Use Desktop Control × AIDE — Full Integration Doctrine in Claude, ChatGPT or Ahel Desktop

Free. Sign in, add Desktop Control × AIDE — Full Integration Doctrine and connect your AI. About a minute.

Also: Claude Code · Cursor · Codex

Then ask your AI: use the Desktop Control × AIDE skill

Details

Instructions available. Your AI can read the instructions. Execution depends on the setup they require.

Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.

Desktop Control × AIDE — Full Integration DoctrineStart free

What this skill tells your AI

The instructions your AI receives, as published by anonymousnomad/covert-coder in skills/packs/aide-desktop-control-integration/SKILL.md and read by ahel’s review.

Born 2026-08-28: closed the gap between the built desktop service and the agent loop. The desktop control surface now has THREE live drivers (REST, Telegram /ask, agent <desktop_action>) all backed by ONE createDesktopControl instance, ONE grants manifest, ONE panic state, ONE trajectory file.

Research base (verified 2026-08-28)

  1. In-repo: desktop-control.mjs is the bounded domain. 7 hard-coded ops (launch_app, open_path, list_windows, focus_window, move_file, outlook_create_draft, excel_generate_report), strict grants manifest, panic kill switch, pending/verdict long-poll, refusal-recovery as training data (T2 90/90 battery).
  2. telegram-brain.mjs is the proof-of-pattern. Model proposes a single grammar-constrained action line; operator confirms via YES/NO; executor runs with full grants/panic; evidence and trajectory land in the same place.
  3. node/src/services/agent-tools.mjs is the agent's tool factory. Each tool declares name/params/readOnly/execute(args). Mutating tools require approved: true at the dispatch layer.
  4. node/src/routes/agent.ts exposes /api/agent/tool with the dispatchTool seam — a closure that takes (name, args, opts) and returns {ok, output, terminal}. This is the integration point.
  5. Rival context: desktop control is an emerging 2026 surface (Cursor

Why it's done this way

  • The differentiator is not "we can drive a desktop" — it is "OUR OWN 4B model drives it, locally, with operator-owned safety rails".
  • Verdict-as-labeling: the operator is already in the loop; reusing those judgments as training data compounds the corpus for free.
  • Grammar-constrained actions eliminate the #1 desktop-control failure mode (malformed action JSON) at the model level instead of with retries.
  • Single service preserves the deny-by-default invariant: a grant set via REST must gate the agent path. Two instances breaks that contract.

Dependencies / issues / bugs

  • Desktop-control.mjs is the floor. The engine lifecycle doctrine does NOT cover the desktop service — it is in-process state, persisted in .aide/desktop/grants.json and rehydrated.
  • Pre-existing contract drift: legacy daemon's status() returns pending_approvals which is NOT in DesktopStatusResponse. The /api/desktop/status route therefore returns BAD_RESPONSE on the current shape. Filed as a follow-up.
  • Memory coexistence: desktop inference REUSES the cipher engine, never a third.
  • Test pattern: tests/arch/desktop-policy.test.ts covers the parser (11 cases) + the agent-tool integration (10 cases) including trajectory

Threat matrix

ThreatSignatureDefense
Runaway automationact loop types into wrong windowgrants + panic; action-rate ceiling; per-category allowlist
Malformed actions from modelinvalid JSON, phantom keysgrammar-constrained parser; strict allowlist on op: and target:
Privilege escalation via modelmodel emits approved: true or unknown fieldUNKNOWN_FIELD rejection; approved set ONLY by dispatchTool, not the parser
Two services with split grantsgrants set via REST don't gate agent pathSINGLE INSTANCE LAW; desktopServiceRef lift in openapi.ts
Model replacement driftexternal API swapped into the policy hookall-local law: endpoint must be 127.0.0.1; egress audit check in CI
Trajectory lossrefused actions not recordedrecordTrajectory called on EVERY act() — both success and refusal
Destructive category too earlymodel attempts file-delete class actions7-op allowlist (no delete_file); destructive classes need explicit-confirm card
Screen-content exfiltrationstate serialization leaks secretsstate schema excludes password fields; all-local law
Coordinate/DPI driftactions miss targets on resolution changerelative coords + window-class targeting (v2 — Phase B)
Panic bypassagent calls act() after operator hits panictool calls desktop.act() which checks panics array, throws PANIC
NO_APPROVAL bypass at HTTPagent calls tool without approved: true at the routedispatchTool MUTATING check rejects with VALIDATION BEFORE the tool runs
NO_APPROVAL inside the toolmodel fakes approved: true in argstool's own if (args.approved !== 'true' && args.approved !== true) throws NO_APPROVAL
Status contract driftresponse includes pending_approvals, breaks strict contractpre-existing issue — follow-up filed

Pitfalls

  • Do NOT create a second createDesktopControl anywhere. Two instances = split brain (grants, panic, trajectory all split).

  • Do NOT bypass the agent dispatchTool layer to call desktop.act directly. The dispatchTool layer is the only place that gates approved: true at the HTTP boundary.

  • Do NOT widen the op allowlist without an eval battery run. Each new op ships with: (a) trajectory rows, (b) a battery entry, (c) docs.

  • Do NOT log full screenshots to disk uncontrolled — state text + hashes only.

  • Do NOT trust model confidence blindly — thresholds measured from verdict data, not guessed.

  • Do NOT add a new field to the DSL without a parser test — desktop-policy.test.ts covers all 4 valid fields + every rejection case. New fields must extend KNOWN_FIELDS and add both happy-path and rejection tests.

    capture and panic propagation.

    Mission Control, OS-level automation rare). AIDE's differentiator is the house model driving the desktop, locally, with operator-owned safety rails — same model, same engine, same chassis, no cloud.

What to do (direct)

  1. Single desktop service instance: every surface (REST routes, telegram brain, agent tool, future UI panels) must receive the SAME createDesktopControl({ workspace }) object. Never create a second one.
  2. Grammar-constrained DSL (node/src/services/desktop-policy.mjs): <desktop_action> blocks carry op:, target:, destination:, note:. Unknown fields are REJECTED (privilege-escalation guard).
  3. Permission class is computed by classForOp(op) (READ | WRITE | OPEN | DESTRUCTIVE). The agent loop surfaces this on the approval card so DESTRUCTIVE actions get the explicit-confirm treatment.
  4. Trajectory capture is the desktop service's job. Refusal-recovery rows are TRAINING GOLD — every refused action is recorded.
  5. All-local law: no cloud, no telemetry, no model replacement via API. The model that moves the mouse must run on this machine.

Signals

GitHub stars
43
Forks
14
Last commit
Oct 2026
Advanced
Item type
skill
Key
aide-desktop-control-integration
Source
github.com/anonymousnomad/covert-coder