Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 1 addition & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -299,32 +299,7 @@ npx skills add chainbase-labs/agentkey
npx -y @agentkey/cli --auth-login
```

</details>

<details>
<summary><b>Installing over SSH, inside Docker, or via OpenClaw / Claude Code remote channels</b></summary>

When the installer runs on a machine you can't see (an SSH server, a Docker container, an OpenClaw runtime triggered from your phone), the default `--auth-login` would silently spawn a browser on the *remote* host — invisible to you.

The installer detects this automatically and switches to a **scan-from-phone** flow: it prints the auth URL plus a terminal QR code, and skips the browser auto-open. Detection signals (any one fires):

- `~/.openclaw/` exists (OpenClaw runtime)
- `$SSH_CONNECTION` / `$SSH_TTY` set
- Linux without `$DISPLAY` / `$WAYLAND_DISPLAY`

Force the mode either way:

```bash
# Force remote mode (URL + QR, no browser)
curl -fsSL https://agentkey.app/install.sh | bash -s -- --remote

# Force local mode (auto-open browser, ignore heuristics)
curl -fsSL https://agentkey.app/install.sh | bash -s -- --local
```

PowerShell: `-Remote` / `-Local`.

If you'd rather skip the URL/QR flow entirely and type a key manually, `npx -y @agentkey/cli --setup` opens an interactive wizard that asks for the key and lets you pick which MCP clients to write to.
**Headless / SSH / Docker?** The auth step always tries to open a browser **and** prints the URL — so on a machine without a usable display, just copy the printed URL to any device with a browser to finish auth. Prefer typing the key manually? `npx -y @agentkey/cli --setup` opens an interactive wizard instead.

</details>

Expand Down
27 changes: 1 addition & 26 deletions docs/README_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -299,32 +299,7 @@ npx skills add chainbase-labs/agentkey
npx -y @agentkey/cli --auth-login
```

</details>

<details>
<summary><b>在 SSH / Docker / OpenClaw 远程通道里安装</b></summary>

如果安装命令是在你看不到屏幕的机器上跑(远程 SSH 服务器、Docker 容器、由手机触发的 OpenClaw 运行时),默认 `--auth-login` 会在远端"成功"打开一个你看不见的浏览器,然后你只能盯着 "Waiting for authorization..." 卡死。

安装器会自动识别这种场景,切换到"扫码授权"流程:终端里直接打印授权 URL 加二维码,不再尝试本地开浏览器。**触发条件**(任一命中即判定为远程):

- `~/.openclaw/` 目录存在(OpenClaw 运行时)
- `$SSH_CONNECTION` / `$SSH_TTY` 已设置
- Linux 且无 `$DISPLAY` / `$WAYLAND_DISPLAY`

需要强制其中一种模式:

```bash
# 强制远程模式(URL + 二维码,不开浏览器)
curl -fsSL https://agentkey.app/install.sh | bash -s -- --remote

# 强制本地模式(自动开浏览器,无视启发式判断)
curl -fsSL https://agentkey.app/install.sh | bash -s -- --local
```

PowerShell:`-Remote` / `-Local`。

如果完全不想走 URL/二维码流程、想自己手动粘 Key,可以用 `npx -y @agentkey/cli --setup` —— 交互式向导,问你要 Key 并让你勾选要写入的 MCP 客户端。
**没 GUI / SSH / Docker?** 授权步骤会**同时**尝试开浏览器并把 URL 打印到终端 —— 在没法弹浏览器的机器上,直接把打印出来的 URL 复制到任何能开浏览器的设备完成授权即可。如果完全不想走 URL 跳转、想自己手动粘 Key,可以用 `npx -y @agentkey/cli --setup` 走交互式向导。

</details>

Expand Down
64 changes: 13 additions & 51 deletions scripts/install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@

Behavior mirrors install.sh: checks Node >= 18 (installs via winget/scoop/choco),
auto-detects which AI agents are installed and runs `npx skills add` for them,
then `npx @agentkey/cli --auth-login` for device auth. The auth step opens a
local browser by default; under SSH / Docker / OpenClaw it switches to a
QR + URL flow that the user scans on a phone (`--no-browser` server-side flag).
MCP config is written automatically for Claude Code / Claude Desktop / Cursor.
then `npx @agentkey/cli --auth-login` for device auth. The auth step always
tries to open a local browser AND prints the URL so headless / SSH users can
copy it elsewhere. MCP config is written automatically for Claude Code /
Claude Desktop / Cursor.
#>

[CmdletBinding()]
Expand All @@ -24,8 +24,6 @@ param(
[string]$Only,
[switch]$AllAgents,
[switch]$ListAgents,
[switch]$Remote,
[switch]$Local,
[switch]$SkipSkill,
[switch]$SkipMcp,
[switch]$NoTelemetry,
Expand Down Expand Up @@ -85,7 +83,7 @@ function Write-Muted($text) { Write-Host " $text" -ForegroundColor DarkGray }

function Die ($text) { Write-Err $text; exit 1 }

# ── Helpers: agent + remote detection ─────────────────────────────────────
# ── Helpers: agent detection ──────────────────────────────────────────────
function Test-AgentMarker {
param([string]$Marker)
if ($Marker.StartsWith('cmd:')) {
Expand All @@ -107,18 +105,6 @@ function Get-DetectedAgents {
return @($hits | Sort-Object -Unique)
}

# Detect "remote install" — context where opening a browser on this host
# is futile (SSH, Docker, OpenClaw remote channels). Mirrors the bash
# script's logic.
function Test-RemoteInstall {
if ($script:Local) { return $false }
if ($script:Remote) { return $true }

if (Test-Path -LiteralPath "$env:USERPROFILE\.openclaw") { return $true }
if ($env:SSH_CONNECTION -or $env:SSH_TTY) { return $true }
return $false
}

# ── Help ──────────────────────────────────────────────────────────────────
if ($Help) {
@'
Expand All @@ -134,11 +120,6 @@ Parameters:
-Only <a,b,c> Only install skill for these agents (e.g. "claude-code,cursor")
-AllAgents Skip auto-detection; let 'skills' CLI install for every detected agent
-ListAgents Print the agents we'd auto-select on this machine and exit
-Remote Force remote-install mode: print URL + QR for the auth step,
do NOT auto-open a local browser. Use this when running over
SSH, in WinRM, in a container, or via OpenClaw / Claude Code
remote channels.
-Local Force local mode (auto-open browser) and bypass remote heuristics
-SkipSkill Skip the skill install step (only run MCP auth)
-SkipMcp Skip the MCP auth step (only install the skill)
-NoTelemetry Disable anonymous usage telemetry (writes
Expand All @@ -148,17 +129,13 @@ Parameters:

Behavior:
The installer auto-detects which AI agents are on this machine and
pre-selects them for skill installation. Remote-install mode is auto-
detected from %USERPROFILE%\.openclaw and SSH env vars; override with
-Remote / -Local.
pre-selects them for skill installation. The auth step always tries
to open a browser and also prints the URL — so SSH / WinRM / Docker
/ OpenClaw users can copy the URL to any device with a browser.
'@
exit 0
}

if ($Remote -and $Local) {
Die '-Remote and -Local are mutually exclusive.'
}

if ($ListAgents) {
$detected = Get-DetectedAgents
if ($detected.Count -gt 0) { $detected -join "`n" | Write-Output }
Expand Down Expand Up @@ -335,24 +312,9 @@ if ($SkipMcp) {
Write-Step '3. Register the MCP server'
Write-Muted 'Skipped (-SkipMcp)'
} else {
$isRemote = Test-RemoteInstall
$authArgs = @('--auth-login')

if ($isRemote) {
Write-Step '3. Register the MCP server (remote auth: scan QR with phone)'
Write-Info 'Detected remote install context — printing QR + URL instead of opening a browser here.'
if (Test-Path -LiteralPath "$env:USERPROFILE\.openclaw") {
Write-Muted ' reason: %USERPROFILE%\.openclaw exists (OpenClaw runtime)'
} elseif ($env:SSH_CONNECTION -or $env:SSH_TTY) {
Write-Muted ' reason: SSH session detected'
}
Write-Muted 'Override with -Local if you want a browser opened on this machine instead.'
$authArgs += '--no-browser'
} else {
Write-Step '3. Register the MCP server (browser login)'
Write-Info 'Opening your browser for AgentKey device authentication ...'
Write-Muted 'When auth finishes, the MCP server is written into Claude Code / Claude Desktop / Cursor configs.'
}
Write-Step '3. Register the MCP server'
Write-Info 'Opening your browser for AgentKey device authentication ...'
Write-Muted "If a browser doesn't open (SSH / WinRM / Docker / headless), the auth URL is also printed below — open it on any device to finish."
Write-Host ''

# Telemetry context for install_completed. Opt-out is honored at the
Expand Down Expand Up @@ -383,10 +345,10 @@ if ($SkipMcp) {
$env:AGENTKEY_DEVICE_FINGERPRINT = $DeviceFingerprint
}

& npx -y $CliPackage @authArgs
& npx -y $CliPackage --auth-login
if ($LASTEXITCODE -ne 0) {
Write-Err 'MCP auth failed.'
Write-Muted "Retry manually: npx -y $CliPackage $($authArgs -join ' ')"
Write-Muted "Retry manually: npx -y $CliPackage --auth-login"
exit 1
}
Write-Ok 'MCP server registered'
Expand Down
80 changes: 9 additions & 71 deletions scripts/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
# curl -fsSL https://agentkey.app/install.sh | bash -s -- --yes
# curl -fsSL https://agentkey.app/install.sh | bash -s -- --interactive
# curl -fsSL https://agentkey.app/install.sh | bash -s -- --only claude-code,cursor
# curl -fsSL https://agentkey.app/install.sh | bash -s -- --remote
# curl -fsSL https://agentkey.app/install.sh | bash -s -- --skip-mcp
#
# The whole procedural body is wrapped in `main()` so that under `curl | bash`
Expand Down Expand Up @@ -104,10 +103,6 @@ Options:
--only <a,b,c> Only install skill for these agents (comma-separated, e.g. claude-code,cursor)
--all-agents Skip auto-detection; let 'skills' CLI install for every detected agent
--list-agents Print the agents we'd auto-select on this machine and exit
--remote Force remote-install mode: print URL + QR for the auth step,
do NOT auto-open a local browser. Use this when running over
SSH, in Docker, or via OpenClaw / Claude Code remote channels.
--local Force local mode (auto-open browser) and bypass remote heuristics
--skip-skill Skip the skill install step (only run MCP auth)
--skip-mcp Skip the MCP auth step (only install the skill)
--no-telemetry Disable anonymous usage telemetry (writes
Expand All @@ -118,13 +113,13 @@ Options:
Behavior:
Interactive mode is the default when a terminal is reachable; otherwise it
falls back to --yes. The installer auto-detects which AI agents are on this
machine and pre-selects them for skill installation. Remote-install mode is
auto-detected from \$HOME/.openclaw, SSH env vars, and missing \$DISPLAY;
override with --remote / --local.
machine and pre-selects them for skill installation. The auth step always
attempts to open a browser and also prints the URL — so SSH / Docker /
OpenClaw users can copy the URL to any device with a browser.
EOF
}

# ── Helpers: agent + remote detection ─────────────────────────────────────
# ── Helpers: agent detection ──────────────────────────────────────────────

# Expand a leading "~" to \$HOME (no glob expansion, no eval).
_expand_path() {
Expand Down Expand Up @@ -165,33 +160,6 @@ detect_agents() {
fi
}

# Detect "remote install" — a context where auto-opening a browser on this
# host is futile because the user isn't sitting in front of it. Mutates
# nothing; returns 0 (true) for remote, 1 (false) for local.
detect_remote() {
[ "$FORCE_LOCAL" = true ] && return 1
[ "$FORCE_REMOTE" = true ] && return 0

# OpenClaw runtime — the project owner confirms ~/.openclaw exists in
# any host where OpenClaw is installed/active. Most reliable single
# signal because it doesn't depend on env-var inheritance through the
# docker → channel → shell chain.
[ -d "$HOME/.openclaw" ] && return 0

# Generic SSH session.
[ -n "${SSH_CONNECTION:-}" ] && return 0
[ -n "${SSH_TTY:-}" ] && return 0

# Headless Linux (no GUI session).
if [ "$(uname -s)" = "Linux" ] \
&& [ -z "${DISPLAY:-}" ] \
&& [ -z "${WAYLAND_DISPLAY:-}" ]; then
return 0
fi

return 1
}

install_node() {
local platform="$1"
ui_info "Installing Node.js v$NODE_MIN_MAJOR+ ..."
Expand Down Expand Up @@ -253,12 +221,6 @@ main() {
local PRINT_HELP=false
local LIST_AGENTS=false
local ALL_AGENTS=false
# FORCE_REMOTE / FORCE_LOCAL are read by detect_remote(). Declared as
# plain (non-`local`) so the helpers see them — they're dynamic-scope
# accessible either way in bash, but explicit assignment here keeps
# `set -u` happy.
FORCE_REMOTE=false
FORCE_LOCAL=false
local NO_TELEMETRY=false

# Snapshot original args before the parse loop shifts them away — needed
Expand All @@ -273,8 +235,6 @@ main() {
--only=*) ONLY_AGENTS="${1#*=}"; shift ;;
--all-agents) ALL_AGENTS=true; shift ;;
--list-agents) LIST_AGENTS=true; shift ;;
--remote) FORCE_REMOTE=true; shift ;;
--local) FORCE_LOCAL=true; shift ;;
--skip-skill) SKIP_SKILL=true; shift ;;
--skip-mcp) SKIP_MCP=true; shift ;;
--no-telemetry) NO_TELEMETRY=true; shift ;;
Expand All @@ -284,9 +244,6 @@ main() {
done

if $PRINT_HELP; then print_help; exit 0; fi
if $FORCE_REMOTE && $FORCE_LOCAL; then
die "--remote and --local are mutually exclusive"
fi

if $LIST_AGENTS; then
local detected
Expand Down Expand Up @@ -468,28 +425,9 @@ main() {
ui_step "3. Register the MCP server"
ui_muted "Skipped (--skip-mcp)"
else
# Decide local-vs-remote and route the MCP CLI flags accordingly.
local IS_REMOTE=false
if detect_remote; then IS_REMOTE=true; fi

local AUTH_ARGS=(--auth-login)
if $IS_REMOTE; then
ui_step "3. Register the MCP server (remote auth: scan QR with phone)"
ui_info "Detected remote install context — printing QR + URL instead of opening a browser here."
if [ -d "$HOME/.openclaw" ]; then
ui_muted " reason: \$HOME/.openclaw exists (OpenClaw runtime)"
elif [ -n "${SSH_CONNECTION:-}" ] || [ -n "${SSH_TTY:-}" ]; then
ui_muted " reason: SSH session detected"
elif [ "$(uname -s)" = "Linux" ]; then
ui_muted " reason: Linux without \$DISPLAY / \$WAYLAND_DISPLAY"
fi
ui_muted "Override with --local if you want a browser opened on this machine instead."
AUTH_ARGS+=(--no-browser)
else
ui_step "3. Register the MCP server (browser login)"
ui_info "Opening your browser for AgentKey device authentication ..."
ui_muted "When auth finishes, the MCP server is written into Claude Code / Claude Desktop / Cursor configs."
fi
ui_step "3. Register the MCP server"
ui_info "Opening your browser for AgentKey device authentication ..."
ui_muted "If a browser doesn't open (SSH / Docker / headless), the auth URL is also printed below — open it on any device to finish."
echo

# Telemetry context for `install_completed`. Opt-out is honored at
Expand All @@ -513,9 +451,9 @@ main() {
export AGENTKEY_DEVICE_FINGERPRINT="$(compute_device_fingerprint "$PLATFORM")"
fi

if ! npx -y "$CLI_PACKAGE" "${AUTH_ARGS[@]}"; then
if ! npx -y "$CLI_PACKAGE" --auth-login; then
ui_error "MCP auth failed."
ui_muted "Retry manually: npx -y $CLI_PACKAGE ${AUTH_ARGS[*]}"
ui_muted "Retry manually: npx -y $CLI_PACKAGE --auth-login"
exit 1
fi
ui_ok "MCP server registered"
Expand Down
Loading