agentradar-cli 0.1.5 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -19,4 +19,4 @@ There is a `--trust` flag for unattended runners, where a launch prompt would ha
19
19
 
20
20
  The skill command installs only the package-bundled `agentradar-vendor` markdown skill at `.claude/skills/agentradar-vendor/SKILL.md` in the current project. It does not fetch or require access to the private AgentRadar repository.
21
21
 
22
- Claude authentication stays separate. Preferred: use interactive `/login` with the vendor's claude.ai account. A `CLAUDE_CODE_OAUTH_TOKEN` may be stored in the private runner env file when non-interactive Claude authentication is required; the supervisor stages it into a mode-`0600` runtime file before launch. `ANTHROPIC_API_KEY` is prohibited and the supervisor refuses to start when it is set.
22
+ Claude authentication stays separate. On macOS, the runner reuses the vendor's existing Claude Code OAuth login by extracting only `claudeAiOauth.accessToken` from the `Claude Code-credentials` Keychain item into a mode-`0600` runtime file; it never copies the credential profile into the isolated config. An explicit `CLAUDE_CODE_OAUTH_TOKEN` in the private runner env remains supported and takes precedence. `ANTHROPIC_API_KEY` is prohibited and the supervisor refuses to start when it is set.
package/dist/setup.js CHANGED
@@ -205,7 +205,7 @@ export async function setupVendorAgent(deps = {}) {
205
205
  : `Claude Code will ask you to trust ${projectPath} on first launch — approve it there. Not pre-accepted, because that would trust everything already in the folder, not just this MCP. Re-run with --trust for unattended onboarding.`);
206
206
  log(`Runner installed → ${runnerEnv}`);
207
207
  log(`Start it with: agentradar runner start ${approved.runnerId}`);
208
- log("Claude Code will use your existing /login session. ANTHROPIC_API_KEY is prohibited; a securely stored CLAUDE_CODE_OAUTH_TOKEN is also supported.");
208
+ log("On macOS the runner uses your existing Claude Code Keychain OAuth credential; an explicit CLAUDE_CODE_OAUTH_TOKEN is also supported. ANTHROPIC_API_KEY is prohibited.");
209
209
  return;
210
210
  }
211
211
  throw new Error("AgentRadar setup code expired; run setup again");
@@ -51,10 +51,10 @@ set +a
51
51
  : "${AR_BASE:?AR_BASE required (the agent working dir)}"
52
52
  : "${AWP_MCP_URL:?AWP_MCP_URL required}"
53
53
  : "${AWP_BEARER:?AWP_BEARER required}"
54
- # CLAUDE_CODE_OAUTH_TOKEN is OPTIONAL. If SET → claude uses the setup-token (bills "API Usage",
55
- # subject to the org spend cap). If UNSET → claude falls through to SUBSCRIPTION OAuth (keychain login,
56
- # a one-time `/login`) → draws on the Max plan's included usage. Either way it's claude.ai auth only —
57
- # ANTHROPIC_API_KEY is still hard-refused below (never a pay-as-you-go key).
54
+ # CLAUDE_CODE_OAUTH_TOKEN is an OPTIONAL explicit override. When unset on macOS, section 2b extracts
55
+ # claudeAiOauth.accessToken from Claude Code's existing Keychain credential into the same private-file
56
+ # handoff. With neither source, Claude uses its normal interactive auth path. ANTHROPIC_API_KEY remains
57
+ # hard-refused below.
58
58
  : "${CLAUDE_CODE_OAUTH_TOKEN:=}"
59
59
  : "${MCP_CONFIG:?MCP_CONFIG required (path to awp-only.json)}"
60
60
  TMUX_SESSION="${TMUX_SESSION:-${AGENT_NAME}}"
@@ -135,16 +135,26 @@ _BEARER_FILE="${_SECRETS_DIR}/awp_bearer"
135
135
  ( umask 077; printf '%s' "${AWP_BEARER}" > "${_BEARER_FILE}" )
136
136
  AWP_BEARER_FILE="${_BEARER_FILE}"
137
137
  unset AWP_BEARER # drop from the supervisor's exported env → feeder no longer inherits it; ps eww clean
138
- # OAuth setup-token: same treatment. `set -a; . ENV_FILE` EXPORTS CLAUDE_CODE_OAUTH_TOKEN into the
139
- # supervisor env, from which the feeder (spawned WITHOUT env -i) would inherit it → ps eww leak. So when
140
- # it's set, stage it to a 0600 file and UNSET the raw var here (mirror of the bearer). ensure_agent then
141
- # passes ONLY AR_OAUTH_TOKEN_FILE (the path) on the scrubbed env -i line, and the sh wrapper reads it into
142
- # claude's env just before exec. When UNSET (subscription-login mode) _OAUTH_TOKEN_FILE stays empty → the
143
- # claude launch is a pure no-op and falls through to subscription OAuth (no API-billing regression).
144
- _OAUTH_TOKEN_FILE=""
138
+ # OAuth token: same treatment. An explicit CLAUDE_CODE_OAUTH_TOKEN still wins. Otherwise, on macOS,
139
+ # Claude Code stores a JSON credential in the "Claude Code-credentials" Keychain item; the env contract
140
+ # needs only its claudeAiOauth.accessToken scalar, not that whole JSON copied into .credentials.json.
141
+ # Pipe Keychain → plutil → a 0600 file so the token never appears in logs, argv, or this supervisor's env.
142
+ _OAUTH_TOKEN_FILE="${_SECRETS_DIR}/oauth_token"
145
143
  if [ -n "${CLAUDE_CODE_OAUTH_TOKEN:-}" ]; then
146
- _OAUTH_TOKEN_FILE="${_SECRETS_DIR}/oauth_token"
147
144
  ( umask 077; printf '%s' "${CLAUDE_CODE_OAUTH_TOKEN}" > "${_OAUTH_TOKEN_FILE}" )
145
+ elif [ "$(uname -s)" = "Darwin" ] && [ -x /usr/bin/security ] && [ -x /usr/bin/plutil ]; then
146
+ _OAUTH_TOKEN_TMP="${_OAUTH_TOKEN_FILE}.$$"
147
+ if ( umask 077; /usr/bin/security find-generic-password -s "Claude Code-credentials" -w 2>/dev/null \
148
+ | /usr/bin/plutil -extract claudeAiOauth.accessToken raw -o "${_OAUTH_TOKEN_TMP}" - 2>/dev/null ) \
149
+ && [ -s "${_OAUTH_TOKEN_TMP}" ]; then
150
+ mv "${_OAUTH_TOKEN_TMP}" "${_OAUTH_TOKEN_FILE}"
151
+ log "loaded Claude Code OAuth credential from macOS Keychain"
152
+ else
153
+ rm -f "${_OAUTH_TOKEN_TMP}"
154
+ _OAUTH_TOKEN_FILE=""
155
+ fi
156
+ else
157
+ _OAUTH_TOKEN_FILE=""
148
158
  fi
149
159
  unset CLAUDE_CODE_OAUTH_TOKEN # out of the supervisor+feeder env (ps eww); staged to the 0600 file above
150
160
  # Vendor MCP-tool creds (#166): the agent's OWN tool API keys (WEBFLOW_TOKEN, PERPLEXITY_API_KEY, …) were
@@ -238,12 +248,10 @@ ensure_agent() {
238
248
  # verified — so the `||` fallback is reliable.) The `/bin/sh -c` wrapper keeps EXTRA_FLAGS word-splitting.
239
249
  # shellcheck disable=SC2086
240
250
  _launch_flags=( ${CLAUDE_EXTRA_FLAGS} --strict-mcp-config --mcp-config="${MCP_CONFIG}" )
241
- # OAuth setup-token (#152): the token was already staged to a 0600 file + UNSET from this env in section
242
- # 2b (so it's off both the supervisor+feeder env / ps eww). Here we only pass AR_OAUTH_TOKEN_FILE (a PATH,
243
- # not the secret) on the env -i line — so the token is NOT in the `env`/claude argv (`ps aux`) either. The
244
- # wrapper below reads the file into CLAUDE_CODE_OAUTH_TOKEN just before exec'ing claude. When it was UNSET
245
- # (subscription-login mode) _OAUTH_TOKEN_FILE is empty → we pass NOTHING token-related and the wrapper's
246
- # read is a no-op → claude falls through to subscription OAuth exactly as before. bash 3.2-safe array form.
251
+ # OAuth (#152): section 2b staged either the explicit token or the macOS Keychain accessToken into a
252
+ # 0600 file and kept the value out of the supervisor+feeder env. Here we pass only that file PATH through
253
+ # env -i; the wrapper reads CLAUDE_CODE_OAUTH_TOKEN immediately before exec'ing Claude. If neither source
254
+ # exists, _OAUTH_TOKEN_FILE is empty and Claude falls back to its normal interactive auth path.
247
255
  _oauth_env=()
248
256
  [ -n "${_OAUTH_TOKEN_FILE}" ] && _oauth_env=( AR_OAUTH_TOKEN_FILE="${_OAUTH_TOKEN_FILE}" )
249
257
  # #166: pass the tool creds as a FILE PATH (AR_TOOL_ENV_FILE), never inline KEY=VALUE on env -i.
@@ -307,8 +315,8 @@ log "starting feeder (${FEEDER_JS}) → session '${TMUX_SESSION}'"
307
315
  # #152: pass AWP_BEARER_FILE (a 0600 PATH), NEVER the raw AWP_BEARER — the feeder reads the file, so the
308
316
  # bearer is not in the feeder process's environment (`ps eww`) or argv. AWP_MCP_URL is not a secret.
309
317
  AWP_MCP_URL="${AWP_MCP_URL}" AWP_BEARER_FILE="${AWP_BEARER_FILE}" TMUX_SESSION="${TMUX_SESSION}" \
310
- AGENT_PID_PATTERN="${AGENT_PID_PATTERN}" CLAUDE_BIN="${CLAUDE_BIN}" AR_OAUTH_TOKEN_FILE="${_OAUTH_TOKEN_FILE}" \
311
- node "${FEEDER_JS}" &
318
+ AGENT_PID_PATTERN="${AGENT_PID_PATTERN}" CLAUDE_BIN="${CLAUDE_BIN}" CLAUDE_CONFIG_DIR="${CLAUDE_CONFIG_DIR}" \
319
+ AR_OAUTH_TOKEN_FILE="${_OAUTH_TOKEN_FILE}" node "${FEEDER_JS}" &
312
320
  FEEDER_PID=$!
313
321
  log "feeder pid ${FEEDER_PID}"
314
322
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentradar-cli",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "Secure AgentRadar vendor setup and skill installer",
5
5
  "type": "module",
6
6
  "bin": {