Skip to content
| Marketplace
Sign in
Visual Studio Code>AI>Mocha AppNew to Visual Studio Code? Get it now.
Mocha App

Mocha App

Preview

Mocha Inc.

|
2 installs
| (0) | Free
Pair a verified Mocha device for guarded native Agent Host control, with separate legacy independent sessions.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Mocha App

Display name: Mocha App. Publisher: Mocha Inc. (mocha). Extension ID: mocha.mocha-client.

The Marketplace/VSIX icon at assets/icon.png is the exact 128x128 web favicon: the supplied white coffee bean on a black rounded square. The shared favicon generator updates both assets, and branding tests enforce byte equality.

Mocha App now includes verified owner-approved device pairing and guarded native Agent Host control through the authenticated relay protocol. Original native session/chat IDs remain unchanged. Existing extension-owned model-text conversations remain separate legacy independent sessions, not native agent chats.

Secure Connect Mocha

  1. Configure the verified relay origin in user-level mocha.relayUrl. Workspace overrides cannot redirect secure pairing or native traffic. HTTPS is required, except verified loopback HTTP development; legacy account IDs/shared tokens are not credentials.
  2. Run Mocha: Connect Mocha (Secure Device Pairing), or open vscode://mocha.mocha-client/connect (vscode-insiders://mocha.mocha-client/connect for Insiders). The desktop name is filled from the actual editor/machine, without a separate naming dialog. Review that name, the displayed code, and the signed-in owner in the browser, then explicitly approve. The link only starts pairing; it never approves or grants access automatically, and query/fragment credentials are rejected.
  3. The desktop makes a one-time S256-bound claim, stores the device bearer only in VS Code SecretStorage, verifies /auth/session, and connects /ws/control. Subsequent activations restore/verify existing credentials without starting a pairing.
  4. The device-first backend exposes actual paired-window workspace/provider contexts and explicit new native chat creation by default. Existing chats remain a separate catalog-selection path. Native session/chat subscriptions require explicit target selection and the adoption/readiness guard below. Empty Copilot chats are source-owned provisional drafts (state: creating), deliberately absent from the host's root list until their first explicit turn. Mocha observes the acknowledged native default chat without sending a setup turn, claiming tool ownership, or pretending its SDK is ready. Source context metadata distinguishes real workspace/provider and editor-host identities; the mobile picker uses readable labels instead of raw process IDs. A unique editor/workspace can default to Copilot; multiple hosts still require explicit choice because the public registry has no window binding.

The installed integration accepts an explicit authenticated-owner request to restore a currently advertised original source through its own Agent Host. Pairing or activation alone never hydrates sessions. Restoration remains host-controlled; Mocha does not convert legacy URIs, create a copy, change migration settings, or approve tools. A stricter registered readiness inspector takes precedence.

See SECURE_PROTOCOL.md for exact app-facing result/event shapes, paging semantics, privacy restrictions, and rollout requirements. Packaging is not proof of an installed-extension or real-provider end-to-end deployment.

Native Agent Host discovery and guarded control

On activation, the adapter discovers published local endpoints, negotiates AHP, lists native sessions, and maintains an in-memory catalog using root notifications and a 30-second refresh. Run Mocha: Inspect Native Agent Hosts (Local Only) to refresh and see counts, unsupported/invalid/stale records, partial catalogs, and limitations. Diagnostics never include titles, transcripts, endpoint URLs, or credentials.

  • The effective user-data directory is derived from the extension's public globalStorageUri, including custom profiles. Explicit --user-data-dir, portable user-data, and Stable/Insiders default directories are additional discovery candidates. No settings or registry files are changed.
  • Discovery reads agent-host\local-endpoint\entries\<sha256(type + NUL + pid + NUL + instanceId)>.json and the legacy metadata.json array. Each record is validated independently; canonical entry files win collisions, confirmed-dead PIDs are ignored, and unknown liveness does not mean dead. No registry files are deleted.
  • Schema 2 and negotiated protocol 0.9.0 only. Schema 1 is reported unsupported. An advertised version, VS Code product name, or build number is not sufficient: every connection performs initialize with protocolVersions: ["0.9.0"]. A host selecting 0.7 or rejecting negotiation is not used.
  • Windows named pipes use the exact published path and a WebSocket upgrade with the standard tkn query parameter. TCP endpoints must be loopback. Endpoint credentials stay in local connection closures and are not part of the catalog, diagnostics, Memento, telemetry, or relay traffic. Secure relay credentials are separately origin-bound in SecretStorage and are sent only in Authorization headers.
  • Activation subscribes only to the root catalog. It never hydrates session/chat channels, mass-subscribes, enables migration, or restarts VS Code. The reusable adapter is default-deny; the installed verified integration grants only an exact, current owner-selected host-restoration request. This is not an import, SDK-session-ID conversion, replacement conversation, or vscode.lm call.

Reusable source interface

src\native\index.ts exports the local adapter. activate() returns nativeCatalog, safe secureStatus(), and trusted local registerNativeReadinessInspector(...) when the desktop context is available. No credential or endpoint secret is exported.

API Behavior
discoverNativeHosts(userDataPaths, options?) Returns safe host descriptors/local transport capabilities and diagnostic counts. Tokens and addresses are not returned as descriptor fields.
NativeCatalog.start(), refresh(), list(), onDidChange() Discovers hosts automatically and lists { hostId, sessionURI, summary }. Identical URIs on different hosts remain distinct.
catalog.subscribeSession(hostId, sessionURI) Requires trusted authorization and verified readiness for that exact discovered host/session before subscribing, including cached channels. Its lease provides state(), visible chats(), onEvent(), and close().
catalog.subscribeChat(hostId, sessionURI, chatURI, options?) Requires both parent-session and chat-operation authorization before any subscribe RPC. Only then hydrates the selected parent and verifies the exact chat against snapshot.state.chats. No unknown chat is subscribed. Its lease provides state(), serverSeq, onEvent(), retained-history access, and close().
chat.loadRetainedHistory({ maxPages?, signal? }) Follows the host's opaque cursor using fetchTurns; only ordered chat/turnsLoaded actions load history. Returns { state, complete, reason }.
NativeAgentHostClient.connect(host, options?) Lower-level local client with refreshSessions(), listSessions(), guarded subscriptions, events, and close(). Without subscriptionPolicy, only catalog access is allowed.
NativeClientOptions.subscriptionPolicy, NativeCatalogOptions.subscriptionPolicy Constructor-only trusted integration interface; never a mobile request parameter. Provides getSelection(context) and non-mutating inspectSession(context, signal). Secure integration only selects an exact advertised target after verified device control receives an explicit broker command.
chat.sendTurn(text, { signal? }), chat.cancelTurn(turnId, { signal? }) Require interactive native chat and matching selection authority: "explicit-local" for local owner selection, or "verified-broker-device" for authenticated broker selection. Resolve only on a matching host action echo; reject rejection/close/unconfirmed delivery. No remote request is relabeled local.

The official @microsoft/agent-host-protocol@0.9.0 client supplies JSON-RPC handling; official session/chat reducers maintain state after ordered snapshot hydration. The package's 0.9 AhpStateMirror is deliberately not used because it does not handle chat state. Node16 TypeScript module output preserves CommonJS extension loading and real dynamic ESM imports; no eval or function-constructor loader is used.

Native tool calls, public activity, assistant output, user messages, input-needed state, and provider errors remain in the original native loop. The adapter never advertises tools, changes active-client ownership or replaces customizations. Phone Review can answer actual pending tool confirmations and user questions only after explicit owner action, and can change a source-advertised session autoApprove mode after separate danger confirmation. No global setting, sandbox, organization policy or authentication boundary is overridden. It declines server-initiated resource requests. Reasoning parts and opaque provider _meta/encrypted fields are not exposed. Changes and pending-tool review read only their actual advertised content references through AHP resourceRead, with bounds and explicit unavailable results. See the review contract.

Subscription/adoption authorization boundary

Subscribing is not necessarily read-only. For eligible legacy copilotcli sessions, the native host can write adoption metadata while handling a session subscription. actionPolicy: "observe-only" blocks turn dispatch; it does not make hydration side-effect-free. subscribeChat must not bypass this boundary through its implicit parent subscription.

src\native\authorization.ts exports policy types through src\native\index.ts. A trusted local owner-selection UI or verified broker/device integration supplies a policy. The secure integration installs a policy whose selection set is initially empty and whose readiness inspector is initially unavailable. Only authenticated, explicitly selected, advertised targets can enter that set; missing readiness evidence still blocks hydration. Review does not change migration settings or bypass this authorization boundary.

Policy method/type Required behavior
getSelection(context): NativeSelectionDecision Reads trusted, current owner-selection state synchronously. Return { kind: "unselected" }, { kind: "denied" }, or { kind: "selected", selection }.
NativeOwnerSelection Contains exact hostId, exact sessionURI, non-secret issuer-controlled selectionId revision, and authority: "local-owner" \| "verified-broker-device". Scope matching is exact, with no wildcard or inferred session-ID conversion.
NativeSubscriptionContext Contains safe host metadata, a detached catalog summary, the exact host/session, operation: "session" \| "chat", and chatURI for chat checks. A policy may restrict particular chats as well as their parent. No endpoint credential, transport, or client is passed to policy callbacks.
inspectSession(context, signal): NativeHydrationAssessment Obtains non-mutating, authoritative evidence for that exact host/session. The hook must not subscribe as a probe, change settings, restart an editor, or inspect private Copilot journals. Honor cancellation; the adapter bounds the wait and suppresses raw inspection errors.
{ kind: "native-existing", scope } May be returned only when the trusted inspector has established that the host already owns this native session. A provider label, URI, successful connection, or presence in listSessions is not this proof.
{ kind: "owner-approved-host-restore", scope, selectionId } Authorizes a host-controlled restoration, not a claim that the session is already hydrated. Requires the exact current verified-broker selection revision and an advertised source. No wire field can manufacture this grant.
{ kind: "legacy-copilotcli", scope, eligibility, configuration } Requires eligibility: "eligible" and configuration: { key: "chat.agentSessions.migrateLegacyCopilotCli", valueAtHostStartup: "enabled" }. Ineligible, disabled, or unverified facts fail closed.
{ kind: "legacy-unsupported" \| "unverified", scope } Blocks hydration with a precise limitation. Use unverified when authoritative native state, eligibility, or effective configuration cannot safely be established.

The policy is an integration trust boundary, not an authentication implementation. Its callbacks must be installed by trusted code and bound to a verified owner/device or explicit local owner selection. Authority labels and selection IDs are not authentication proof on their own. Never return a selection by merely reflecting a raw mobile ownerAuthorized boolean, a claimed owner/device ID, or other unverified request fields. Subscription arguments cannot supply or replace the policy. Broker authentication, authorization, and explicit selection must already have been verified before the trusted policy reports a selection.

Both parent and chat checks complete before a chat request's first subscribe RPC. Selection is checked again immediately before sending and before returning state; unknown/disappeared sessions are rejected. Every newly requested lease, even for an already-cached channel, needs authorization. Changing the selection revision or returning unselected/denied invalidates prior leases: state access and new history reads are denied, and subsequent progress is suppressed. Close revoked leases to release idle observers promptly. Revocation/cancellation cannot undo adoption already authorized and sent to the native host.

AHP 0.9 catalog metadata does not prove universal legacy migration readiness. The reusable adapter therefore supplies no permissive inspector. The installed integration separately opts into host-controlled restoration after the verified owner explicitly selects an advertised source. It does not assert native-existing, infer a legacy twin, or change the host's settings.

The experimental Insiders setting chat.agentSessions.migrateLegacyCopilotCli is default-off and migration permission is frozen at startup. A currently enabled setting alone is insufficient: the inspector must verify the already-effective startup configuration of the same target host, not a different Stable/Insiders window. The adapter never enables it or reloads/restarts an editor. Its migration path applies only to eligible legacy Copilot CLI sessions and can preserve their raw SDK/journal identity. Ordinary legacy Ask/Edit/Agent chats are not covered; exporting/importing still creates a separate identity.

Useful errors include subscription-policy-required, subscription-denied, session-not-selected, subscription-scope-mismatch, native-state-unverified, migration-config-unverified, migration-disabled, migration-eligibility-unverified, migration-ineligible, legacy-session-unsupported, and subscription-check-timeout. These messages contain no host tokens, titles, or raw policy errors.

Retention, limits, and cancellation

  • The host owns retained history. The adapter keeps only bounded, transient subscription state in memory and clears it on close; it never writes native transcripts to Mocha Memento or cloud storage.
  • complete: true means the host exposed all currently retained turns (no remaining cursor), not that every historic local, cloud, or deleted chat was recovered. Current installed host handlers can return an empty no-op fetchTurns result; a cursor with no corresponding progress returns complete: false, reason: "host-no-progress". A page ceiling returns "page-limit".
  • Chronicle reindex rebuilds/uploads local history; it is not a universal cloud restore. This adapter does not invoke it.
  • view.turns is advisory. A larger snapshot is not silently sliced. Default hard bounds include 8 hosts, 500 sessions/10 catalog pages per host, 16 subscribed channels per host, 2,000 completed turns/8 MiB per state, 16 MiB combined state/buffers per host, 8 MiB frames, and 128 queued frames/8 MiB transport buffering. Exceeding state/history limits refuses the snapshot or closes the affected host stream, leaving original history unchanged. Diagnostics mark partial catalogs.
  • Dispatch uses a notification with a fresh turn UUID and monotonically increasing client sequence, never a request ID. Send success alone is not acceptance. Unconfirmed delivery is uncertain and is never automatically replayed; inspect and resubscribe to the original chat before retrying.
  • Aborting an RPC or dispatch wait does not undo a host-side operation or implicitly cancel an active turn. Explicit cancelTurn targets the exact active turn, also awaiting a host echo. Closing a lease releases subscriptions/listeners; closing the client rejects pending work and closes its transport. No native turn is cancelled merely because this observer disconnects.

Integration boundary and source/install distinction

There is no verified open-in-VS-Code command/URI in this adapter; it does not create a replacement chat. Native discovery does not imply support for all historical Copilot chat surfaces.

The existing legacy room protocol is not an authorization boundary for native traffic. Native metadata/results/events use only the verified device /ws/control protocol, with bounded transient projection, exact advertised target checks, guarded selection, and real native receipts. They never use legacy hello/history snapshots, account-ID assertions, shared-token auth, or Mocha Memento. Native readiness, real frontend approval, and authorized rollout validation remain required.

These are source/build changes only. Existing installed Mocha extensions and packaged VSIX files are unchanged; nothing is installed, published, or restarted automatically. Fixture tests verify the protocol and an isolated Windows named-pipe upgrade, not a real user turn or approval.

References: VS Code local endpoint contract, AHP 0.9 types, official TypeScript client, Insiders legacy migration and startup gate.

Existing independent mobile-session workflow

  1. Install the extension in VS Code 1.93 or newer.
  2. Sign in to GitHub Copilot in VS Code.
  3. Configure mocha.relayUrl and the required mocha.accountId.
  4. Run Mocha: Create Legacy Independent Session or Mocha: Import Exported Chat Transcript.
  5. Open Mocha: Show Legacy Independent Sessions to view legacy status, history, and the legacy room code. This is not verified device pairing.

The account ID must exactly match the account ID used by the Mocha mobile app. There is no demo account or implicit account fallback.

Explicit chat handoff

The public VS Code extension API does not enumerate arbitrary native Copilot history. Supported Agent Hosts can instead expose their own catalog/retained history via the local AHP adapter above. Mocha does not inspect or scrape VS Code or Copilot private storage. Export/import remains a separate, independent-session workflow:

To hand off an existing chat:

  1. Export the chat using the export action provided by your installed VS Code or Copilot Chat version.
  2. Run Mocha: Import Exported Chat Transcript.
  3. Select one or more JSON, JSON Lines, text, or Markdown transcript files.

Imported history is displayed in its Mocha session panel and used as context for subsequent prompts. Each imported file becomes a separate Mocha-owned session.

Commands

Command Purpose
Mocha: Connect Mocha (Secure Device Pairing) Starts explicit browser owner review or reconnects an already verified device; no legacy fallback.
Mocha: Disconnect Secure Device and Forget Pairing Disconnects observation/control and deletes this origin's local device credential; native work continues.
Mocha: Show Legacy Independent Sessions Lists extension-owned legacy model-text sessions, not native chats.
Mocha: Create Legacy Independent Session Creates an empty, persistent independent Copilot-powered session.
Mocha: Import Exported Chat Transcript Creates sessions from explicitly selected transcript files.
Mocha: Disconnect and Remove Legacy Independent Session Disconnects/removes a selected independent legacy session.
Mocha: Inspect Native Agent Hosts (Local Only) Refreshes local native discovery and displays count-only diagnostics; no mobile pairing or native writes.

The extension activates after VS Code starts for list-only native discovery and credential-verified secure control restoration. Existing independent sessions retain their separate restoration path. mocha.connect now means secure pairing/control and never creates an independent chat; mocha.showPanel remains the legacy session-view alias. Status indicators explicitly distinguish Mocha Secure from Mocha Legacy.

Settings

Setting Required Description
mocha.accountId Legacy only Explicit independent-session account namespace. Never trusted for secure ownership.
mocha.relayUrl Yes Secure mode uses the user-level origin only: HTTPS or verified loopback HTTP. Defaults to local development.
mocha.token Legacy only Independent-session shared token. Secure device credentials use SecretStorage, not settings.
mocha.model No Preferred GitHub Copilot model family. The first available Copilot model is used when empty.

If mocha.accountId is missing, commands that create or import sessions show a setup error and offer to open the setting.

Runtime readiness and cancellation

  • A mobile prompt selects Copilot models afresh, activates an installed inactive Copilot provider when needed, and waits up to three seconds for model registration changes. It does not sign in automatically or bypass model consent.
  • Model availability, permission, and quota errors are reported as error statuses, not assistant replies or evidence that the desktop disconnected. Mocha checks existing model access; first-use consent may still require action in VS Code.
  • A missing model can be reselected once before a response starts. A started response is never automatically replayed after an error, cancellation, or reconnect.
  • { "type": "cancel", "id": "request-id" } signals that active or queued request; omit id to cancel all pending requests. { "type": "cancel-ack", "id": "request-id", "accepted": true } acknowledges signalling matching work, not undoing prior side effects. Cancellation uses VS Code cancellation tokens.
  • A newer connection replaces the older session owner. The older window stops reconnecting automatically. Authentication, protocol, and oversized-message closures also pause reconnects rather than retrying indefinitely.

Session history and privacy

  • Mocha persists only independent sessions created or imported through this extension, never native adapter transcripts.
  • User-selected transcript imports are limited to 2 MB per file.
  • The extension sends session snapshots to the configured relay for cross-device replay.
  • The 2 MB transport limit includes the JSON envelope. A larger snapshot is not sent: local source history and the existing relay snapshot are preserved, and a history-sync error is shown. Source-owned pagination is not implemented yet.
  • The relay bounds stored history and redacts common credential patterns before persistence or replay.
  • Live prompts and replies still pass through the configured relay.
  • Use HTTPS/WSS and configure mocha.token when the relay is reachable outside a trusted local environment.

Limitations

  • Native discovery is limited to sessions actually exposed by a supported, negotiated AHP host, not arbitrary Copilot tabs or archives.
  • Imported conversations become independent Mocha sessions; they are not written back into native Copilot chat history.
  • The vscode.lm path is a model-text conversation, not the full native Copilot agent/tool execution loop.
  • Mobile history display requires a compatible Mocha app that handles the relay's history snapshot protocol.
  • Native transport is wired to verified device control, but source hydration remains blocked without a trusted readiness inspector. Frontend consent/native rendering and an authorized installed rollout must be validated separately.

Development verification

npm run test:secure covers S256 pairing, SecretStorage, authoritative device verification, scoped control, bounded history/progress, teardown, HTTP/WS transport isolation and UI trust boundaries. npm run test:authorization covers focused adoption/selection guards; npm run test:native covers AHP adapter regressions. npm test runs these with the preserved independent-session/transcript suite. Tests never read real endpoint registries, send real user turns, approve tools, change migration configuration, or install an extension.

Package and install

From this directory, run npm test and the additional approval suites node --test dist-test/test/nativeApprovals.test.js dist-test/test/secureApprovals.test.js. Use npm version patch --no-git-tag-version for an authorized version increment, then package with the existing VSCE tool and vscode:prepublish build:

npx.cmd --no-install @vscode/vsce package --allow-missing-repository --no-rewrite-relative-links --skip-license --out mocha.mocha-client-<version>.vsix

Keep runtime dependencies included; do not use --no-dependencies. The existing manifest has no repository/license declaration, so the command explicitly permits those omissions without adding an invented license or publishing to the Marketplace. Secret scanning remains enabled.

Install the resulting VSIX with Extensions: Install from VSIX... in the intended Stable or Insiders editor/profile. Existing pairing remains in that profile's origin-scoped SecretStorage. An update does not move native chats, restart their source host, or enable relay billing. Reload the editor only when safe for current work. Verify the installed version, user-level relay origin, verified device connection, and an explicitly selected native chat before claiming live readiness.

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
  • Your Privacy Choices
  • Consumer Health Privacy
© 2026 Microsoft