Skip to content

feat(cli,mcp): take the requester id from the agent session - #165

Merged
V3RON merged 4 commits into
mainfrom
feature/158
Sep 30, 2026
Merged

V3RON merged 4 commits into
mainfrom
feature/158

Conversation

@V3RON

@V3RON V3RON commented Sep 28, 2026

Copy link
Copy Markdown
Contributor

Closes #158

Without --agent-id or SIMLOCK_AGENT_ID, the CLI and simlock mcp now use CLAUDE_CODE_SESSION_ID as claude-code:<id> or CODEX_SESSION_ID as codex:<id>, then the pid as before. One resolveRequesterId in the new src/agent-identity replaces the two copies of the rule. Docs updated in docs/CLI.md and README.md.

Beyond the three comments the spec named, two more comments and one docs/CLI.md sentence were fixed because the change made them false.

Completion conditions

  • Two simlock lease in one Claude Code session, and one Codex session: same requester, second gets REQUESTER_ALREADY_LEASED naming the first lease. Checked with a throwaway e2e run against the fake driver.
  • Against a gateway, lease --detach then simctl with no --lease runs on that device; another session's id is refused. Same throwaway e2e run.
  • status and list --leases show claude-code:<id> / codex:<id>. Same run.
  • simlock mcp leases under the CLI's id; a CLI lease after it gets REQUESTER_ALREADY_LEASED. Same run, plus the unit test "the CLI and simlock mcp resolve the same session-derived requester id".
  • SIMLOCK_AGENT_ID beats the session id; --agent-id beats both. Unit tests and the e2e run.
  • No ids at all: pid-derived, unchanged. New CLI and MCP fallback tests.
  • Empty session variable skipped. Unit test, and the e2e run fell back to the pid.
  • Docs: "Agent identity", "simlock mcp", README "MCP integration".

Checks: typecheck, typecheck:e2e, lint, format:check, unit (1872 passed), e2e (60 passed). Every new path was broken and failed on a named assertion.

Review

Spec review: 4 findings, 1 fixed. Code review: 9 findings, 5 fixed.

Rejected:

  • Extra comment and doc edits beyond the three the spec named (raised twice) — architecture rule 13 requires them; the change made them false.
  • Extra test pinning Claude Code over Codex when both are set — the spec says "the first table row"; the code review showed swapping rows stayed green without it.
  • Parallel sub-agents and simlock mcp in one session now share one requester and one lease (raised twice) — this is the specified outcome.
  • Empty SIMLOCK_AGENT_ID resolves to "" and no test pins it — unchanged behaviour; the spec keeps "defined wins, as today".
  • The e2e harness passes process.env through, so under an agent tool e2e runs as the session id — out of scope here; the suite passes with and without the variable.

Written by an agent.

🤖 Generated with Claude Code

https://claude.ai/code/session_01E7hp6xYT1cA3BXRYiUukby


Generated by Claude Code

Without --agent-id or SIMLOCK_AGENT_ID, the CLI and simlock mcp now use
the Claude Code or Codex session id as <tool>:<id> before falling back
to the pid. One shared resolveRequesterId in src/agent-identity replaces
the two copies of that rule.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E7hp6xYT1cA3BXRYiUukby
@V3RON

V3RON commented Sep 29, 2026

Copy link
Copy Markdown
Contributor Author

Manual verification (real iOS simulators, inside a Claude Code session)

All four checks pass on feature/158 (88678bb), using a throwaway SIMLOCK_HOME.

Check Result
1. Session id becomes the requester Pass. The grant, list --leases and status all show claude-code:<CLAUDE_CODE_SESSION_ID>.
2. Second lease from the same session Pass. Exit 13, REQUESTER_ALREADY_LEASED, and the message names the first lease id.
3. simlock mcp resolves the same id Pass. lease_simulator was refused with REQUESTER_ALREADY_LEASED naming the CLI's lease.
4. Precedence and fallbacks Pass. SIMLOCK_AGENT_ID gave explicit-agent, --agent-id gave flag-agent, CODEX_SESSION_ID gave codex:codex-thread-1, and an empty CLAUDE_CODE_SESSION_ID gave a bare pid-derived number.

Not covered: the gateway passthrough case (simlock simctl with no --lease against a gateway). The e2e run exercises it.

@V3RON

V3RON commented Sep 29, 2026

Copy link
Copy Markdown
Contributor Author

Known limitation: simlock mcp under Codex

Found while verifying on real simulators. Under Codex, the CLI gets codex:<id> but simlock mcp gets a pid-derived mcp:<pid>.

Codex starts MCP servers without its own CODEX_* variables. I checked this with a stub MCP server that printed its CODEX_* environment under Codex 0.159.0, and it was empty. Claude Code does pass its session variable through, and that path passes. MCP itself gives stdio servers only a limited environment and has no session id for stdio, so this is client behaviour we cannot rely on.

Effect: an agent that leases through both the CLI and MCP in one Codex session is two requesters and can hold two leases. Each side still enforces one lease per requester.

Decision: leave MCP as it is. The PR now says this in docs/CLI.md, the README and KNOWN-PITFALLS.md. If it matters later, the fix is an optional agentId argument on lease_simulator, filled by the agent from its shell's session variable.

@V3RON
V3RON merged commit f814ea4 into main Sep 30, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Stable agent id from the agent session

2 participants