agent_profile/adapter/
cursor.rs1use std::path::PathBuf;
10
11use super::{
12 Adapter, AdapterEvidence, AdapterMetadata, Capability, CapabilityClaim, CapabilityState,
13 EnvOverride, Mechanism, PathKind, PlanContext, PlannedLaunch, SupportLevel, profile_dir,
14};
15use crate::config::AppRoot;
16use crate::error::Result;
17use crate::name::ProfileName;
18
19const VAR: &str = "CURSOR_CONFIG_DIR";
20
21static METADATA: AdapterMetadata = AdapterMetadata {
22 id: "cursor",
23 executable: "cursor-agent",
24 mechanism: Mechanism::Env(VAR),
25 support: SupportLevel::Experimental,
26 evidence: AdapterEvidence {
27 mechanism_id: "cursor-config-dir-v1",
28 verified_at: "2026-11-09",
29 upstream_version: "2026.11.05-86047df",
30 source_url: "https://cursor.com/docs/cli/reference/configuration",
31 notes: "the agent's one pre-network write moved under CURSOR_CONFIG_DIR \
32 (`+ f /home/agent/probe-target/cli-config.json`) while the default \
33 `~/.cursor/cli-config.json` and the watched XDG fallback `.config/cursor` \
34 recorded nothing (§9 outcome 1); the probe installed by the vendor script, \
35 which refuses a version argument (§12), so upstream_version is the \
36 `version-extracted` value; `CURSOR_API_KEY` is the documented bypass variable \
37 (help: `--api-key <key> ... (can also use CURSOR_API_KEY env var)`); no \
38 login/auth step ran and no credential-bearing file appeared",
39 },
40 capabilities: &[
41 CapabilityClaim {
42 capability: Capability::ConfigIsolation,
43 state: CapabilityState::Supported,
44 basis: "measured: `+ f /home/agent/probe-target/cli-config.json` — the agent's one \
45 pre-network write followed CURSOR_CONFIG_DIR into the target, and the watched \
46 fallback location recorded `f /home/agent/.config/cursor (absent)`, so the \
47 XDG fallback was not chosen",
48 },
49 CapabilityClaim {
50 capability: Capability::CredentialIsolation,
51 state: CapabilityState::Unknown,
52 basis: "unmeasured: where stored credentials live was not established (Q4) — no \
53 login/auth step ran and no credential-bearing file surfaced anywhere in the \
54 delta; `CURSOR_API_KEY` (strings: `documented CURSOR_API_KEY: present`) is \
55 the documented bypass variable, and no stored-credential observation was made",
56 },
57 CapabilityClaim {
58 capability: Capability::StateIsolation,
59 state: CapabilityState::Unknown,
60 basis: "unmeasured: the agent wrote only `cli-config.json` before it needed network \
61 access, so no session/state file was observable — the delta tail names \
62 nothing beyond `+ f /home/agent/probe-target/cli-config.json`",
63 },
64 ],
65 env: &[EnvOverride { name: VAR, sensitive: false }],
66 conflicts: &[],
67 credential_env: &["CURSOR_API_KEY"],
68};
69
70#[derive(Debug, Clone, Copy)]
72pub struct Cursor;
73
74impl Adapter for Cursor {
75 fn metadata(&self) -> &'static AdapterMetadata {
76 &METADATA
77 }
78
79 fn paths(&self, root: &AppRoot, profile: &ProfileName) -> Vec<(PathBuf, PathKind)> {
80 vec![(profile_dir(root, profile, METADATA.id), PathKind::Dir)]
85 }
86
87 fn plan(&self, ctx: &PlanContext<'_>) -> Result<PlannedLaunch> {
88 METADATA.mechanism.plan(self, ctx)
89 }
90}