Member Junction
    Preparing search index...

    Drives Claude Code through its headless CLI. This is the ONLY Claude Code adapter.

    An SDK-based adapter was built and then deliberately removed. The SDK offers a programmatic permission callback (canUseTool) and in-process MCP tools, both genuinely useful — but it runs IN-PROCESS in Node, and no sandbox executor can place an in-process library inside a container.

    That trade does not survive scrutiny: it buys better permission hooks at the cost of any process isolation, for a feature whose entire purpose is executing an autonomous agent's shell commands. Worse, an SDK-backed agent configured with provider: 'docker' would run outside its sandbox while the config claimed otherwise — the same false-containment failure this design refuses elsewhere. And the asymmetry is decisive: the CLI's missing permission hook is fixable (an MCP permission-prompt tool), while the SDK's missing containment is not.

    Two incidental findings that removed the remaining arguments for it: the SDK's typing advantage largely evaporated in practice (its message union is too broad to narrow against, so the adapter read fields structurally anyway — exactly what the CLI adapter does), and the SDK is not dependency-free — it ships a ~259 MB platform-specific claude binary. It wraps the same program this adapter invokes.

    So there is one Claude path, and it works in all three deployments: local spawn, local container, cloud container.

    Hierarchy (View Summary)

    Index

    Constructors

    Properties

    activeProcess: HarnessProcess = null
    config: HarnessSessionConfig = null
    sessionId: string = undefined

    Accessors

    • get DidResumeSession(): boolean

      Whether this session actually continued HarnessSessionConfig.ResumeSessionId.

      Default false: a harness that cannot resume, or one offered no prior session, starts cold and must be sent the full conversation. Adapters that DO resume MUST override this and report truthfully — the caller sends only the newest message when it returns true, so a false positive leaves the harness answering a question it never saw the context for.

      Deliberately separate from CapabilitySettings.SessionResume. That flag says the adapter CAN resume in principle; this says it DID, this time. A stale or pruned session id makes the two disagree, and only the second one is safe to branch the turn input on.

      Returns boolean

    • get ReportedModel(): string

      The model the harness actually used, if it reports one.

      Adapters that can observe this SHOULD override it. Accounting resolves AIPromptRun.ModelID from this first and only falls back to the harness row's declared model, because a harness left to choose its own model will — and billing a run against a model it never used is worse than having no attribution at all, since it looks authoritative.

      Returns string

    Methods

    • Maps MJ's posture onto Claude Code's permission vocabulary.

      Conservative at both ends, deliberately:

      • strict adds NOTHING, leaving Claude Code's default prompting in place. Headless, those prompts have nowhere to go and every call denies — the correct outcome for a posture whose contract is "no mutation without a human" when MJ has no approval channel yet. Observably useless beats quietly permissive.
      • auto uses acceptEdits, NOT bypassPermissions. Edits inside the workspace proceed while genuinely dangerous operations still gate; using bypass here would make auto and dangerous the same setting under two names.
      • dangerous passes --dangerously-skip-permissions, which Claude Code's own help restricts to sandboxes with no internet access. Pairing it with the LOCAL provider is a misconfiguration — that provider does not contain the process at all.

      Allow/deny patterns pass through in Claude Code's own syntax, deny applied last so it wins: an overlapping policy must fail closed.

      Bash(git commit:*) matches only commands that begin with git commit. Proven live: a Bash(git:*) allow paired with a Bash(git commit:*) deny let git -C <path> commit through, because any flag before the subcommand defeats the prefix. The run failed only because nothing happened to be staged.

      The consequence is a rule, not a caveat: do not use a broad Bash(<tool>:*) allow and try to carve dangerous subcommands back out with denies. Deny whole tool names (Bash — an exact name match, no prefix involved) or allow only fully-specified commands. Real containment comes from the sandbox provider; with the LOCAL provider there is none, so the policy is all there is.

      Parameters

      Returns void

    • Tears the session down.

      MUST be idempotent and MUST be safe to call on every exit path — success, failure, cancellation and crash — because it is what revokes the per-run MCP credential and releases the workspace. A teardown that only runs on the happy path leaks a live credential.

      Returns Promise<void>

    • Answers a permission-request the adapter raised.

      Only meaningful when Capabilities.PermissionHooks is true; adapters without hooks should treat this as a no-op rather than throwing, because the posture layer above may still call it defensively.

      Parameters

      • _requestId: string
      • _approved: boolean
      • Optional_note: string

      Returns Promise<void>

    • Runs one turn and streams what happens.

      The first call receives the task prompt; subsequent calls receive formatted results of steps MJ executed on the harness's behalf. Implementations MUST emit exactly one terminal event — turn-complete or session-error — so the caller's accumulation loop always terminates.

      Where the harness cannot resume a session natively (SessionResume false), the adapter is responsible for replaying prior context into a fresh invocation here, and for reporting the resulting token cost through usage so the run's guardrails see the true spend.

      Parameters

      • input: string

      Returns AsyncIterable<HarnessTurnEvent>

    • Supplies MJ's system prompt for the session, where the harness can accept one.

      Harnesses ship their own system prompt defining their identity, and it dominates anything sent as user text. MJ's turn-end contract delivered as a user message therefore competes with the harness's own instructions and loses — observed directly: a harness given the contract in the user turn still answered "what can you do?" in prose, costing a retry every run.

      Adapters whose harness accepts a system prompt SHOULD override this. Those that cannot are no worse off than before: the contract still rides in the turn input.

      Parameters

      • systemPrompt: string

      Returns void