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
42 changes: 39 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,21 +218,32 @@ Still stuck? See the "Where do I get help" item below.
<details>
<summary><b>Advanced install options (CI / specific agents / manual two-step)</b></summary>

The installer auto-detects which AI agents you have on this machine (by probing well-known config dirs and binaries from the [vercel-labs/skills supported-agents list](https://github.com/vercel-labs/skills)) and pre-selects them — no multi-select prompt. Override with the flags below.

**Installer flags:**

```bash
# Non-interactive (CI / unattended): install to every detected agent, no prompts
curl -fsSL https://agentkey.app/install.sh | bash -s -- --yes

# Only install the skill for specific agents
# See which agents the installer would auto-select on this host (and exit)
curl -fsSL https://agentkey.app/install.sh | bash -s -- --list-agents

# Only install the skill for specific agents (overrides auto-detection)
curl -fsSL https://agentkey.app/install.sh | bash -s -- --only claude-code,cursor

# Skip our agent detection; let `skills` CLI install for every agent it finds
curl -fsSL https://agentkey.app/install.sh | bash -s -- --all-agents

# Only the skill, or only the MCP auth
curl -fsSL https://agentkey.app/install.sh | bash -s -- --skip-mcp
curl -fsSL https://agentkey.app/install.sh | bash -s -- --skip-skill

# Re-authenticate even if AgentKey is already configured locally
curl -fsSL https://agentkey.app/install.sh | bash -s -- --force-mcp
```

PowerShell equivalents: `-Yes`, `-Only`, `-SkipMcp`, `-SkipSkill`.
PowerShell equivalents: `-Yes`, `-ListAgents`, `-Only`, `-AllAgents`, `-SkipMcp`, `-SkipSkill`, `-ForceMcp`.

**Manual two-step install** (if you'd rather run the two underlying commands yourself, or the one-line installer can't reach your machine):

Expand All @@ -244,7 +255,32 @@ npx skills add chainbase-labs/agentkey
npx -y @agentkey/mcp --auth-login
```

Over SSH or any shell where a browser can't open, use `npx -y @agentkey/mcp --setup` — an interactive wizard asks for the key and lets you pick which MCP clients to write to.
</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/mcp --setup` opens an interactive wizard that asks for the key and lets you pick which MCP clients to write to.

</details>

Expand Down
42 changes: 39 additions & 3 deletions docs/README_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,21 +218,32 @@ npx skills remove chainbase-labs/agentkey
<details>
<summary><b>进阶安装(CI / 指定 Agent / 手动两步)</b></summary>

安装器会自动探测本机已安装的 AI Agent(依据 [vercel-labs/skills 支持列表](https://github.com/vercel-labs/skills) 比对配置目录和命令行工具),自动选中它们 —— 不再弹多选框。需要覆盖时用下面的旗标:

**安装器参数:**

```bash
# 非交互模式(CI / 无人值守):安装到所有检测到的 Agent,不询问
curl -fsSL https://agentkey.app/install.sh | bash -s -- --yes

# 只安装到指定的 Agent
# 看一下安装器在本机会自动选中哪些 Agent(看完即退出)
curl -fsSL https://agentkey.app/install.sh | bash -s -- --list-agents

# 只安装到指定的 Agent(覆盖自动检测结果)
curl -fsSL https://agentkey.app/install.sh | bash -s -- --only claude-code,cursor

# 跳过我们的检测,让 skills CLI 自己识别全部 Agent
curl -fsSL https://agentkey.app/install.sh | bash -s -- --all-agents

# 只装 Skill 或只做 MCP 授权
curl -fsSL https://agentkey.app/install.sh | bash -s -- --skip-mcp
curl -fsSL https://agentkey.app/install.sh | bash -s -- --skip-skill

# 即使本机已经配置过 AgentKey 也强制重新走一次授权
curl -fsSL https://agentkey.app/install.sh | bash -s -- --force-mcp
```

PowerShell 对应参数:`-Yes`、`-Only`、`-SkipMcp`、`-SkipSkill`。
PowerShell 对应参数:`-Yes`、`-ListAgents`、`-Only`、`-AllAgents`、`-SkipMcp`、`-SkipSkill`、`-ForceMcp`。

**手动两步安装**(想自己跑两条底层命令,或一键脚本在你的环境里跑不起来):

Expand All @@ -244,7 +255,32 @@ npx skills add chainbase-labs/agentkey
npx -y @agentkey/mcp --auth-login
```

在 SSH 远程或无法弹浏览器的终端里,用 `npx -y @agentkey/mcp --setup` —— 交互式向导,问你要 Key 并让你勾选要写入的 MCP 客户端。
</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/mcp --setup` —— 交互式向导,问你要 Key 并让你勾选要写入的 MCP 客户端。

</details>

Expand Down
185 changes: 168 additions & 17 deletions scripts/install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,23 @@
& ([scriptblock]::Create((irm https://agentkey.app/install.ps1))) -Only "claude-code,cursor"

Behavior mirrors install.sh: checks Node >= 18 (installs via winget/scoop/choco),
runs `npx skills add` (auto-detects agents), then `npx @agentkey/mcp --auth-login`
to open a browser for device auth. MCP config is written automatically for
Claude Code / Claude Desktop / Cursor.
auto-detects which AI agents are installed and runs `npx skills add` for them,
then `npx @agentkey/mcp --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.
#>

[CmdletBinding()]
param(
[switch]$Yes,
[switch]$Interactive,
[string]$Only,
[switch]$AllAgents,
[switch]$ListAgents,
[switch]$Remote,
[switch]$Local,
[switch]$ForceMcp,
[switch]$SkipSkill,
[switch]$SkipMcp,
[switch]$Help
Expand All @@ -29,6 +36,31 @@ $SkillRepo = 'chainbase-labs/agentkey'
$McpPackage = '@agentkey/mcp'
$NodeMinMajor = 18

# ── Agent markers (mirror of install.sh) ──────────────────────────────────
# Subset of vercel-labs/skills' 45 supported agent IDs that have reliable
# Windows-side markers. Sync source:
# https://github.com/vercel-labs/skills (Supported Agents table).
$AgentMarkers = @(
@{ Id = 'claude-code'; Markers = @("path:$env:USERPROFILE\.claude.json", 'cmd:claude', "path:$env:APPDATA\Claude") }
@{ Id = 'cursor'; Markers = @("path:$env:USERPROFILE\.cursor", 'cmd:cursor', "path:$env:LOCALAPPDATA\Programs\cursor") }
@{ Id = 'codex'; Markers = @("path:$env:USERPROFILE\.codex", 'cmd:codex') }
@{ Id = 'gemini-cli'; Markers = @("path:$env:USERPROFILE\.gemini", 'cmd:gemini') }
@{ Id = 'opencode'; Markers = @("path:$env:USERPROFILE\.opencode", 'cmd:opencode') }
@{ Id = 'openclaw'; Markers = @("path:$env:USERPROFILE\.openclaw") }
@{ Id = 'qwen-code'; Markers = @("path:$env:USERPROFILE\.qwen", 'cmd:qwen') }
@{ Id = 'iflow-cli'; Markers = @("path:$env:USERPROFILE\.iflow", 'cmd:iflow') }
@{ Id = 'windsurf'; Markers = @("path:$env:USERPROFILE\.windsurf", 'cmd:windsurf') }
@{ Id = 'warp'; Markers = @("path:$env:USERPROFILE\.warp") }
@{ Id = 'amp'; Markers = @('cmd:amp') }
@{ Id = 'crush'; Markers = @('cmd:crush') }
@{ Id = 'goose'; Markers = @('cmd:goose') }
@{ Id = 'droid'; Markers = @('cmd:droid') }
@{ Id = 'kode'; Markers = @('cmd:kode') }
@{ Id = 'kilo'; Markers = @('cmd:kilo') }
@{ Id = 'kimi-cli'; Markers = @("path:$env:USERPROFILE\.kimi", 'cmd:kimi') }
@{ Id = 'kiro-cli'; Markers = @("path:$env:USERPROFILE\.kiro", 'cmd:kiro') }
)

# ── UI helpers ────────────────────────────────────────────────────────────
function Write-Banner {
Write-Host ''
Expand All @@ -52,6 +84,58 @@ function Write-Muted($text) { Write-Host " $text" -ForegroundColor DarkGray }

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

# ── Helpers: agent + remote detection ─────────────────────────────────────
function Test-AgentMarker {
param([string]$Marker)
if ($Marker.StartsWith('cmd:')) {
return [bool](Get-Command $Marker.Substring(4) -ErrorAction SilentlyContinue)
}
if ($Marker.StartsWith('path:')) {
return Test-Path -LiteralPath $Marker.Substring(5)
}
return $false
}

function Get-DetectedAgents {
$hits = New-Object System.Collections.Generic.List[string]
foreach ($entry in $AgentMarkers) {
foreach ($m in $entry.Markers) {
if (Test-AgentMarker $m) { $hits.Add($entry.Id) | Out-Null; break }
}
}
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
}

# Cheap "is AgentKey already configured?" check across known MCP config files.
function Test-AlreadyAuthed {
$configs = @(
"$env:USERPROFILE\.claude.json",
"$env:USERPROFILE\.cursor\mcp.json",
"$env:APPDATA\Claude\claude_desktop_config.json"
)
foreach ($cfg in $configs) {
if (-not (Test-Path -LiteralPath $cfg)) { continue }
$content = Get-Content -Raw -LiteralPath $cfg -ErrorAction SilentlyContinue
if (-not $content) { continue }
if ($content -match '"agentkey"' -and $content -match '"AGENTKEY_API_KEY"\s*:\s*"ak_[A-Za-z0-9_-]+"') {
return $true
}
}
return $false
}

# ── Help ──────────────────────────────────────────────────────────────────
if ($Help) {
@'
Expand All @@ -65,13 +149,38 @@ Parameters:
-Yes Non-interactive: install skill to every detected agent, no prompts
-Interactive Force interactive mode (fails if console input is redirected)
-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
-ForceMcp Re-run MCP auth even if AgentKey is already configured
-SkipSkill Skip the skill install step (only run MCP auth)
-SkipMcp Skip the MCP auth step (only install the skill)
-Help Show this help

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.
'@
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 }
else { Write-Host 'no agents detected on this host' -ForegroundColor Yellow }
exit 0
}

Write-Banner

# ── 1. Preflight ──────────────────────────────────────────────────────────
Expand Down Expand Up @@ -151,15 +260,38 @@ if (-not (Get-Command npx -ErrorAction SilentlyContinue)) {
# ── 2. Install the AgentKey skill ─────────────────────────────────────────
if (-not $SkipSkill) {
Write-Step '2. Install the AgentKey skill'
Write-Info "The 'skills' CLI will auto-detect every supported agent on this machine."

$skillsArgs = @('-y', 'skills', 'add', $SkillRepo, '-g')
# Resolve target agent list:
# 1. -Only wins (manual override)
# 2. else -AllAgents ⇒ no -a (let skills CLI auto-detect everything)
# 3. else our auto-detection ⇒ -a <detected list>
# 4. else (nothing detected) ⇒ no -a (fall back to skills CLI default)
$targets = @()
if ($Only) {
$agentList = $Only -split ',' | Where-Object { $_ -ne '' }
$targets = $Only -split ',' | Where-Object { $_ -ne '' }
Write-Info "Targeting agents from -Only: $($targets -join ', ')"
} elseif ($AllAgents) {
Write-Info "Installing for every agent the 'skills' CLI detects (-AllAgents)"
} else {
$targets = Get-DetectedAgents
if ($targets.Count -gt 0) {
Write-Ok "Detected agents on this host: $($targets -join ', ')"
Write-Muted '(override with -Only <ids>, or use -AllAgents)'
} else {
Write-Info "No agents auto-detected — letting 'skills' CLI scan."
}
}

$skillsArgs = @('-y', 'skills', 'add', $SkillRepo, '-g')
if ($targets.Count -gt 0) {
$skillsArgs += '-a'
$skillsArgs += $agentList
$skillsArgs += $targets
}
# Always pass -y in noninteractive mode AND when we already resolved
# an explicit target list — there's nothing left to ask the user.
if ($Mode -eq 'noninteractive' -or $targets.Count -gt 0) {
$skillsArgs += '-y'
}
if ($Mode -eq 'noninteractive') { $skillsArgs += '-y' }

& npx @skillsArgs
if ($LASTEXITCODE -ne 0) { Die "Failed to install skill via 'skills' CLI" }
Expand All @@ -170,22 +302,41 @@ if (-not $SkipSkill) {
}

# ── 3. MCP authentication ────────────────────────────────────────────────
if (-not $SkipMcp) {
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.'
if ($SkipMcp) {
Write-Step '3. Register the MCP server'
Write-Muted 'Skipped (-SkipMcp)'
} elseif ((Test-AlreadyAuthed) -and -not $ForceMcp) {
Write-Step '3. Register the MCP server'
Write-Ok 'AgentKey is already configured in an MCP client config — skipping auth.'
Write-Muted 'Re-run with -ForceMcp to authenticate again.'
} 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-Host ''

& npx -y $McpPackage --auth-login
& npx -y $McpPackage @authArgs
if ($LASTEXITCODE -ne 0) {
Write-Err 'MCP auth failed.'
Write-Muted "Retry manually: npx -y $McpPackage --auth-login"
Write-Muted "Retry manually: npx -y $McpPackage $($authArgs -join ' ')"
exit 1
}
Write-Ok 'MCP server registered'
} else {
Write-Step '3. Register the MCP server'
Write-Muted 'Skipped (-SkipMcp)'
}

# ── 4. Summary ───────────────────────────────────────────────────────────
Expand Down
Loading
Loading