mirror of
https://github.com/agentclientprotocol/claude-agent-acp.git
synced 2026-11-11 20:01:11 +00:00
## Problem In a remote environment (`SSH_CONNECTION`, `SSH_CLIENT`, `SSH_TTY`, `NO_BROWSER` or `CLAUDE_CODE_REMOTE` set), `initialize` advertised only `claude-login`, the TUI `claude /login`. A user with API billing had no Anthropic Console option. With `--hide-claude-auth`, the list was empty and there was no way to log in at all. There is a second bug. A `_meta["terminal-auth"]` command reruns the agent with its own flags, for example `--hide-claude-auth --cli auth login --console`. The `--cli` passthrough removed only `--cli`, so the Claude CLI failed with `unknown option '--hide-claude-auth'`. ## Fix - `terminalAuthMethods` (`src/auth-methods.ts`) now offers `console-login` in remote environments too. Since Claude Code 2.1.126, `auth login` accepts the OAuth code pasted into the terminal when the localhost callback can't be reached. The subscription method stays as `claude-login` on a remote host and `claude-ai-login` locally. `--hide-claude-auth` hides it in both cases. The change is in the shared module, so it applies to v1 and v2. - New `cliArgs()` (`src/agent-command.ts`) removes `--cli` and `--hide-claude-auth` before the arguments go to the Claude CLI. ## Tests - `v1/authorization.test.ts`: an `it.each` over the five remote env vars × typed/`_meta` terminal auth × with/without `--hide-claude-auth`. - `v2/acp-v2.test.ts`: a remote host with `--hide-claude-auth` gets exactly one `console-login` terminal method. - `agent-command.test.ts`: `cliArgs` under Node, a compiled binary, and `--cli --version`. Manually checked in a JetBrains IDE through a local launch overlay with `SSH_CONNECTION` set and `--hide-claude-auth`. Only Anthropic Console was offered, the terminal login completed, and the chat worked afterwards.
84 lines
2.7 KiB
TypeScript
84 lines
2.7 KiB
TypeScript
import type { AuthMethod } from "@agentclientprotocol/sdk/unstable";
|
|
import { agentCommand } from "./agent-command.js";
|
|
import { shouldHideClaudeAuth } from "./hide-claude-auth.js";
|
|
|
|
/**
|
|
* The terminal login methods the agent advertises, in v1 form.
|
|
*
|
|
* - `terminal`: the client runs `args` against the agent's own command
|
|
* (`auth.terminal` in v1, an `auth.terminal` object in v2).
|
|
* - `metaTerminal`: the client reads `_meta["terminal-auth"]`, which names
|
|
* the command too.
|
|
*
|
|
* Without either, the client cannot run a login, and the list is empty. On a
|
|
* remote machine (SSH, `NO_BROWSER`, `CLAUDE_CODE_REMOTE`, as the SDK's own
|
|
* isRemote check) the subscription login runs the TUI's `claude /login`:
|
|
* clients such as Tidewave set `NO_BROWSER` to get it. The Anthropic Console
|
|
* login is offered there too, because since Claude Code 2.1.126 `auth login`
|
|
* accepts the OAuth code pasted into the terminal when the localhost callback
|
|
* can't be reached. The Claude subscription method is left out when
|
|
* `shouldHideClaudeAuth()` says so.
|
|
*/
|
|
export function terminalAuthMethods({
|
|
terminal,
|
|
metaTerminal,
|
|
}: {
|
|
terminal: boolean;
|
|
metaTerminal: boolean;
|
|
}): AuthMethod[] {
|
|
if (!terminal && !metaTerminal) return [];
|
|
const withMeta = (method: AuthMethod & { args: string[] }, label: string): AuthMethod => {
|
|
if (!metaTerminal) return method;
|
|
const agent = agentCommand();
|
|
return {
|
|
...method,
|
|
_meta: {
|
|
"terminal-auth": { command: agent.command, args: [...agent.args, ...method.args], label },
|
|
},
|
|
};
|
|
};
|
|
const isRemote = !!(
|
|
process.env.NO_BROWSER ||
|
|
process.env.SSH_CONNECTION ||
|
|
process.env.SSH_CLIENT ||
|
|
process.env.SSH_TTY ||
|
|
process.env.CLAUDE_CODE_REMOTE
|
|
);
|
|
const subscriptionLogin = isRemote
|
|
? withMeta(
|
|
{
|
|
description: "Run `claude /login` in the terminal",
|
|
name: "Log in with Claude",
|
|
id: "claude-login",
|
|
type: "terminal",
|
|
args: ["--cli"],
|
|
},
|
|
"Claude Login",
|
|
)
|
|
: withMeta(
|
|
{
|
|
description: "Use Claude subscription ",
|
|
name: "Claude Subscription",
|
|
id: "claude-ai-login",
|
|
type: "terminal",
|
|
args: ["--cli", "auth", "login", "--claudeai"],
|
|
},
|
|
"Claude Login",
|
|
);
|
|
const methods: AuthMethod[] = [];
|
|
if (!shouldHideClaudeAuth()) methods.push(subscriptionLogin);
|
|
methods.push(
|
|
withMeta(
|
|
{
|
|
description: "Use Anthropic Console (API usage billing)",
|
|
name: "Anthropic Console",
|
|
id: "console-login",
|
|
type: "terminal",
|
|
args: ["--cli", "auth", "login", "--console"],
|
|
},
|
|
"Anthropic Console Login",
|
|
),
|
|
);
|
|
return methods;
|
|
}
|