agent_profile/adapter/
cline.rs1use std::path::PathBuf;
11
12use super::{
13 Adapter, AdapterEvidence, AdapterMetadata, Capability, CapabilityClaim, CapabilityState,
14 EnvOverride, Mechanism, PathKind, PlanContext, PlannedLaunch, SupportLevel, profile_dir,
15};
16use crate::config::AppRoot;
17use crate::error::Result;
18use crate::name::ProfileName;
19
20const VAR: &str = "CLINE_DATA_DIR";
21
22static METADATA: AdapterMetadata = AdapterMetadata {
23 id: "cline",
24 executable: "cline",
25 mechanism: Mechanism::Env(VAR),
26 support: SupportLevel::Experimental,
27 evidence: AdapterEvidence {
28 mechanism_id: "cline-cli-v1",
29 verified_at: "2026-11-09",
30 upstream_version: "3.0.74",
31 source_url: "measured",
32 notes: "measured in a sandbox at 3.0.73: --help lists `CLINE_DATA_DIR` as a Configuration \
33 directory and `--config`/`--data-dir` as directory flags; a launch with the env var set \
34 exits 0, but the delta at both watched locations (target and default) was \
35 `(no change: nothing was created, moved or removed at the watched locations)` — the \
36 agent writes nothing before it needs the network (§9 outcome 5); the strings scan \
37 found ANTHROPIC_API_KEY, CLINE_API_KEY, OPENAI_API_KEY and OPENROUTER_API_KEY \
38 documented; Q1 unanswered (no isolation or sandbox-mode side effects were observed \
39 before the agent needed the network); three `Unknown`s ⇒ Experimental under Gate C/D6",
40 },
41 capabilities: &[
42 CapabilityClaim {
43 capability: Capability::ConfigIsolation,
44 state: CapabilityState::Unknown,
45 basis: "unmeasured: the probe's delta at both watched locations — the target and the default \
46 `/home/agent/.cline` — was `(no change: nothing was created, moved or removed at the \
47 watched locations)`, so whether the agent's own config writes would follow CLINE_DATA_DIR \
48 was not observable while the agent writes nothing before it needs the network \
49 (§9 outcome 5)",
50 },
51 CapabilityClaim {
52 capability: Capability::CredentialIsolation,
53 state: CapabilityState::Unknown,
54 basis: "unmeasured: no login/auth step ran and no credential-bearing file surfaced anywhere \
55 in the delta, so where stored credentials live was not established; the documented \
56 bypass variables are `CLINE_API_KEY`, `ANTHROPIC_API_KEY`, `OPENAI_API_KEY` \
57 and `OPENROUTER_API_KEY` (strings: `documented CLINE_API_KEY: present`)",
58 },
59 CapabilityClaim {
60 capability: Capability::StateIsolation,
61 state: CapabilityState::Unknown,
62 basis: "unmeasured: the agent's only pre-network write was `cli-node-extra-ca-certs.pem`, \
63 present at the default location at baseline, and the measured delta recorded \
64 `(no change: nothing was created, moved or removed at the watched locations)`, so no \
65 state write was observable to place (§9 outcome 5)",
66 },
67 ],
68 env: &[EnvOverride { name: VAR, sensitive: false }],
69 conflicts: &[],
70 credential_env: &["CLINE_API_KEY", "ANTHROPIC_API_KEY", "OPENAI_API_KEY", "OPENROUTER_API_KEY"],
71};
72
73#[derive(Debug, Clone, Copy)]
75pub struct Cline;
76
77impl Adapter for Cline {
78 fn metadata(&self) -> &'static AdapterMetadata {
79 &METADATA
80 }
81
82 fn paths(&self, root: &AppRoot, profile: &ProfileName) -> Vec<(PathBuf, PathKind)> {
83 vec![(profile_dir(root, profile, METADATA.id), PathKind::Dir)]
87 }
88
89 fn plan(&self, ctx: &PlanContext<'_>) -> Result<PlannedLaunch> {
90 METADATA.mechanism.plan(self, ctx)
91 }
92}