Skip to main content

agent_profile/adapter/
claude.rs

1// Copyright (c) 2026 Costas Kirgoussios
2//
3// This software is licensed under the PolyForm Noncommercial License 1.0.0.
4// You may obtain a copy of the License at:
5// https://polyformproject.org/licenses/noncommercial/1.0.0/
6
7//! Claude Code: `CLAUDE_CONFIG_DIR` per profile (SP2 design ยง5.1).
8
9use 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 = "CLAUDE_CONFIG_DIR";
20
21static METADATA: AdapterMetadata = AdapterMetadata {
22    id: "claude",
23    executable: "claude",
24    mechanism: Mechanism::Env(VAR),
25    support: SupportLevel::Proven,
26    evidence: AdapterEvidence {
27        mechanism_id: "claude-config-dir-v1",
28        verified_at: "2026-11-09",
29        upstream_version: "2.1.319",
30        source_url: "https://code.claude.com/docs/en/authentication",
31        notes: "CLAUDE_CONFIG_DIR relocates .credentials.json and keys the macOS Keychain entry per directory; \
32                ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN, CLAUDE_CODE_OAUTH_TOKEN, CLAUDE_CODE_OAUTH_REFRESH_TOKEN, \
33                ANTHROPIC_PROFILE, CLAUDE_CODE_USE_BEDROCK, CLAUDE_CODE_USE_VERTEX and CLAUDE_CODE_USE_FOUNDRY override it (binary strings measured)",
34    },
35    capabilities: &[
36        CapabilityClaim {
37            capability: Capability::ConfigIsolation,
38            state: CapabilityState::Supported,
39            basis: "cited: user settings live in the config directory; project .claude/settings*.json \
40                    and .mcp.json still layer on top",
41        },
42        CapabilityClaim {
43            capability: Capability::CredentialIsolation,
44            state: CapabilityState::Conditional,
45            basis: "measured: credential environment variables override it; the per-directory \
46                    .credentials.json and macOS Keychain entry are cited, not measured",
47        },
48        CapabilityClaim {
49            capability: Capability::StateIsolation,
50            state: CapabilityState::NotGuaranteed,
51            basis: "cited: history and project state moving with the directory is community-sourced only",
52        },
53    ],
54    env: &[EnvOverride { name: VAR, sensitive: false }],
55    conflicts: &[],
56    credential_env: &[
57        "ANTHROPIC_API_KEY",
58        "ANTHROPIC_AUTH_TOKEN",
59        "CLAUDE_CODE_OAUTH_TOKEN",
60        "CLAUDE_CODE_OAUTH_REFRESH_TOKEN",
61        "ANTHROPIC_PROFILE",
62        "CLAUDE_CODE_USE_BEDROCK",
63        "CLAUDE_CODE_USE_VERTEX",
64        "CLAUDE_CODE_USE_FOUNDRY",
65    ],
66};
67
68/// The Claude Code adapter.
69#[derive(Debug, Clone, Copy)]
70pub struct Claude;
71
72impl Adapter for Claude {
73    fn metadata(&self) -> &'static AdapterMetadata {
74        &METADATA
75    }
76
77    fn paths(&self, root: &AppRoot, profile: &ProfileName) -> Vec<(PathBuf, PathKind)> {
78        vec![(profile_dir(root, profile, METADATA.id), PathKind::Dir)]
79    }
80
81    fn plan(&self, ctx: &PlanContext<'_>) -> Result<PlannedLaunch> {
82        METADATA.mechanism.plan(self, ctx)
83    }
84}