# https://github.com/pea3nut/agent-add 项目说明书

生成时间：2026-05-15 10:35:27 UTC

## 目录

- [Introduction](#introduction)
- [Getting Started](#getting-started)
- [System Architecture](#system-architecture)
- [Host Integration](#host-integration)
- [Source Resolution](#source-resolution)
- [Asset Types](#asset-types)
- [Manifest System](#manifest-system)
- [CLI Interface](#cli-interface)
- [Testing](#testing)
- [Project Configuration](#configuration)

<a id='introduction'></a>

## Introduction

### 相关页面

相关主题：[Getting Started](#getting-started), [System Architecture](#system-architecture)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [README.md](https://github.com/pea3nut/agent-add/blob/main/README.md)
- [package.json](https://github.com/pea3nut/agent-add/blob/main/package.json)
- [src/installer.ts](https://github.com/pea3nut/agent-add/blob/main/src/installer.ts)
- [src/cli.ts](https://github.com/pea3nut/agent-add/blob/main/src/cli.ts)
- [src/hosts/types.ts](https://github.com/pea3nut/agent-add/blob/main/src/hosts/types.ts)
- [src/source/infer-name.ts](https://github.com/pea3nut/agent-add/blob/main/src/source/infer-name.ts)
- [vibe/system-prompt.md](https://github.com/pea3nut/agent-add/blob/main/vibe/system-prompt.md)
</details>

# Introduction

agent-add is a unified CLI tool that streamlines the installation and management of AI coding agent assets across multiple host environments. It eliminates the need to manually configure MCP servers, skills, prompts, commands, and sub-agents by automating asset discovery, validation, and deployment to the appropriate host-specific directories.

## Purpose and Scope

agent-add addresses the fragmented ecosystem of AI coding assistants by providing a single command-line interface that works with 18 different host environments. Rather than maintaining separate installation instructions for Cursor, Claude Code, Windsurf, and other tools, developers and asset distributors can use agent-add to distribute assets universally.

**Core capabilities include:**

- **Asset Installation**: Install MCP servers, skills, prompts, commands, and sub-agents from local paths, Git URLs, or HTTP endpoints
- **Host Abstraction**: Automatic detection and adaptation for each host's unique configuration format and directory structure
- **Pack Distribution**: Bundle multiple assets into a single JSON manifest for team-wide distribution
- **Atomic Operations**: Safe file writes using temp file + rename patterns to prevent corruption
- **Idempotent Updates**: Marker-based append strategy ensures repeated installations do not create duplicates

资料来源：[README.md:1-50](https://github.com/pea3nut/agent-add/blob/main/README.md)

## Supported Hosts

agent-add supports the following 18 AI coding host environments:

| Host ID | Configuration Format | Install Directory |
|---------|---------------------|-------------------|
| `cursor` | JSON | `.cursor/` |
| `claude-code` | JSON | `.claude/` |
| `claude-desktop` | JSON | `~/Library/Application Support/Claude/` |
| `windsurf` | JSON | `.windsurf/rules/` |
| `github-copilot` | JSON | `.github/copilot/` |
| `gemini` | JSON | `.gemini/` |
| `roo-code` | JSON | `.roo/rules/` |
| `kilo-code` | JSON | `.kilocode/` |
| `qwen-code` | JSON | `.qwen/` |
| `opencode` | JSON | `.opencode/` |
| `augment` | JSON | `.augment/` |
| `kiro` | JSON | `.kiro/` |
| `tabnine` | JSON | `.tabnine/` |
| `kimi` | JSON | `.kimi/` |
| `trae` | JSON | `.trae/` |
| `openclaw` | JSON | `.openclaw/` |
| `codex` | TOML | `.codex/` |
| `vibe` | TOML | `.vibe/` |

资料来源：[vibe/system-prompt.md:30-35](https://github.com/pea3nut/agent-add/blob/main/vibe/system-prompt.md)

## Supported Asset Types

agent-add manages five distinct asset types, each with host-specific installation strategies:

| Asset Type | Description | Install Behavior |
|------------|-------------|------------------|
| `mcp` | Model Context Protocol server configurations | JSON shallow merge or TOML array append |
| `skill` | Reusable agent skill directories | Recursive directory copy |
| `prompt` | System prompts or rule files | Append-with-marker or create-file-in-dir |
| `command` | Slash commands | Create in commands directory |
| `subAgent` | Sub-agent configurations | Create in agents directory |

资料来源：[src/installer.ts:1-50](https://github.com/pea3nut/agent-add/blob/main/src/installer.ts)

## Architecture Overview

The codebase follows a layered architecture pattern with clear separation of concerns:

```mermaid
graph TD
    A[CLI Input] --> B[CLI Parser<br/>src/cli.ts]
    B --> C[Installer Core<br/>src/installer.ts]
    C --> D[Source Resolution<br/>src/source/]
    D --> E[Validation]
    E --> F[Host Adapter<br/>src/hosts/]
    F --> G[Asset Handler<br/>src/assets/]
    G --> H[Filesystem]
    
    I[Pack Manifest] -.-> C
    J[18 Host Adapters] -.-> F
    K[5 Asset Handlers] -.-> G
```

**Layer responsibilities:**

| Layer | Module | Responsibility |
|-------|--------|----------------|
| Input | `src/cli.ts` | Commander.js argument parsing, TTY detection, interactive host selection |
| Core | `src/installer.ts` | Orchestration: input parsing → capability check → source resolution → validation → handler execution → summary |
| Resolution | `src/source/` | Local file access, Git URL handling, HTTP fetching, inline content parsing |
| Adaptation | `src/hosts/` | Host-specific directory paths, capability declarations, write strategies |
| Execution | `src/assets/` | Type-specific installation logic (MCP merge, skill copy, prompt append, etc.) |

资料来源：[vibe/system-prompt.md:45-65](https://github.com/pea3nut/agent-add/blob/main/vibe/system-prompt.md)

## Core Data Flow

The installation pipeline follows a sequential process from CLI invocation to filesystem write:

```mermaid
graph LR
    A[CLI flags / --pack Manifest] --> B[Explicit flag capability check<br/>exit 2 if unsupported]
    B --> C[AssetDescriptor[]<br/>type + source]
    C --> D[ResolvedSource[]<br/>localPath + tempDir]
    D --> E[InstallJob[]<br/>skip unsupported assets]
    E --> F[InstallResult[]<br/>written / exists / updated / conflict / skipped / error]
    F --> G[Summary output]
```

**Processing stages:**

1. **Input Collection**: Gather all asset sources from CLI flags and pack manifests
2. **Capability Validation**: Verify each asset type is supported by the target host (exit 2 if explicit flag unsupported)
3. **Source Resolution**: Convert sources to local file paths (git clone, http download, inline temp files)
4. **Asset Validation**: Validate file existence, format compliance, and required metadata
5. **Job Creation**: Build installation jobs, skipping assets with unsupported capabilities
6. **Execution**: Dispatch to appropriate asset handler based on type
7. **Result Reporting**: Output summary with status for each asset

资料来源：[src/cli.ts:1-80](https://github.com/pea3nut/agent-add/blob/main/src/cli.ts)

## Write Strategies

Different asset types use different write strategies based on host capabilities:

```mermaid
graph TD
    A[Asset Type] --> B{Write Strategy}
    B --> C[append-with-marker]
    B --> D[create-file-in-dir]
    B --> E[atomic-json-merge]
    B --> F[directory-copy]
    
    C --> G[HTML comment markers<br/><!-- agent-add:name -->]
    D --> H[Create new file<br/>Skip if exists]
    E --> I[Temp file + rename<br/>JSON shallow merge]
    F --> J[Recursive copy<br/>SKILL.md required]
```

| Strategy | Used By | Behavior |
|----------|---------|----------|
| `append-with-marker` | Prompt (Cursor, Claude Code) | Wraps content in HTML comment markers, idempotent append |
| `create-file-in-dir` | Prompt (Windsurf, Roo Code), Command, Sub-agent | Creates `<name>.md` in rules/commands/agents directory |
| `atomic-json-merge` | MCP (JSON hosts) | Shallow merge with temp file + rename for safety |
| `toml-array-append` | MCP (Codex, Vibe) | Append to `[[mcp_servers]]` array |
| `directory-copy` | Skill | Recursive copy to host's skills directory |

资料来源：[src/installer.ts:50-120](https://github.com/pea3nut/agent-add/blob/main/src/installer.ts)

## Source Resolution

agent-add accepts assets from multiple source types with automatic detection:

| Source Format | Example | Name Inference |
|---------------|---------|---------------|
| Git URL + `#path` | `https://github.com/user/repo.git#skills/pdf` | Last segment after `#` (strip extension) |
| Git URL without `#` | `https://github.com/user/playwright.git` | Repo name (strip `.git`) |
| Local path | `./mcps/playwright.json` | Filename (strip extension) |
| HTTP URL | `https://example.com/config.json` | Filename (strip extension) |
| Inline JSON | `{"playwright":{...}}` | Top-level key as name |
| Inline Markdown | `# Code Review\n\nRules...` | First `# Heading` in kebab-case |

资料来源：[src/source/infer-name.ts:1-50](https://github.com/pea3nut/agent-add/blob/main/src/source/infer-name.ts)

## Installation and Usage

### Quick Install

```bash
# Install a single MCP server
npx -y agent-add --host cursor --mcp 'https://github.com/modelcontextprotocol/servers.git#mcp/playwright'

# Install multiple assets
npx -y agent-add --host cursor \
  --mcp './configs/mcp.json' \
  --skill './skills/pdf' \
  --prompt './rules/code-review.md'

# Install from a pack manifest
npx -y agent-add --host claude-code --pack './manifests/frontend-pack.json'
```

### CLI Options

| Flag | Description | Can Repeat |
|------|-------------|------------|
| `--host <id>` | Target host ID (required in CI, optional in TTY) | No |
| `--pack <source>` | Install from a pack manifest | Yes |
| `--mcp <source>` | Install MCP server configuration | Yes |
| `--skill <source>` | Install skill directory | Yes |
| `--prompt <source>` | Install prompt/rule file | Yes |
| `--command <source>` | Install slash command | Yes |
| `--sub-agent <source>` | Install sub-agent file | Yes |

资料来源：[src/cli.ts:40-60](https://github.com/pea3nut/agent-add/blob/main/src/cli.ts)

## Key Design Decisions

The architecture reflects several intentional design choices:

**Atomic JSON Writes**: MCP configuration uses temp file + rename pattern to prevent corruption from interrupted writes. 资料来源：[vibe/system-prompt.md:70-72](https://github.com/pea3nut/agent-add/blob/main/vibe/system-prompt.md)

**Marker-Based Idempotency**: Prompt append mode uses `<!-- agent-add:<name> -->` HTML comment markers, ensuring repeated installations update existing blocks rather than creating duplicates.

**Explicit Flag Rejection**: When using explicit flags like `--mcp`, agent-add validates host capability and exits with code 2 if unsupported. Pack sources skip unsupported assets silently instead.

**Non-TTY Strict Mode**: CI environments must explicitly specify `--host` to prevent ambiguous behavior in automated pipelines.

**Inline Content Support**: Prompt/Command/Sub-agent assets support inline content via newline detection, while MCP supports inline JSON via brace detection. HTTP and inline sources are explicitly rejected for Skill type assets.

资料来源：[src/installer.ts:80-100](https://github.com/pea3nut/agent-add/blob/main/src/installer.ts)

## Project Structure

```
agent-add/
├── bin/
│   └── agent-add.js          # Compiled entry point
├── src/
│   ├── index.ts              # Main entry, program creation
│   ├── cli.ts                # Commander definition + TTY detection
│   ├── installer.ts          # Orchestration core
│   ├── hosts/                # Host adapter layer (18 hosts)
│   │   ├── types.ts          # HostAdapter, AssetCapability types
│   │   ├── index.ts          # Host registry (Map<id, HostAdapter>)
│   │   └── <id>.ts           # Per-host adapter implementations
│   ├── assets/               # 5 asset type handlers
│   │   ├── mcp.ts            # JSON/TOML MCP handling
│   │   ├── skill.ts          # Directory copy + validation
│   │   ├── prompt.ts         # Append or create-file strategy
│   │   ├── command.ts        # Command file creation
│   │   └── subAgent.ts       # Sub-agent file creation
│   ├── source/               # Source resolution
│   │   ├── infer-name.ts     # Asset name inference
│   │   └── expand-directory.ts  # Directory expansion
│   ├── manifest/             # Pack manifest handling
│   │   └── parser.ts         # Zod schema validation
│   └── utils/                # Shared utilities
│       └── unwrap-mcp-servers.ts
├── tests/
│   ├── unit/                 # Unit tests per module
│   ├── features/             # Gherkin scenario tests
│   └── fixtures/             # Static test fixtures
└── vibe/                     # Development assets
    ├── manifest.json         # Dev pack manifest
    └── tasks/                # AI task definitions
```

资料来源：[README.md:80-100](https://github.com/pea3nut/agent-add/blob/main/README.md)

## Development

```bash
# Setup
npm install
npm run build

# Run tests
npm test                # All unit + integration tests
npm run test:contract   # CLI black-box contract tests only
npx vitest run tests/unit/hosts/cursor.test.ts  # Single file

# Run scenario tests (Gherkin)
# Use /scenario-exec command in your AI tool:
/scenario-exec tests/features/core
/scenario-exec tests/features/host
```

资料来源：[README.md:100-120](https://github.com/pea3nut/agent-add/blob/main/README.md)

---

<a id='getting-started'></a>

## Getting Started

### 相关页面

相关主题：[Introduction](#introduction), [CLI Interface](#cli-interface)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/cli.ts](https://github.com/pea3nut/agent-add/blob/main/src/cli.ts)
- [src/installer.ts](https://github.com/pea3nut/agent-add/blob/main/src/installer.ts)
- [src/index.ts](https://github.com/pea3nut/agent-add/blob/main/src/index.ts)
- [src/manifest/parser.ts](https://github.com/pea3nut/agent-add/blob/main/src/manifest/parser.ts)
- [src/source/infer-name.ts](https://github.com/pea3nut/agent-add/blob/main/src/source/infer-name.ts)
- [src/source/expand-directory.ts](https://github.com/pea3nut/agent-add/blob/main/src/source/expand-directory.ts)
</details>

# Getting Started

## Overview

`agent-add` is a CLI tool that automates the installation of AI agent assets—including MCP servers, skills, prompts, commands, and sub-agents—across 18 different AI coding assistant hosts. It provides a unified interface for installing community assets from Git repositories, local paths, HTTP URLs, or inline content.

The tool handles host-specific installation logic, validates assets before installation, and supports batch installation via pack manifests. 资料来源：[src/index.ts:1-7]()

## Prerequisites

- **Node.js**: v18 or later
- **npm** or **pnpm** for package management
- Access to the target host's configuration directory

## Installation

### Using npx (Recommended for One-time Use)

```bash
npx -y agent-add --help
```

### Global Installation

```bash
npm install -g agent-add
# or
pnpm add -g agent-add
```

### Local Installation

```bash
npm install
npm run build
```

The CLI entry point is located at `bin/agent-add.js`. 资料来源：[README.md](https://github.com/pea3nut/agent-add)

## Basic Usage

### Interactive Mode

When run in a TTY environment without specifying a host, `agent-add` prompts for target selection:

```bash
npx -y agent-add
```

The CLI detects available hosts in the current directory and presents an interactive selection menu. 资料来源：[src/cli.ts:56-77]()

### Non-interactive Mode

In CI environments or when a host must be specified explicitly:

```bash
npx -y agent-add --host <host-id> [asset-flags...]
```

If `--host` is omitted in non-TTY environments, the CLI exits with error code 2. 资料来源：[src/cli.ts:46-55]()

## Supported Hosts

The following 18 hosts are supported:

| Host ID | Type | Notes |
|---------|------|-------|
| `cursor` | JSON | Cursor IDE |
| `claude-code` | Markdown | Claude Code CLI |
| `claude-desktop` | JSON | Claude Desktop |
| `windsurf` | JSON | Windsurf IDE |
| `github-copilot` | JSON | GitHub Copilot |
| `gemini` | JSON | Google Gemini |
| `roo-code` | JSON | Roo Code |
| `kilo-code` | JSON | Kilo Code |
| `qwen-code` | JSON | Qwen Code |
| `opencode` | JSON | OpenCode |
| `augment` | JSON | Augment |
| `kiro` | JSON | Kiro |
| `tabnine` | JSON | Tabnine |
| `kimi` | JSON | Kimi |
| `trae` | JSON | Trae |
| `openclaw` | JSON | OpenClaw |
| `codex` | TOML | Codex |
| `vibe` | TOML | Vibe |

资料来源：[README.md](https://github.com/pea3nut/agent-add)

## Asset Types

### 1. MCP Server

Installs Model Context Protocol server configurations.

```bash
agent-add --host cursor --mcp 'https://github.com/modelcontextprotocol/servers.git#mcp/playwright'
```

### 2. Skill

Installs reusable agent skill directories containing `SKILL.md`.

```bash
agent-add --host cursor --skill './my-skill'
agent-add --host cursor --skill 'https://github.com/anthropics/skills.git#skills/webapp-testing'
```

> **Note**: Skills must target directory sources (local paths or Git URLs). Inline content or direct HTTP(S) URLs are not supported. 资料来源：[src/installer.ts:80-84]()

### 3. Prompt

Installs system prompts or rule files.

```bash
agent-add --host claude-code --prompt 'https://raw.githubusercontent.com/PatrickJS/awesome-cursorrules/main/rules/nextjs-react-tailwind/.cursorrules'
```

### 4. Command

Installs slash commands for AI assistants.

```bash
agent-add --host cursor --command 'https://github.com/wshobson/commands.git#tools/security-scan.md'
```

### 5. Sub-agent

Installs specialized agent configurations.

```bash
agent-add --host cursor --sub-agent 'https://github.com/VoltAgent/awesome-claude-code-subagents.git#categories/01-core-development/backend-developer.md'
```

## Source Specification

`agent-add` supports multiple source types for each asset:

| Source Type | Syntax Example | Name Inference |
|-------------|-----------------|----------------|
| Git URL with path | `...git#skills/pdf` | Last segment after `#`, stripped extension |
| Git URL without path | `...playwright.git` | Repository name (strip `.git`) |
| Local path | `./mcps/playwright.json` | Filename (strip extension) |
| HTTP URL | `https://example.com/config.json` | Filename (strip extension) |
| Inline JSON | `{"playwright":{...}}` | Single top-level key |
| Inline Markdown | `# Heading\nContent` | First `# Heading`, kebab-cased |

资料来源：[src/source/infer-name.ts:1-41]()

## Pack Manifests

Bundles multiple assets for distribution via a JSON manifest:

```json
{
  "name": "my-team/frontend-pack",
  "assets": [
    { "type": "mcp",      "source": "https://github.com/modelcontextprotocol/servers.git#.mcp.json" },
    { "type": "skill",    "source": "https://github.com/anthropics/skills.git#skills/pdf" },
    { "type": "prompt",   "source": "https://raw.githubusercontent.com/PatrickJS/awesome-cursorrules/main/rules/nextjs-react-tailwind/.cursorrules" }
  ]
}
```

Install with:

```bash
agent-add --host cursor --pack './my-pack.json'
```

Pack names must follow `namespace/pack-name` format with only `[a-zA-Z0-9_-]` characters. 资料来源：[src/manifest/parser.ts:1-31]()

## Workflow Diagram

```mermaid
graph TD
    A[CLI Input] --> B{Source Type Detection}
    B -->|Git URL| C[Clone to temp]
    B -->|Local Path| D[Resolve absolute path]
    B -->|HTTP URL| E[Download to temp]
    B -->|Inline| F[Write temp file]
    C --> G[Validate Asset]
    D --> G
    E --> G
    F --> G
    G -->|Invalid| H[Exit 2 with error]
    G -->|Valid| I{Check Host Capability}
    I -->|Unsupported| J[Skip asset]
    I -->|Supported| K[Install to Host]
    K --> L[Print Summary]
    J --> L
```

## Exit Codes

| Code | Meaning |
|------|---------|
| 0 | Success (all assets installed or already up-to-date) |
| 1 | Partial failure (conflicts or errors occurred) |
| 2 | Fatal error (invalid input, missing host, validation failure) |

资料来源：[src/cli.ts:27-34]()

## Examples

### Install MCP Server from GitHub

```bash
npx -y agent-add --host cursor --mcp 'https://github.com/modelcontextprotocol/servers.git#mcp/playwright'
```

### Install Multiple Assets

```bash
agent-add --host claude-code \
  --mcp 'https://github.com/modelcontextprotocol/servers.git#mcp/playwright' \
  --prompt 'https://raw.githubusercontent.com/PatrickJS/awesome-cursorrules/main/rules/nextjs-react-tailwind/.cursorrules' \
  --command 'https://github.com/wshobson/commands.git#tools/security-scan.md'
```

### Install Pack Manifest

```bash
agent-add --host cursor --pack 'https://github.com/VoltAgent/awesome-claude-code-subagents.git#manifests/backend-dev.json'
```

### Inline MCP Configuration

```bash
agent-add --host cursor --mcp '{"playwright":{"command":"npx","args":["@playwright/mcp@latest"]}}'
```

## Directory Expansion

For directories containing multiple assets, `agent-add` automatically expands them:

```bash
agent-add --host cursor --mcp './mcp-servers/'
```

Each `.json` file in the directory becomes a separate MCP asset. For skills, it scans for subdirectories containing `SKILL.md`. 资料来源：[src/source/expand-directory.ts:1-43]()

## Validation

Before installation, `agent-add` validates:

- **MCP**: File must exist and have `.json` extension
- **Skill**: Directory must contain `SKILL.md`; cannot use inline or HTTP sources
- **Prompt/Command/Sub-agent**: File must exist

资料来源：[src/installer.ts:78-107]()

## Next Steps

- Review the [Asset Developer Guide](https://github.com/pea3nut/agent-add#asset-developer-guide) for creating distributable assets
- Explore the [Host Adapter Architecture](https://github.com/pea3nut/agent-add#architecture-overview) for adding new hosts
- Run `agent-add --help` for complete CLI reference

---

<a id='system-architecture'></a>

## System Architecture

### 相关页面

相关主题：[Host Integration](#host-integration), [Source Resolution](#source-resolution)

<details>
<summary>Relevant Source Files</summary>

以下源码文件用于生成本页说明：

- [src/index.ts](https://github.com/pea3nut/agent-add/blob/main/src/index.ts)
- [src/installer.ts](https://github.com/pea3nut/agent-add/blob/main/src/installer.ts)
- [src/cli.ts](https://github.com/pea3nut/agent-add/blob/main/src/cli.ts)
- [src/hosts/index.ts](https://github.com/pea3nut/agent-add/blob/main/src/hosts/index.ts)
- [src/hosts/types.ts](https://github.com/pea3nut/agent-add/blob/main/src/hosts/types.ts)
- [src/source/index.ts](https://github.com/pea3nut/agent-add/blob/main/src/source/index.ts)
- [src/assets/mcp.ts](https://github.com/pea3nut/agent-add/blob/main/src/assets/mcp.ts)
- [src/assets/skill.ts](https://github.com/pea3nut/agent-add/blob/main/src/assets/skill.ts)
- [src/assets/prompt.ts](https://github.com/pea3nut/agent-add/blob/main/src/assets/prompt.ts)
- [src/source/infer-name.ts](https://github.com/pea3nut/agent-add/blob/main/src/source/infer-name.ts)
</details>

# System Architecture

agent-add is a cross-host AI agent pack installer CLI tool that enables developers to install MCP (Model Context Protocol), Skill, Prompt, Command, and Sub-agent assets into various AI agent hosts with a single command. The system is built with TypeScript 5.x in strict mode, targeting Node.js 18+ as a CommonJS bundle.

## Overview

The architecture follows a layered, pipeline-based design that separates concerns between CLI interface, orchestration logic, host adapters, and asset handlers. The system is stateless—no install state files are maintained—relying instead on filesystem-based idempotency checks.

```mermaid
graph TD
    subgraph CLI["CLI Layer"]
        CLI_ENTRY["src/index.ts<br/>Entry Point"]
        CLI_CMD["src/cli.ts<br/>Commander + TTY Detection"]
    end

    subgraph Core["Core Pipeline"]
        INST["src/installer.ts<br/>Orchestration Core"]
        VALIDATE["Validation Layer"]
        RESOLVE["src/source/index.ts<br/>Source Resolution"]
    end

    subgraph Adapters["Host Adapter Layer"]
        REGISTRY["src/hosts/index.ts<br/>Host Registry"]
        CURSOR["cursor.ts"]
        CLAUDE_CODE["claude-code.ts"]
        VIBE["vibe.ts"]
        CODEX["codex.ts"]
    end

    subgraph Handlers["Asset Handler Layer"]
        MCP["assets/mcp.ts"]
        SKILL["assets/skill.ts"]
        PROMPT["assets/prompt.ts"]
        COMMAND["assets/command.ts"]
        SUBAGENT["assets/sub-agent.ts"]
    end

    CLI_ENTRY --> CLI_CMD
    CLI_CMD --> INST
    INST --> VALIDATE
    INST --> RESOLVE
    RESOLVE --> REGISTRY
    REGISTRY --> CURSOR
    REGISTRY --> CLAUDE_CODE
    REGISTRY --> VIBE
    REGISTRY --> CODEX
    INST --> MCP
    INST --> SKILL
    INST --> PROMPT
    INST --> COMMAND
    INST --> SUBAGENT
```

资料来源：[src/index.ts:1-7]()

## Directory Structure

```
agent-add/
├── src/
│   ├── index.ts            # Entry point
│   ├── cli.ts               # Commander definition + TTY detection
│   ├── installer.ts         # Orchestration core
│   ├── hosts/               # Host adapter layer
│   │   ├── index.ts         # Host registry (Map<id, HostAdapter>)
│   │   ├── types.ts         # HostAdapter, AssetCapability, WriteStrategy
│   │   ├── README.md        # Capability matrix (single source of truth)
│   │   └── <id>.ts          # Per-host adapter (18 hosts)
│   ├── assets/              # Asset type handlers
│   │   ├── mcp.ts           # JSON shallow merge + atomic write
│   │   ├── skill.ts         # Directory copy + SKILL.md validation
│   │   ├── prompt.ts        # Marker append or create-file-in-dir
│   │   ├── command.ts       # Command file handler
│   │   └── sub-agent.ts     # Sub-agent with host specialization
│   └── source/              # Source resolution system
│       ├── index.ts         # Source resolution entry
│       ├── infer-name.ts    # Asset name inference
│       ├── local.ts         # Local file resolution
│       ├── git.ts           # Git URL cloning
│       └── http.ts          # HTTP/HTTPS download
├── tests/
│   ├── unit/                # Unit tests (vitest)
│   ├── integration/         # Integration tests
│   ├── features/            # Gherkin scenario tests
│   └── fixtures/            # Static test fixtures
└── dist/                    # Built output
```

资料来源：[README.md:1-45]()

## Core Data Flow

The installation pipeline follows a strict sequential flow from CLI input to final installation result:

```mermaid
graph LR
    A["CLI Flags /<br/>--pack Manifest"] --> B["Explicit Flag<br/>Capability Check"]
    B --> C["AssetDescriptor[]<br/>(type + source)"]
    C --> D["ResolvedSource[]<br/>(localPath + tempDir)"]
    D --> E["InstallJob[]<br/>(skip unsupported)"]
    E --> F["InstallResult[]<br/>(written/exists/updated/<br/>conflict/skipped/error)"]
    F --> G["Summary Output"]
```

### Pipeline Stages

| Stage | Input | Output | Key Operations |
|-------|-------|--------|-----------------|
| CLI Parsing | `process.argv` | `CliInput` object | TTY detection, host selection |
| Capability Check | `CliInput` | `AssetDescriptor[]` | Validates `--host` exists, checks explicit flags against host capabilities |
| Source Resolution | `AssetDescriptor[]` | `ResolvedSource[]` | Downloads Git/HTTP, extracts archives, writes inline sources to temp |
| Job Creation | `ResolvedSource[]` | `InstallJob[]` | Filters assets unsupported by target host |
| Handler Execution | `InstallJob[]` | `InstallResult[]` | Writes files using host-specific strategies |
| Summary | `InstallResult[]` | Console output | Formatted install summary |

资料来源：[src/installer.ts:1-200]()

## Host Adapter Layer

The host adapter layer provides a unified interface for interacting with different AI agent hosts. Each host has specific capabilities, installation paths, and write strategies.

### Host Registry

The `src/hosts/index.ts` file maintains a `Map<string, HostAdapter>` that maps host IDs to their adapter implementations:

```typescript
const hostRegistry = new Map<string, HostAdapter>([
  ['cursor', new CursorAdapter()],
  ['claude-code', new ClaudeCodeAdapter()],
  ['claude-desktop', new ClaudeDesktopAdapter()],
  ['windsurf', new WindsurfAdapter()],
  ['github-copilot', new GitHubCopilotAdapter()],
  ['gemini', new GeminiAdapter()],
  ['roo-code', new RooCodeAdapter()],
  ['kilo-code', new KiloCodeAdapter()],
  ['qwen-code', new QwenCodeAdapter()],
  ['opencode', new OpenCodeAdapter()],
  ['augment', new AugmentAdapter()],
  ['kiro', new KiroAdapter()],
  ['tabnine', new TabnineAdapter()],
  ['kimi', new KimiAdapter()],
  ['trae', new TraeAdapter()],
  ['openclaw', new OpenClawAdapter()],
  ['codex', new CodexAdapter()],
  ['vibe', new VibeAdapter()],
]);
```

资料来源：[src/hosts/index.ts]()
资料来源：[src/hosts/README.md:1-100]()

### Supported Hosts

| Host ID | MCP | Prompt | Skill | Command | Sub-agent | Config Format |
|---------|-----|--------|-------|---------|-----------|---------------|
| cursor | ✅ | ✅ | ✅ | ✅ | ✅ | JSON |
| claude-code | ✅ | ✅ | ❌ | ❌ | ❌ | JSON |
| claude-desktop | ✅ | ❌ | ❌ | ❌ | ❌ | JSON |
| windsurf | ✅ | ✅ | ✅ | ❌ | ❌ | JSON |
| github-copilot | ✅ | ❌ | ❌ | ❌ | ❌ | JSON |
| codex | ✅ | ✅ | ❌ | ❌ | ❌ | TOML |
| vibe | ✅ | ✅ | ❌ | ❌ | ❌ | TOML |

资料来源：[src/hosts/README.md:1-150]()

### HostAdapter Interface

Each host adapter implements the `HostAdapter` interface with asset-specific capabilities:

```typescript
interface HostAdapter {
  readonly id: string;
  readonly displayName: string;
  readonly docs: string;
  readonly assets: Record<AssetType, AssetCapability>;
}

interface AssetCapability {
  supported: boolean;
  reason?: string;
  configFile?: string;
  installDir?: string;
  writeStrategy?: WriteStrategy;
  baseRulesFile?: string;
}
```

资料来源：[src/hosts/types.ts]()

### Write Strategies

The system supports different write strategies for different asset types and hosts:

| Strategy | Description | Used By |
|----------|-------------|---------|
| `append-with-marker` | Appends content wrapped in HTML comment markers (`<!-- agent-add:name -->`) | Cursor, Claude Code |
| `create-file-in-dir` | Creates standalone `<name>.md` file in rules directory | Windsurf, Roo Code, Kilo Code |
| `json-merge` | Shallow JSON merge for MCP config | Most hosts |
| `toml-merge` | TOML merge for Codex/Vibe | codex, vibe |

资料来源：[src/hosts/types.ts]()
资料来源：[src/assets/prompt.ts]()
资料来源：[src/assets/mcp.ts]()

## Asset Handler Layer

Each asset type has a dedicated handler that implements the `AssetHandler` interface:

```mermaid
graph TD
    H["InstallJob"] --> MCP["MCP Handler"]
    H --> SKILL["Skill Handler"]
    H --> PROMPT["Prompt Handler"]
    H --> COMMAND["Command Handler"]
    H --> SUBAGENT["Sub-agent Handler"]

    MCP --> MCP_WRITE["Atomic JSON/TOML Write"]
    SKILL --> SKILL_COPY["Directory Copy + Validation"]
    PROMPT --> PROMPT_STRAT["Marker Append or Create File"]
    COMMAND --> COMMAND_WRITE["YAML Frontmatter Parse"]
    SUBAGENT --> SUB_WRITE["Host Specialization Processing"]
```

### MCP Handler

The MCP handler supports both JSON and TOML formats with automatic format detection:

- **JSON format A (inner config)**: Single server without wrapper
- **JSON format B (full config)**: With `mcpServers` wrapper
- **TOML format**: Auto-detected by `.toml` extension

Key behavior:
- Shallow merge for existing configurations
- Atomic write using temp file + rename pattern
- TOML auto-dispatches for Codex and Vibe hosts

资料来源：[src/assets/mcp.ts]()
资料来源：[README.md:50-80]()

### Skill Handler

The Skill handler installs entire skill directories:

- Recursively copies directory contents to host's skills directory
- Validates `SKILL.md` exists within the source directory
- Asset name becomes the subdirectory name under skills root
- **Note**: Does not support inline sources, HTTP URLs, or git subpaths

资料来源：[src/assets/skill.ts]()
资料来源：[src/installer.ts:50-100]()

### Prompt Handler

The Prompt handler supports two write strategies:

1. **Append Mode** (Cursor, Claude Code): Content is wrapped in idempotent HTML markers
   ```html
   <!-- agent-add:code-review-rules -->
   # Code Review Rules
   ...
   <!-- /agent-add:code-review-rules -->
   ```

2. **Standalone File Mode** (Windsurf, Roo Code): Creates `<name>.md` in rules directory

资料来源：[src/assets/prompt.ts]()
资料来源：[README.md:80-120]()

### Sub-agent Handler

The Sub-agent handler supports host specialization using YAML frontmatter:

```yaml
---
name: playwright-tester
description: A playwright testing agent.
agent-add/cursor/model: fast
agent-add/claude-code/model: haiku
---

# Playwright Test Agent
```

During installation:
1. Matching `agent-add/<host>/*` values are promoted to top-level
2. All `agent-add/*` prefixed keys are removed
3. Resulting frontmatter is host-specific

资料来源：[src/assets/sub-agent.ts]()
资料来源：[README.md:140-180]()

## Source Resolution System

The source resolution system handles multiple source types and normalizes them to local filesystem paths:

```mermaid
graph TD
    S["Source String"] --> TYPE{"Source Type Detection"}
    
    TYPE -->|Starts with `{` | INLINE_JSON["Inline JSON"]
    TYPE -->|Contains `\n` | INLINE_MD["Inline Markdown"]
    TYPE -->|Starts with `http` | HTTP["HTTP/HTTPS URL"]
    TYPE -->|Contains `://` or `.git` | GIT["Git URL"]
    TYPE -->|Otherwise | LOCAL["Local Path"]
    
    INLINE_JSON --> TEMP["Write to Temp File"]
    INLINE_MD --> TEMP
    HTTP --> DOWNLOAD["Download via fetch"]
    GIT --> CLONE["Git Clone/Shallow Clone"]
    LOCAL --> RESOLVE["path.resolve()"]
    
    DOWNLOAD --> CACHE["Cache in Temp Dir"]
    CLONE --> CACHE
    TEMP --> CACHE
    RESOLVE --> CACHE
    
    CACHE --> RESULT["ResolvedSource"]
```

### Supported Source Types

| Source Type | Detection | Processing |
|-------------|-----------|------------|
| Inline JSON | Starts with `{` | Parse, validate, write to temp |
| Inline Markdown | Contains `\n` | Extract name from `# Heading`, write to temp |
| HTTP File | `https://` or `http://` | Download via fetch, save to temp |
| Git URL | Contains `://` or `.git` | Shallow clone to temp directory |
| Local Path | Default | Resolve relative to cwd |

### Name Inference Rules

Asset names are inferred from sources using these rules:

| Source Pattern | Inference Rule | Example |
|----------------|----------------|---------|
| Git URL + `#path` | Last segment after `#`, kebab-case | `...git#skills/pdf` → `pdf` |
| Git URL without `#` | Repo name, strip `.git` | `...playwright.git` → `playwright` |
| HTTP URL | Filename, strip extension | `./mcps/playwright.json` → `playwright` |
| Local path | Filename, strip extension | `playwright.json` → `playwright` |
| Inline JSON | Top-level key name | `{"playwright":{...}}` → `playwright` |
| Inline Markdown | First `# Heading`, kebab-case | `# Code Review` → `code-review` |

资料来源：[src/source/infer-name.ts:1-50]()

## CLI Layer

### Entry Point

```typescript
import { createProgram } from './cli.js';

const program = createProgram();
program.parseAsync(process.argv).catch((err: Error) => {
  process.stderr.write(`agent-add error: ${err.message}\n`);
  process.exit(2);
});
```

资料来源：[src/index.ts:1-7]()

### CLI Options

| Flag | Type | Description | Repeatable |
|------|------|-------------|------------|
| `--pack <source>` | string | Install Agent Pack manifest | Yes |
| `--mcp <source>` | string | Install MCP config | Yes |
| `--skill <source>` | string | Install Skill directory | Yes |
| `--prompt <source>` | string | Install Prompt file | Yes |
| `--command <source>` | string | Install Command file | Yes |
| `--sub-agent <source>` | string | Install Sub-agent file | Yes |
| `--host <host>` | string | Target host ID | No |
| `-V, --version` | - | Show version | - |
| `-h, --help` | - | Show help | - |

资料来源：[src/cli.ts]()
资料来源：[README.md:200-220]()

### TTY Detection

Non-TTY environments (CI/CD) require explicit `--host` specification:

```typescript
if (!process.stdout.isTTY && !cliInput.host) {
  process.stderr.write(
    `agent-add error: Non-TTY environment detected. ` +
    `Specify --host explicitly. Valid hosts: ${validIds.join(', ')}\n`,
  );
  process.exit(2);
}
```

资料来源：[src/cli.ts]()
资料来源：[README.md:30-35]()

## Validation Layer

The validation layer performs asset-specific validation before installation:

| Asset Type | Validations |
|------------|-------------|
| MCP | File must exist, extension must be `.json` |
| Skill | Must be directory (not HTTP/inline), must contain `SKILL.md` |
| Prompt | None (Markdown has no required structure) |
| Command | None (Markdown with optional YAML frontmatter) |
| Sub-agent | None (Markdown with optional YAML frontmatter) |

资料来源：[src/installer.ts:100-150]()

### Explicit Flag Capability Check

When a user explicitly specifies an asset type flag (e.g., `--mcp`), the system checks if the target host supports that asset type. If `supported: false`, the installation exits with code 2 and provides a helpful error message with documentation link.

**Exception**: Assets from `--pack` manifests skip this check, as pack authors may include host-specific assets.

资料来源：[src/installer.ts:30-60]()

## Error Handling

| Error Type | Exit Code | Action |
|------------|-----------|--------|
| Capability not supported | 2 | Exit with error message + README link |
| Validation failure | 2 | Exit with source path |
| No matching files in directory | 2 | Exit with source path |
| Inline source for Skill | 2 | Exit with reason |
| Install conflict | 1 | Exit 1 (not 2, partial success) |
| Install error | 1 | Exit 1 (not 2, partial success) |

资料来源：[src/installer.ts:150-200]()
资料来源：[src/cli.ts:60-80]()

## Testing Architecture

The project uses a three-layer test strategy:

```mermaid
graph TD
    T["npm test"] --> U["Unit Tests"]
    T --> I["Integration Tests"]
    T --> CONTRACT["Contract Tests"]
    
    U --> V["vitest unit/"]
    I --> VITEST_INT["vitest integration/"]
    CONTRACT --> BLACKBOX["CLI black-box tests"]
    
    SCENARIO["Gherkin Scenarios"] -.-> MANUAL["AI Agent Manual Trigger"]
    SCENARIO --> FEATURES["tests/features/"]
    FEATURES --> ISOLATED["Isolated Temp Dir Execution"]
```

| Test Layer | Command | Purpose |
|------------|---------|---------|
| Unit | `npm test` | Component-level testing with mocks |
| Integration | `npm run test:integration` | Full flow testing with filesystem |
| Contract | `npm run test:contract` | CLI black-box behavior verification |
| Scenario | `/scenario-exec tests/features/` | Gherkin feature files, AI-executed |

资料来源：[README.md:15-30]()
资料来源：[README.md:230-250]()

## Environment Variables

| Variable | Purpose |
|----------|---------|
| `AGENT_ADD_HOME` | Overrides `os.homedir()` for test isolation, redirects Claude Desktop/Codex host install paths to temp directories |

资料来源：[system-prompt.md:10-12]()
资料来源：[src/assets/mcp.ts]()

## Key Design Decisions

### Atomic Writes

MCP configuration uses a temp file + rename pattern to ensure atomicity:

```typescript
// 1. Write to temp file
// 2. Rename to target (atomic on POSIX)
// 3. On failure, temp file is orphaned (not a partial write)
```

资料来源：[src/assets/mcp.ts]()

### Idempotent Marker Blocks

Prompt append mode uses HTML comment markers for safe re-installation:

```html
<!-- agent-add:code-review-rules -->
# Code Review Rules
...
<!-- /agent-add:code-review-rules -->
```

If markers exist, content between them is replaced; otherwise, markers are appended.

资料来源：[src/assets/prompt.ts]()
资料来源：[README.md:100-110]()

### TOML Auto-Dispatch

The MCP handler detects `.toml` extension and routes to TOML-specific merge logic:

```typescript
if (resolved.localPath.endsWith('.toml')) {
  // Use smol-toml for read/write
} else {
  // Use JSON shallow merge
}
```

资料来源：[src/assets/mcp.ts]()
资料来源：[package.json:20-25]()

## Technology Stack

| Component | Technology | Version |
|-----------|------------|---------|
| Language | TypeScript | 5.x (strict mode) |
| Runtime | Node.js | 18+ |
| Build | tsup (esbuild) | 8.x |
| Testing | vitest | 4.x |
| CLI | commander | 14.x |
| TOML | smol-toml | 1.x |
| Config validation | zod | 4.x |
| YAML parsing | yaml | 2.x |
| Interactive prompts | @inquirer/select | 5.x |

资料来源：[package.json:1-50]()

---

<a id='host-integration'></a>

## Host Integration

### 相关页面

相关主题：[System Architecture](#system-architecture), [Asset Types](#asset-types)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/hosts/types.ts](https://github.com/pea3nut/agent-add/blob/main/src/hosts/types.ts)
- [src/hosts/index.ts](https://github.com/pea3nut/agent-add/blob/main/src/hosts/index.ts)
- [src/hosts/cursor.ts](https://github.com/pea3nut/agent-add/blob/main/src/hosts/cursor.ts)
- [src/hosts/claude-code.ts](https://github.com/pea3nut/agent-add/blob/main/src/hosts/claude-code.ts)
- [src/hosts/windsurf.ts](https://github.com/pea3nut/agent-add/blob/main/src/hosts/windsurf.ts)
- [src/hosts/github-copilot.ts](https://github.com/pea3nut/agent-add/blob/main/src/hosts/github-copilot.ts)
- [src/hosts/README.md](https://github.com/pea3nut/agent-add/blob/main/src/hosts/README.md)
</details>

# Host Integration

## Overview

The Host Integration layer is the core abstraction in `agent-add` that enables cross-host compatibility. It provides a unified interface for installing assets (MCP servers, Skills, Prompts, Commands, and Sub-agents) across 18 different AI agent hosts including Cursor, Claude Code, Windsurf, and GitHub Copilot.

Each supported host has a dedicated adapter class that encapsulates:
- Host detection mechanisms
- Asset installation paths
- Configuration file formats
- Write strategies for different asset types
- Platform-specific considerations

This architecture allows `agent-add` to abstract away the complexities of each host's unique file system structure and configuration format, presenting a single CLI interface to end users.

## Architecture

### System Architecture

```mermaid
graph TD
    subgraph "CLI Layer"
        CLI[CLI Input Parsing]
    end
    
    subgraph "Core Engine"
        INST[Installer]
        VAL[Validator]
    end
    
    subgraph "Host Adapter Layer"
        REG[Host Registry]
        CA[Cursor Adapter]
        CCA[Claude Code Adapter]
        WA[Windsurf Adapter]
        OHA[Other Host Adapters]
    end
    
    subgraph "Asset Handlers"
        MCP[MCP Handler]
        SKILL[Skill Handler]
        PROMPT[Prompt Handler]
        CMD[Command Handler]
        SUB[Sub-agent Handler]
    end
    
    CLI --> INST
    INST --> VAL
    VAL --> REG
    REG --> CA
    REG --> CCA
    REG --> WA
    REG --> OHA
    
    CA --> MCP
    CA --> SKILL
    CA --> PROMPT
    CA --> CMD
    CA --> SUB
    
    CCA --> MCP
    CCA --> SKILL
    CCA --> PROMPT
    CCA --> CMD
    CCA --> SUB
```

### Data Flow

```mermaid
sequenceDiagram
    participant CLI as CLI Input
    participant INST as Installer
    participant HOST as Host Adapter
    participant HAND as Asset Handler
    participant FS as File System
    
    CLI->>INST: Parse flags + --pack manifest
    INST->>INST: Capability check
    INST->>INST: Source resolution
    INST->>INST: Asset validation
    INST->>HOST: Get capabilities for asset type
    HOST-->>INST: Return AssetCapability
    INST->>INST: Create InstallJob[]
    INST->>HAND: Execute install job
    HAND->>FS: Write with strategy
    FS-->>HAND: Confirm write
    HAND-->>INST: InstallResult
    INST->>INST: Format summary output
```

## HostAdapter Interface

The `HostAdapter` interface defines the contract all host implementations must follow.

### Interface Definition

```typescript
// src/hosts/types.ts
export interface HostAdapter {
  readonly id: string;
  readonly displayName: string;
  readonly docs: string;
  readonly detection: {
    paths: string[];
  };
  readonly assets: Record<AssetType, AssetCapability>;
}
```

### Property Specification

| Property | Type | Description |
|----------|------|-------------|
| `id` | `string` | Unique identifier for the host (e.g., `"cursor"`, `"claude-code"`) |
| `displayName` | `string` | Human-readable name (e.g., `"Claude Code"`) |
| `docs` | `string` | URL to official documentation |
| `detection.paths` | `string[]` | Directory paths that indicate this host is active |
| `assets` | `Record<AssetType, AssetCapability>` | Capability definitions for each asset type |

资料来源：[src/hosts/types.ts](https://github.com/pea3nut/agent-add/blob/main/src/hosts/types.ts)

## AssetCapability Types

Each asset type has its own capability configuration within the host adapter.

### AssetType Enum

```typescript
// src/hosts/types.ts
export type AssetType = 'mcp' | 'skill' | 'prompt' | 'command' | 'subAgent';
```

### Capability Structure

```typescript
// src/hosts/types.ts
export interface AssetCapability {
  supported: boolean;
  reason?: string;  // Required when supported=false
  configFile?: ConfigFileSpec;      // For MCP
  configKey?: string;              // For MCP
  targetFile?: string;             // For Prompt (append mode)
  installDir?: string;             // For Skill/Command/Sub-agent
  entryFile?: string;              // For Skill
  fileExtension?: string;          // For Command/Sub-agent
  writeStrategy?: WriteStrategy;    // Strategy for writing files
}

export interface ConfigFileSpec {
  darwin?: string;
  linux?: string;
  win32?: string;
}
```

### Supported Asset Types

| Asset Type | Purpose | Install Method |
|------------|---------|----------------|
| `mcp` | Model Context Protocol servers | Modify config file (JSON or TOML) |
| `skill` | Reusable agent skill directories | Copy directory recursively |
| `prompt` | System prompts / rule files | Append or create standalone file |
| `command` | Custom slash commands | Copy markdown file |
| `subAgent` | Sub-agent configurations | Copy configuration file |

资料来源：[src/hosts/types.ts](https://github.com/pea3nut/agent-add/blob/main/src/hosts/types.ts)

## Write Strategies

The `writeStrategy` property determines how assets are installed to the host's filesystem.

### Strategy Types

| Strategy | Description | Supported Asset Types |
|----------|-------------|----------------------|
| `inject-json-key` | Inject configuration into existing JSON/TOML file | MCP, Prompt (append mode) |
| `append-with-marker` | Append content wrapped in HTML comment markers | Prompt |
| `copy-file` | Copy file directly to target directory | Skill, Command, Sub-agent |
| `create-file-in-dir` | Create file at `installDir/<name>.md` | Prompt (standalone mode) |

### Marker Block Format

When using `append-with-marker`, content is wrapped in HTML comment markers for idempotent updates:

```html
<!-- agent-add:code-review-rules -->
# Code Review Rules

Always review for security issues first.
<!-- /agent-add:code-review-rules -->
```

### JSON Injection

The `inject-json-key` strategy performs shallow merging of MCP server configurations:

```typescript
// Before
{ "mcpServers": { "existing-server": {} } }

// After (injecting playwright)
{ "mcpServers": { "existing-server": {}, "playwright": { "command": "npx", "args": ["@playwright/mcp@latest"] } } }
```

## Host Registry

The host registry maps host IDs to their adapter instances.

```mermaid
classDiagram
    class HostRegistry {
        +hostRegistry: Map~string, HostAdapter~
        +getHost(id: string): HostAdapter
        +getValidHostIds(): string[]
    }
    
    class HostAdapter {
        <<interface>>
        +id: string
        +displayName: string
        +docs: string
        +assets: Record~AssetType, AssetCapability~
    }
    
    HostRegistry --> HostAdapter
```

### Registry Implementation

```typescript
// src/hosts/index.ts
const hostRegistry = new Map<string, HostAdapter>([
  ['cursor', new CursorAdapter()],
  ['claude-code', new ClaudeCodeAdapter()],
  ['windsurf', new WindsurfAdapter()],
  ['github-copilot', new GitHubCopilotAdapter()],
  // ... 14 more hosts
]);
```

### Currently Supported Hosts

The system supports 18 hosts across multiple platforms:

| Host ID | Display Name | Config Format |
|---------|--------------|---------------|
| `cursor` | Cursor AI | JSON |
| `claude-code` | Claude Code | JSON |
| `claude-desktop` | Claude Desktop | JSON |
| `windsurf` | Windsurf | TOML |
| `github-copilot` | GitHub Copilot | JSON |
| `gemini` | Google Gemini | JSON |
| `roo-code` | Roo Code | JSON |
| `kilo-code` | Kilo Code | JSON |
| `qwen-code` | Qwen Code | JSON |
| `opencode` | OpenCode | JSON |
| `augment` | Augment Code | JSON |
| `kiro` | Kiro | JSON |
| `tabnine` | Tabnine | JSON |
| `kimi` | Kimi | JSON |
| `trae` | Trae | JSON |
| `openclaw` | OpenClaw | JSON |
| `codex` | Codex CLI | TOML |
| `vibe` | Vibe | TOML |

## Example Host Adapters

### Claude Code Adapter

```typescript
// src/hosts/claude-code.ts
export class ClaudeCodeAdapter implements HostAdapter {
  readonly id = 'claude-code';
  readonly displayName = 'Claude Code';
  readonly docs = 'https://code.claude.com/docs/en';
  readonly detection = {
    paths: ['.claude/'],
  };
  readonly assets: Record<AssetType, AssetCapability> = {
    mcp: {
      supported: true,
      configFile: '.mcp.json',
      configKey: 'mcpServers',
      writeStrategy: 'inject-json-key',
    },
    skill: {
      supported: true,
      installDir: '.claude/skills/',
      entryFile: 'SKILL.md',
      writeStrategy: 'copy-file',
    },
    prompt: {
      supported: true,
      targetFile: 'CLAUDE.md',
      writeStrategy: 'append-with-marker',
    },
    command: {
      supported: true,
      installDir: '.claude/commands/',
      fileExtension: '.md',
      writeStrategy: 'copy-file',
    },
    subAgent: {
      supported: true,
      installDir: '.claude/agents/',
      fileExtension: '.md',
      writeStrategy: 'copy-file',
    },
  };
}
```

资料来源：[src/hosts/claude-code.ts](https://github.com/pea3nut/agent-add/blob/main/src/hosts/claude-code.ts)

### Cursor Adapter

```typescript
// src/hosts/cursor.ts
export class CursorAdapter implements HostAdapter {
  readonly id = 'cursor';
  readonly displayName = 'Cursor';
  readonly docs = 'https://www.cursor.com/docs';
  readonly detection = {
    paths: ['.cursor/'],
  };
  readonly assets: Record<AssetType, AssetCapability> = {
    mcp: {
      supported: true,
      configFile: {
        darwin: '~/Library/Application Support/Cursor/config/mcp.json',
        linux: '~/.config/Cursor/config/mcp.json',
        win32: '%APPDATA%\\Cursor\\config\\mcp.json',
      },
      configKey: 'mcpServers',
      writeStrategy: 'inject-json-key',
    },
    skill: {
      supported: true,
      installDir: '.cursor/skills/',
      entryFile: 'SKILL.md',
      writeStrategy: 'copy-file',
    },
    prompt: {
      supported: true,
      targetFile: 'AGENTS.md',
      writeStrategy: 'append-with-marker',
    },
    command: {
      supported: true,
      installDir: '.cursor/commands/',
      fileExtension: '.md',
      writeStrategy: 'copy-file',
    },
    subAgent: {
      supported: true,
      installDir: '.cursor/agents/',
      fileExtension: '.md',
      writeStrategy: 'copy-file',
    },
  };
}
```

资料来源：[src/hosts/cursor.ts](https://github.com/pea3nut/agent-add/blob/main/src/hosts/cursor.ts)

### Unsupported Assets

Hosts that don't support certain asset types use the `NOT_SUPPORTED` helper:

```typescript
// src/hosts/github-copilot.ts
const NOT_SUPPORTED = (reason: string): AssetCapability => ({
  supported: false,
  reason,
});

export class GitHubCopilotAdapter implements HostAdapter {
  // ...
  readonly assets: Record<AssetType, AssetCapability> = {
    mcp: {
      supported: true,
      configFile: '.github/copilot-instruqt.md',
      writeStrategy: 'inject-json-key',
    },
    command: NOT_SUPPORTED('GitHub Copilot does not support custom slash commands via files.'),
    // ...
  };
}
```

## Adding a New Host

### Contribution Workflow

```mermaid
graph LR
    A[Create Adapter] --> B[Register in index.ts]
    B --> C[Update README.md]
    C --> D[Add Unit Tests]
    D --> E[Verify with scenario tests]
```

### Step 1: Create the Adapter File

Create `src/hosts/<id>.ts` with a class implementing `HostAdapter`:

```typescript
// src/hosts/new-host.ts
import type { HostAdapter, AssetCapability, AssetType } from './types.js';

const NOT_SUPPORTED = (reason: string): AssetCapability => ({
  supported: false,
  reason,
});

export class NewHostAdapter implements HostAdapter {
  readonly id = 'new-host';
  readonly displayName = 'New Host';
  readonly docs = 'https://docs.newhost.com';
  readonly detection = {
    paths: ['.newhost/'],
  };
  readonly assets: Record<AssetType, AssetCapability> = {
    mcp: {
      supported: true,
      configFile: '.newhost/mcp.json',
      configKey: 'mcpServers',
      writeStrategy: 'inject-json-key',
    },
    prompt: NOT_SUPPORTED('New Host does not support prompts.'),
    skill: NOT_SUPPORTED('New Host does not support skills.'),
    command: NOT_SUPPORTED('New Host does not support commands.'),
    subAgent: NOT_SUPPORTED('New Host does not support sub-agents.'),
  };
}
```

### Step 2: Register the Adapter

Add to the registry in `src/hosts/index.ts`:

```typescript
import { NewHostAdapter } from './new-host.js';

const hostRegistry = new Map<string, HostAdapter>([
  // ... existing entries
  ['new-host', new NewHostAdapter()],
]);
```

### Step 3: Update Documentation

Add a row to the capability matrix in `src/hosts/README.md`:

| Host | MCP | Prompt | Skill | Command | Sub-agent |
|------|-----|--------|-------|---------|-----------|
| New Host | ✅ `.newhost/mcp.json` | ❌ | ❌ | ❌ | ❌ |

### Step 4: Add Unit Tests

Create `tests/unit/hosts/new-host.test.ts`:

```typescript
import { describe, it, expect } from 'vitest';
import { NewHostAdapter } from '../../../src/hosts/new-host.js';

describe('NewHostAdapter', () => {
  const adapter = new NewHostAdapter();

  it('should have correct id', () => {
    expect(adapter.id).toBe('new-host');
  });

  it('should have correct displayName', () => {
    expect(adapter.displayName).toBe('New Host');
  });

  it('should support MCP', () => {
    expect(adapter.assets.mcp.supported).toBe(true);
    expect(adapter.assets.mcp.configFile).toBe('.newhost/mcp.json');
  });
});
```

## Key Design Decisions

### Atomic JSON Writes

MCP configurations use a temp file + rename pattern to ensure atomicity:

```mermaid
graph TD
    A[New Config] --> B[Write to temp file]
    B --> C[Rename temp to target]
    C --> D{Success?}
    D -->|Yes| E[Complete]
    D -->|No| F[Rollback temp file]
```

### Platform-Specific Paths

MCP config files use platform-specific paths:

```typescript
configFile: {
  darwin: '~/Library/Application Support/Cursor/config/mcp.json',
  linux: '~/.config/Cursor/config/mcp.json',
  win32: '%APPDATA%\\Cursor\\config\\mcp.json',
}
```

### TOML vs JSON Auto-Detection

The system auto-detects TOML format based on file extension:

```typescript
// src/assets/mcp.ts
if (path.extname(configFile) === '.toml') {
  // Use smol-toml for read/write
} else {
  // Use standard JSON
}
```

### Explicit Flag Capability Checking

The installer validates that explicitly requested asset types are supported before attempting installation:

```typescript
// src/installer.ts
if (!capability.supported) {
  skippedResults.push({
    job: { assetType, assetName, resolvedSource, host },
    status: 'skipped',
    reason: capability.reason,
  });
}
```

## Summary

The Host Integration system provides a scalable architecture for supporting multiple AI agent hosts through a consistent adapter pattern. Key benefits include:

- **Single Source of Truth**: All host capabilities defined in adapter classes and documented in `src/hosts/README.md`
- **Extensibility**: New hosts can be added by implementing the `HostAdapter` interface
- **Type Safety**: TypeScript strict mode ensures adapter implementations match specifications
- **Testability**: Each adapter has corresponding unit tests verifying exact field values
- **Platform Abstraction**: Platform-specific paths handled transparently
- **Format Flexibility**: Supports both JSON and TOML configuration formats

---

<a id='source-resolution'></a>

## Source Resolution

### 相关页面

相关主题：[System Architecture](#system-architecture), [Asset Types](#asset-types)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/source/index.ts](https://github.com/pea3nut/agent-add/blob/main/src/source/index.ts)
- [src/source/git.ts](https://github.com/pea3nut/agent-add/blob/main/src/source/git.ts)
- [src/source/http-file.ts](https://github.com/pea3nut/agent-add/blob/main/src/source/http-file.ts)
- [src/source/local.ts](https://github.com/pea3nut/agent-add/blob/main/src/source/local.ts)
- [src/source/inline.ts](https://github.com/pea3nut/agent-add/blob/main/src/source/inline.ts)
- [src/source/infer-name.ts](https://github.com/pea3nut/agent-add/blob/main/src/source/infer-name.ts)
</details>

# Source Resolution

## Overview

Source Resolution is the core subsystem responsible for transforming user-provided source strings into concrete filesystem paths that the installer can process. It acts as an abstraction layer that normalizes diverse input formats—including local paths, Git URLs, HTTP URLs, and inline content—into a unified `ResolvedSource` data structure.

The resolution pipeline accepts asset sources in multiple formats and outputs temporary directories containing the asset content, ready for downstream handlers to install into host-specific locations. This design decouples asset specification from asset installation, enabling users to reference assets through various convenient syntaxes without understanding host-specific installation mechanics.

资料来源：[src/source/index.ts](https://github.com/pea3nut/agent-add/blob/main/src/source/index.ts)

## Architecture

The Source Resolution module is located in `src/source/` and comprises six specialized modules:

| Module | Purpose |
|--------|---------|
| `index.ts` | Main entry point; orchestrates resolution pipeline |
| `git.ts` | Resolves Git URLs (SSH and HTTPS) with sparse checkout support |
| `http-file.ts` | Downloads assets from HTTP/HTTPS URLs |
| `local.ts` | Resolves local filesystem paths |
| `inline.ts` | Handles inline JSON and Markdown content |
| `infer-name.ts` | Extracts asset names from source strings |

资料来源：[src/source/index.ts](https://github.com/pea3nut/agent-add/blob/main/src/source/index.ts)

## Resolution Pipeline

The resolution process follows a sequential pipeline that attempts each resolver until one successfully produces a `ResolvedSource`:

```mermaid
graph TD
    A[User Source String] --> B{Starts with ./ or / or ~?}
    B -->|Yes| C[Local Resolver]
    B -->|No| D{Starts with http:// or https://?}
    D -->|Yes| E[HTTP Resolver]
    D -->|No| F{Starts with git@ or ends with .git?}
    F -->|Yes| G[Git Resolver]
    F -->|No| H{Starts with {?}
    H -->|Yes| I[Inline JSON Resolver]
    H -->|No| J{Contains \n?}
    J -->|Yes| K[Inline Markdown Resolver]
    J -->|No| L[Error: Unknown source format]
    
    C --> M[ResolvedSource]
    E --> M
    G --> M
    I --> M
    K --> M
```

Each resolver returns a `ResolvedSource` object containing the original source, resolved local path, and content type:

```typescript
interface ResolvedSource {
  originalSource: string;  // The user's original input
  localPath: string;       // Absolute path to resolved content
  type: SourceType;        // 'local' | 'git' | 'http-file' | 'inline-json' | 'inline-md'
  tempDir?: string;        // Temp directory if content was downloaded/generated
}
```

资料来源：[src/source/index.ts](https://github.com/pea3nut/agent-add/blob/main/src/source/index.ts)

## Source Types

### Local Files and Directories

The local resolver handles filesystem paths beginning with `./`, `../`, `/`, or `~`. It performs the following operations:

1. **Path normalization**: Expands `~` to home directory and resolves relative paths to absolute paths
2. **Existence verification**: Confirms the path exists on the filesystem
3. **Directory detection**: For directory sources, scans for matching asset files

```typescript
// Supported path formats
'./mcps/playwright.json'     // Relative path
'/absolute/path/to/file'    // Absolute path
'~/dotfiles/mcp.json'       // Home directory expansion
'../shared/rules.md'        // Parent directory relative path
```

资料来源：[src/source/local.ts](https://github.com/pea3nut/agent-add/blob/main/src/source/local.ts)

### Git URLs

The Git resolver supports both SSH and HTTPS Git URLs with optional path fragment syntax for sparse checkout:

| Format | Example | Behavior |
|--------|---------|----------|
| SSH | `git@github.com:user/repo.git#path/to/asset` | Clones via SSH, extracts specified path |
| HTTPS | `https://github.com/user/repo.git#path/to/asset` | Clones via HTTPS, extracts specified path |
| Without fragment | `git@github.com:user/repo.git` | Clones entire repository |

**Sparse Checkout Behavior**

When a `#path` fragment is specified, the resolver performs a sparse checkout, downloading only the specified directory or file. This is particularly useful for monorepos where only specific assets are needed.

```typescript
// Example: Extract only the playwright skill from a monorepo
git@github.com:anthropics/skills.git#skills/playwright
```

The resolver supports both formats:
- **Directory path**: Extracts all files within the directory
- **File path**: Extracts a single file

资料来源：[src/source/git.ts](https://github.com/pea3nut/agent-add/blob/main/src/source/git.ts)

### HTTP/HTTPS URLs

The HTTP resolver downloads files directly from web URLs. It supports:

- Direct file downloads from any HTTP/HTTPS endpoint
- Automatic filename extraction from URL path
- Integrity verification of downloaded content

**Supported Asset Types for HTTP:**

| Asset Type | HTTP Support |
|------------|--------------|
| MCP | ✅ Yes |
| Skill | ❌ No (validation rejects) |
| Prompt | ✅ Yes |
| Command | ✅ Yes |
| Sub-agent | ✅ Yes |

资料来源：[src/source/http-file.ts](https://github.com/pea3nut/agent-add/blob/main/src/source/http-file.ts)

### Inline Content

Inline sources allow embedding asset content directly in the command line, eliminating the need for separate files or remote URLs. The system auto-detects content type based on format.

#### Inline JSON (MCP Only)

Sources beginning with `{` are treated as inline JSON. The format supports MCP configuration in two structures:

**Format A: Inner config (single server)**
```json
{"command":"npx","args":["@playwright/mcp@latest"]}
```
Asset name is inferred from the MCP config filename.

**Format B: Wrapped config with `mcpServers`**
```json
{"mcpServers":{"playwright":{"command":"npx","args":["@playwright/mcp@latest"]}}}
```
The wrapper is automatically unwrapped and the inner server name becomes the asset name.

```bash
# Example command
npx -y agent-add --host cursor \
  --mcp '{"playwright":{"command":"npx","args":["@playwright/mcp"]}}'
```

资料来源：[src/source/inline.ts](https://github.com/pea3nut/agent-add/blob/main/src/source/inline.ts)

#### Inline Markdown (Prompt/Command/Sub-agent)

Sources containing `\n` (newline) are treated as inline Markdown. This applies to:

- **Prompt files**: System prompts and rule files
- **Command files**: Slash commands
- **Sub-agent files**: Agent configurations

The asset name is inferred from the first `# Heading` in the content, converted to kebab-case:

```markdown
# Code Review Rules

Always review for security first.
```
→ Asset name: `code-review-rules`

```bash
# Example command
npx -y agent-add --host claude-code \
  --prompt $'# Code Review Rules\n\nAlways review for security issues first.'
```

资料来源：[src/source/inline.ts](https://github.com/pea3nut/agent-add/blob/main/src/source/inline.ts)
资料来源：[src/source/infer-name.ts](https://github.com/pea3nut/agent-add/blob/main/src/source/infer-name.ts)

## Asset Name Inference

The `infer-name.ts` module extracts consistent asset names from diverse source formats. This ensures uniform naming regardless of how the asset is referenced.

### Name Inference Rules

| Source Type | Rule | Example Input | Inferred Name |
|-------------|------|---------------|---------------|
| Inline JSON | Extract top-level key | `{"playwright":{...}}` | `playwright` |
| Inline Markdown | First `# Heading` → kebab-case | `# Code Review` | `code-review` |
| Git URL + `#path` | Last segment, strip extension | `...git#skills/pdf` | `pdf` |
| Git URL without `#` | Repository name, strip `.git` | `...playwright.git` | `playwright` |
| Local path / HTTP | Filename, strip extension | `./mcps/playwright.json` | `playwright` |

### Inline JSON Parsing

When processing inline JSON sources:

1. Parse the JSON string into an object
2. If the object has an `mcpServers` wrapper, unwrap it
3. Extract the top-level key as the asset name
4. If multiple keys exist, throw an error (inline JSON supports single MCP only)

```typescript
// Single server (inner format) - name from source metadata
{"command":"npx","args":["@playwright/mcp"]}  // ❌ No name, requires filename inference

// Single server (wrapped format) - name from key
{"mcpServers":{"playwright":{...}}}  // ✅ Name is "playwright"
```

资料来源：[src/source/infer-name.ts](https://github.com/pea3nut/agent-add/blob/main/src/source/infer-name.ts)

## Temporary File Management

Source Resolution manages temporary directories to ensure clean operation:

1. **Downloaded content**: HTTP and Git downloads are stored in temporary directories
2. **Inline content**: Generated files (from inline JSON/Markdown) are written to temp files
3. **Cleanup**: Temp directories are cleaned up after installation completes

The `AGENT_ADD_HOME` environment variable can override the default temp directory location, useful for test isolation:

```bash
AGENT_ADD_HOME=/tmp/test-home npx -y agent-add --host cursor --mcp '{"test":{...}}'
```

资料来源：[src/source/index.ts](https://github.com/pea3nut/agent-add/blob/main/src/source/index.ts)

## Integration with Installation Pipeline

Source Resolution integrates into the broader installation workflow as follows:

```mermaid
graph LR
    A[CLI Input] --> B[Source Resolution]
    B --> C[ResolvedSource]
    C --> D[Validation]
    D --> E[InstallJob Creation]
    E --> F[Asset Handler Execution]
    F --> G[InstallResult]
    
    B -.->|Inline sources| H[Temp File Generation]
    B -.->|Git/HTTP sources| I[Download to Temp]
```

After resolution, the `installer.ts` module performs validation based on asset type:

- **MCP**: File must exist and have `.json` extension
- **Skill**: Must be a directory containing `SKILL.md`
- **Prompt/Command/Sub-agent**: No additional validation at this stage

```typescript
// From src/installer.ts - validation logic
if (assetType === 'skill') {
  if (resolved.type === 'http-file' || resolved.type === 'inline-json' || resolved.type === 'inline-md') {
    return 'Skill assets must point to directory sources (local path or Git URL)';
  }
  const skillMdPath = path.join(resolved.localPath, 'SKILL.md');
  // ...
}
```

资料来源：[src/installer.ts](https://github.com/pea3nut/agent-add/blob/main/src/installer.ts)

## Error Handling

The resolution system provides specific error messages for common failures:

| Error Condition | Message |
|-----------------|---------|
| Inline JSON parse failure | `内联 JSON 解析失败。格式应为 {"<name>":{...}}` |
| Inline JSON not object | `内联 JSON 必须为对象类型` |
| Multiple keys in inline JSON | Error listing unsupported multiple keys |
| Directory empty (skill) | `No matching files found in directory` |
| SKILL.md missing | `Skill 目录内缺少 SKILL.md 文件` |
| MCP file missing | `MCP 来源文件不存在` |
| MCP wrong extension | `MCP 来源文件扩展名必须为 .json` |
| HTTP for Skill | `Skill 资产必须指向目录来源` |

All errors result in process exit with code 2, ensuring CI/CD pipelines fail fast on configuration issues.

资料来源：[src/source/infer-name.ts](https://github.com/pea3nut/agent-add/blob/main/src/source/infer-name.ts)
资料来源：[src/installer.ts](https://github.com/pea3nut/agent-add/blob/main/src/installer.ts)

---

<a id='asset-types'></a>

## Asset Types

### 相关页面

相关主题：[Manifest System](#manifest-system), [Host Integration](#host-integration)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/manifest/schema.ts](https://github.com/pea3nut/agent-add/blob/main/src/manifest/schema.ts)
- [src/manifest/parser.ts](https://github.com/pea3nut/agent-add/blob/main/src/manifest/parser.ts)
- [vibe/manifest.json](https://github.com/pea3nut/agent-add/blob/main/vibe/manifest.json)
- [src/installer.ts](https://github.com/pea3nut/agent-add/blob/main/src/installer.ts)
- [src/assets/mcp.ts](https://github.com/pea3nut/agent-add/blob/main/src/assets/mcp.ts)
- [src/assets/skill.ts](https://github.com/pea3nut/agent-add/blob/main/src/assets/skill.ts)
- [src/assets/prompt.ts](https://github.com/pea3nut/agent-add/blob/main/src/assets/prompt.ts)
- [src/assets/command.ts](https://github.com/pea3nut/agent-add/blob/main/src/assets/command.ts)
- [src/hosts/types.ts](https://github.com/pea3nut/agent-add/blob/main/src/hosts/types.ts)
</details>

# Asset Types

Asset Types define the categories of installable resources that agent-add can distribute to AI coding assistant hosts. The system supports five distinct asset types, each with specific file formats, validation rules, and installation behaviors.

## Overview

agent-add categorizes all distributable resources into five asset types. Each type has a dedicated handler responsible for installation logic, validation, and host-specific write strategies.

```mermaid
graph TD
    A[User Input / Pack Manifest] --> B{Asset Type Detection}
    B -->|JSON| C[MCP Server]
    B -->|Directory + SKILL.md| D[Skill]
    B -->|Markdown| E[Prompt]
    B -->|Markdown + Frontmatter| F[Command]
    B -->|Markdown + Agent Meta| G[Sub-agent]
    
    C --> H[Validation]
    D --> H
    E --> H
    F --> H
    G --> H
    
    H --> I[Host Adapter]
    I --> J[Write Strategy]
    J --> K[Host Filesystem]
```

## Supported Asset Types

| Asset Type | Identifier | Source Format | Validation Requirement |
|------------|------------|---------------|------------------------|
| MCP Server | `mcp` | JSON file | `.json` extension required |
| Skill | `skill` | Directory | Must contain `SKILL.md` |
| Prompt | `prompt` | Markdown file | First `# Heading` required |
| Command | `command` | Markdown with YAML frontmatter | Optional description field |
| Sub-agent | `subAgent` | Markdown with YAML frontmatter | Optional host specialization |

资料来源：[src/manifest/schema.ts]() and [src/manifest/parser.ts:30-35]()

## MCP Server (`mcp`)

MCP Servers provide Model Context Protocol configurations that enable AI assistants to interact with external tools and services.

### Supported JSON Formats

agent-add auto-detects two MCP configuration formats:

**Format A: Inner Config (Single Server)**

```json
{
  "command": "npx",
  "args": ["@playwright/mcp@latest"],
  "env": {}
}
```

The asset name is inferred from the filename: `playwright.json` → name is `playwright`.

**Format B: Full Config with `mcpServers` Wrapper**

```json
{
  "mcpServers": {
    "playwright": {
      "command": "npx",
      "args": ["@playwright/mcp@latest"]
    }
  }
}
```

agent-add automatically unwraps the `mcpServers` object and extracts the inner server name and configuration. This format currently supports a single server only.

资料来源：[README.md - Asset Developer Guide](README.md)

### Installation Behavior

- **JSON shallow merge**: New servers are merged into existing configuration
- **Atomic write**: Uses temp file + rename for safe writes
- **TOML support**: `.toml` extension auto-dispatches to TOML parsing path for Codex and Vibe hosts

```mermaid
graph LR
    A[MCP JSON Input] --> B{Extension Check}
    B -->|.json| C[JSON Handler]
    B -->|.toml| D[TOML Handler]
    C --> E[Shallow Merge]
    D --> E
    E --> F[Atomic Write]
    F --> G[host mcp config]
```

## Skill (`skill`)

Skills are reusable agent capabilities distributed as directory bundles.

### Structure Requirements

A valid Skill asset must be a directory containing a `SKILL.md` file at its root:

```
helpers/
├── utils.py
└── templates/
    └── report.md
```

The `SKILL.md` file defines the skill metadata:

```markdown
---
name: my-skill
description: A reusable agent skill.
---

# Skill: my-skill

This skill does something useful.
```

### Installation Behavior

- **Directory copy**: Entire directory is recursively copied to host's skills directory
- **Location**: Installed to `.cursor/skills/my-skill/` (path varies by host)
- **Validation**: Refuses installation if `SKILL.md` is missing

资料来源：[src/installer.ts:85-93]()

### Source Restrictions

Skills have strict source requirements:

| Allowed Source | Description |
|----------------|-------------|
| Local directory path | `~/path/to/skill` |
| Git URL | `https://github.com/user/repo.git#path/to/skill` |

| Prohibited Source | Reason |
|-------------------|--------|
| HTTP(S) URL | Not supported |
| Inline JSON | Not supported |
| Inline Markdown | Not supported |

资料来源：[src/installer.ts:85-93]()

## Prompt (`prompt`)

Prompts are rule files or system prompts that define agent behavior guidelines.

### Installation Strategies

Prompts use different write strategies based on host capabilities:

**Append Mode** (Cursor, Claude Code, etc.)

Content is wrapped in HTML comment markers and appended idempotently:

```html
<!-- agent-add:code-review-rules -->
# Code Review Rules

Always review for security issues first.
Use bullet points for lists.
<!-- /agent-add:code-review-rules -->
```

**Standalone File Mode** (Windsurf, Roo Code, etc.)

Creates a `<name>.md` file in the rules directory:

```
.windsurf/rules/code-review-rules.md
```

资料来源：[README.md - Prompt File]()

### Naming Convention

The asset name is inferred from the first `# Heading` in the Markdown content:

```markdown
# Code Review Rules
```

→ Asset name: `code-review-rules`

## Command (`command`)

Commands are slash commands that users can invoke directly in the AI assistant interface.

### File Format

Commands are Markdown files with optional YAML frontmatter:

```markdown
---
description: Run a comprehensive code review.
---

# code-review

Review the current file for bugs, security issues, and style violations.
```

### Installation Behavior

- **Installation directory**: Host-specific commands directory (e.g., `.cursor/commands/`)
- **File extension**: `.md`
- **Naming**: Derived from filename or `# Heading`

## Sub-agent (`subAgent`)

Sub-agents are specialized AI agents with their own configuration and instructions.

### File Format

Sub-agents use Markdown with YAML frontmatter, supporting host specialization:

```markdown
---
name: playwright-tester
description: A playwright testing agent.
agent-add/cursor/model: fast
agent-add/claude-code/model: haiku
---

# Playwright Test Agent

Plan and generate Playwright tests.
```

### Host Specialization Syntax

The `agent-add/<host>/<key>` syntax allows different frontmatter values per host:

```mermaid
graph TD
    A[Sub-agent File] --> B[Installation Time]
    B --> C{Current Host}
    C -->|Cursor| D[Extract agent-add/cursor/*]
    C -->|Claude Code| E[Extract agent-add/claude-code/*]
    
    D --> F[Promote to top-level keys]
    E --> F
    F --> G[Remove agent-add/* prefixes]
    G --> H[Install Result]
```

**After installing to Cursor:**

```markdown
---
name: playwright-tester
description: A playwright testing agent.
model: fast
---

# Playwright Test Agent
```

**After installing to Claude Code:**

```markdown
---
name: playwright-tester
description: A playwright testing agent.
model: haiku
---

# Playwright Test Agent
```

## Asset Validation

Each asset type undergoes validation before installation:

```mermaid
graph TD
    A[Resolved Source] --> B{Asset Type}
    
    B -->|skill| C{Directory Check}
    C -->|Missing SKILL.md| D[Error: Exit 2]
    C -->|Valid| E[Pass]
    
    B -->|mcp| F{File Check}
    F -->|File not exist| G[Error: Exit 2]
    F -->|.json extension?| H[Error: Exit 2]
    F -->|Valid| E
    
    B -->|prompt| I{Name from Heading}
    I -->|No heading| J[Error: Exit 2]
    I -->|Valid| E
    
    B -->|command| I
    B -->|subAgent| I
```

资料来源：[src/installer.ts:71-101]()

### Validation Rules by Type

| Asset Type | Checks |
|------------|--------|
| `mcp` | File exists, `.json` extension |
| `skill` | Directory exists, contains `SKILL.md` |
| `prompt` | First `# Heading` exists (for name inference) |
| `command` | First `# Heading` exists |
| `subAgent` | First `# Heading` exists |

## Pack Manifest Integration

Asset types are bundled in pack manifests for distribution:

```json
{
  "name": "my-team/frontend-pack",
  "assets": [
    { "type": "mcp",      "source": "https://github.com/modelcontextprotocol/servers.git#.mcp.json" },
    { "type": "skill",    "source": "https://github.com/anthropics/skills.git#skills/pdf" },
    { "type": "prompt",   "source": "https://raw.githubusercontent.com/PatrickJS/awesome-cursorrules/main/rules/nextjs-react-tailwind/.cursorrules" },
    { "type": "command",  "source": "https://github.com/wshobson/commands.git#tools/security-scan.md" },
    { "type": "subAgent", "source": "https://github.com/VoltAgent/awesome-claude-code-subagents.git#categories/01-core-development/backend-developer.md" }
  ]
}
```

### Asset Name Inference Rules

When a pack manifest doesn't specify an asset name, it is inferred from the source:

| Source Pattern | Name Inference |
|----------------|----------------|
| Git URL + `#path` | Last segment after `#`, strip extension |
| Git URL without `#` | Repo name, strip `.git` suffix |
| Local path / HTTP | Filename, strip extension |
| Inline JSON `{...}` | Top-level key as MCP name |
| Inline Markdown with `\n` | First `# Heading` in kebab-case |

资料来源：[src/source/infer-name.ts]()

---

<a id='manifest-system'></a>

## Manifest System

### 相关页面

相关主题：[Asset Types](#asset-types), [CLI Interface](#cli-interface)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/manifest/parser.ts](https://github.com/pea3nut/agent-add/blob/main/src/manifest/parser.ts)
- [src/manifest/schema.ts](https://github.com/pea3nut/agent-add/blob/main/src/manifest/schema.ts)
- [src/installer.ts](https://github.com/pea3nut/agent-add/blob/main/src/installer.ts)
- [src/source/infer-name.ts](https://github.com/pea3nut/agent-add/blob/main/src/source/infer-name.ts)
- [vibe/manifest.json](https://github.com/pea3nut/agent-add/blob/main/vibe/manifest.json)
- [README.md](https://github.com/pea3nut/agent-add/blob/main/README.md)
</details>

# Manifest System

The Manifest System is a core component of agent-add that enables batch installation of multiple assets through a single JSON configuration file. It provides a declarative way to define, distribute, and install a collection of AI agent assets (MCPs, Skills, Prompts, Commands, and Sub-agents) as a single package.

## Overview

Agent Packs are JSON files that bundle multiple assets together, allowing developers and teams to share complete asset collections with a single reference. The Manifest System handles parsing, validation, and processing of these pack manifests.

```mermaid
graph TD
    A[Pack Manifest JSON] --> B[Manifest Parser]
    B --> C{Validation}
    C -->|Pass| D[Asset Descriptor Array]
    C -->|Fail| E[Error Exit 2]
    D --> F[Source Resolver]
    F --> G[Install Jobs]
    G --> H[Asset Handlers]
    H --> I[Host Installation]
```

## Manifest File Format

### Schema Structure

The manifest schema is defined using Zod for runtime validation. The file path to the schema definition is:

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | `string` | Yes | Pack identifier in `namespace/pack-name` format. Only `[a-zA-Z0-9_-]` characters allowed |
| `assets` | `Asset[]` | Yes | Array of asset definitions, minimum 1 item |

### Asset Definition

Each asset in the `assets` array has the following structure:

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `type` | `string` | Yes | Asset type: `mcp`, `skill`, `prompt`, `command`, or `subAgent` |
| `source` | `string` | Yes | Source location (Git URL, local path, or HTTP URL) |

资料来源：[README.md](https://github.com/pea3nut/agent-add/blob/main/README.md)

### Example Manifest

```json
{
  "name": "my-team/frontend-pack",
  "assets": [
    { "type": "mcp",      "source": "https://github.com/modelcontextprotocol/servers.git#/.mcp.json" },
    { "type": "skill",    "source": "https://github.com/anthropics/skills.git#skills/pdf" },
    { "type": "prompt",   "source": "https://raw.githubusercontent.com/PatrickJS/awesome-cursorrules/main/rules/nextjs-react-tailwind/.cursorrules" },
    { "type": "command",  "source": "https://github.com/wshobson/commands.git#tools/security-scan.md" },
    { "type": "subAgent", "source": "https://github.com/VoltAgent/awesome-claude-code-subagents.git#categories/01-core-development/backend-developer.md" }
  ]
}
```

资料来源：[README.md](https://github.com/pea3nut/agent-add/blob/main/README.md)

## Source Syntax for Manifests

The manifest parser supports multiple source formats that are resolved to local paths:

```mermaid
graph LR
    A[Source String] --> B{Format Detection}
    B --> C[#path segment]
    B --> D[Git URL .git suffix]
    B --> E[Local/HTTP path]
    
    C --> F[kebab-case name from path]
    D --> G[repo name without .git]
    E --> H[filename without extension]
```

### Source Resolution Rules

| Source Format | Name Extraction Rule | Example |
|--------------|---------------------|---------|
| Git URL with `#path` | Take last segment after `#`, strip extension | `...git#skills/pdf` → `pdf` |
| Git URL without `#` | Take repo name, strip `.git` suffix | `...playwright.git` → `playwright` |
| Local path / HTTP URL | Take filename, strip extension | `./mcps/playwright.json` → `playwright` |

资料来源：[src/source/infer-name.ts](https://github.com/pea3nut/agent-add/blob/main/src/source/infer-name.ts)

### Inline Sources

Manifests support two inline source formats:

| Format | Detection | Name Source |
|--------|-----------|-------------|
| `inline-json` | Starts with `{` | Single top-level JSON key |
| `inline-md` | Contains `\n` (newlines) | First `# Heading` in Markdown, converted to kebab-case |

Both inline sources are written to temporary files before following the normal installation flow.

## Parser Implementation

### Entry Point

The manifest parser is invoked from the installer orchestrator. When `--pack` flags are detected, the parser processes each manifest file:

```mermaid
sequenceDiagram
    participant CLI as CLI Input
    participant Inst as Installer
    participant MP as Manifest Parser
    participant SR as Source Resolver
    
    CLI->>Inst: pack: [manifest.json, ...]
    Inst->>MP: parseManifest(filePath)
    MP->>MP: Read JSON file
    MP->>MP: Zod validation
    alt Valid
        MP-->>Inst: ManifestData[]
    else Invalid
        MP->>Inst: Error + Exit 2
    end
    Inst->>SR: Resolve each asset source
```

### Validation Flow

The parser performs comprehensive validation using Zod schema validation:

1. **Schema validation**: Checks required fields and types
2. **Name format validation**: Ensures `name` matches `namespace/pack-name` pattern
3. **Asset type validation**: Verifies all `type` fields are in the allowed set
4. **Error reporting**: Provides specific error messages with field paths

资料来源：[src/manifest/parser.ts](https://github.com/pea3nut/agent-add/blob/main/src/manifest/parser.ts)

### Error Handling

The parser provides structured error messages for common validation failures:

| Error Condition | Message |
|-----------------|---------|
| Invalid asset type | `Unsupported asset type: '<type>'. Supported: mcp, skill, prompt, command, subAgent` |
| Invalid name format | `Manifest name must match namespace/pack-name format` |
| Missing required field | `Manifest missing required field: <field path>` |
| JSON parse failure | `Invalid Manifest format` |

资料来源：[src/manifest/parser.ts](https://github.com/pea3nut/agent-add/blob/main/src/manifest/parser.ts)

## Integration with Installer

### Processing Pipeline

```mermaid
graph TD
    subgraph Input Processing
        A[Pack Manifests] --> B[Parse Each Manifest]
        B --> C[Extract Asset Descriptors]
    end
    
    subgraph Resolution
        C --> D[Resolve Sources]
        D --> E[Validate Each Asset]
    end
    
    subgraph Job Creation
        E --> F{Capability Check}
        F -->|Supported| G[Create Install Job]
        F -->|Unsupported| H[Skip Result]
    end
    
    subgraph Execution
        G --> I[Execute Handler]
        I --> J[Install Result]
    end
```

### Manifest Processing in Installer

The installer processes manifests in the following sequence:

1. **Parse**: Each manifest file is parsed to extract asset descriptors
2. **Resolve**: Asset sources are resolved to local file paths
3. **Validate**: Each asset is validated according to its type requirements
4. **Filter**: Assets unsupported by the target host are skipped
5. **Execute**: Valid assets are processed by appropriate handlers

资料来源：[src/installer.ts](https://github.com/pea3nut/agent-add/blob/main/src/installer.ts)

### Skip Behavior for Pack Sources

Unlike explicit flag sources, pack sources that target unsupported asset types are **silently skipped** rather than causing errors. This design allows pack authors to create cross-host compatible manifests without requiring per-host manifest files.

> Note: This is different from explicit flags, which exit with error code 2 if the asset type is unsupported.

## CLI Usage

### Installing a Pack

```bash
# Single pack installation
npx -y agent-add --host cursor --pack ./manifest.json

# Multiple packs
npx -y agent-add --host claude-code \
  --pack ./frontend-pack.json \
  --pack ./backend-pack.json

# Combined with explicit assets
npx -y agent-add --host cursor \
  --pack ./team-pack.json \
  --mcp ./local-mcp.json
```

### All `--pack` Flag Options

| Flag | Description | Collectable |
|------|-------------|-------------|
| `--pack <source>` | Install an Agent Pack manifest | Yes (repeatable) |

All asset flags can be repeated and freely combined with `--pack`.

## Development and Testing

### Test Coverage

The manifest system is tested through:

| Test Type | Location | Purpose |
|-----------|----------|---------|
| Unit tests | `tests/unit/` | Parser validation, name inference |
| Contract tests | `tests/contract/` | CLI black-box behavior |
| Feature tests | `tests/features/` | End-to-end scenarios |

### Running Tests

```bash
# All unit + integration tests
npm test

# Contract tests only
npm run test:contract

# Single manifest parser test
npx vitest run tests/unit/manifest/parser.test.ts
```

### Development Setup

```bash
npm install
npm run build
npm run install:vibe  # Installs dev assets via pack manifest
```

The `install:vibe` command installs assets defined in `vibe/manifest.json`, demonstrating the pack manifest system in action.

## Related Components

| Component | File | Role |
|-----------|------|------|
| Schema | `src/manifest/schema.ts` | Zod schema definition for ManifestData |
| Parser | `src/manifest/parser.ts` | Parsing and validation logic |
| Name Inference | `src/source/infer-name.ts` | Extracts asset names from sources |
| Installer | `src/installer.ts` | Orchestrates manifest processing |
| CLI | `src/cli.ts` | Command-line argument handling |

## Key Design Decisions

| Decision | Rationale |
|----------|-----------|
| Pack sources skip unsupported types | Enables cross-host manifest sharing without per-host variants |
| Explicit flags error on unsupported types | Forces developers to handle host compatibility explicitly |
| Atomic JSON writes for MCP | Ensures config file integrity during concurrent operations |
| Temp file + rename strategy | Provides atomicity for manifest-based MCP installations |
| Zod for schema validation | Runtime type checking with detailed error messages |

---

<a id='cli-interface'></a>

## CLI Interface

### 相关页面

相关主题：[Getting Started](#getting-started), [Manifest System](#manifest-system)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/cli.ts](https://github.com/pea3nut/agent-add/blob/main/src/cli.ts)
- [src/index.ts](https://github.com/pea3nut/agent-add/blob/main/src/index.ts)
- [src/installer.ts](https://github.com/pea3nut/agent-add/blob/main/src/installer.ts)
- [bin/agent-add.js](https://github.com/pea3nut/agent-add/blob/main/bin/agent-add.js)
- [package.json](https://github.com/pea3nut/agent-add/blob/main/package.json)
</details>

# CLI Interface

The CLI Interface is the primary user-facing component of agent-add, responsible for command-line argument parsing, host detection, input validation, and orchestrating the installation workflow. It serves as the entry point for all asset installation operations.

## Overview

agent-add provides a unified command-line interface for installing MCP servers, Skills, Prompts, Commands, and Sub-agents across 18 different AI agent hosts. The CLI handles argument parsing using the `commander` library and delegates actual installation logic to the `installer` module.

```mermaid
graph TD
    A[User CLI Command] --> B[bin/agent-add.js]
    B --> C[src/index.ts]
    C --> D[src/cli.ts - createProgram]
    D --> E[program.parseAsync process.argv]
    E --> F[Input Validation]
    F --> G[runInstaller cliInput, host, cwd]
    G --> H[printSummary results]
    H --> I[Exit: 0=success, 1=conflict/error, 2=validation]
```

资料来源：[src/index.ts:1-8](https://github.com/pea3nut/agent-add/blob/main/src/index.ts)

## Entry Points

### Binary Entry Point

The CLI binary is defined at `bin/agent-add.js` and serves as the executable entry point for the npm package. It is registered in `package.json` under the `bin` field.

```javascript
#!/usr/bin/env node
import '../dist/index.js';
```

资料来源：[bin/agent-add.js](https://github.com/pea3nut/agent-add/blob/main/bin/agent-add.js)

### Module Entry Point

The TypeScript module entry at `src/index.ts` creates the program and handles top-level error catching:

```typescript
import { createProgram } from './cli.js';

const program = createProgram();
program.parseAsync(process.argv).catch((err: Error) => {
  process.stderr.write(`agent-add error: ${err.message}\n`);
  process.exit(2);
});
```

资料来源：[src/index.ts:1-8](https://github.com/pea3nut/agent-add/blob/main/src/index.ts)

## Command Structure

### Global Options

| Option | Type | Description |
|--------|------|-------------|
| `--host <host>` | string | Target host ID (cursor, claude-code, claude-desktop, etc.) |
| `-V, --version` | boolean | Show version number |
| `-h, --help` | boolean | Show help information |

### Asset Installation Flags

All asset flags can be repeated to install multiple assets of the same type and can be freely combined with `--pack`:

| Flag | Type | Description |
|------|------|-------------|
| `--pack <source>` | string[] | Install an Agent Pack manifest |
| `--mcp <source>` | string[] | Install an MCP server config |
| `--skill <source>` | string[] | Install a Skill directory |
| `--prompt <source>` | string[] | Install a Prompt file |
| `--command <source>` | string[] | Install a Command file |
| `--sub-agent <source>` | string[] | Install a Sub-agent file |

资料来源：[src/cli.ts](https://github.com/pea3nut/agent-add/blob/main/src/cli.ts)

## Command Definition

The `createProgram()` function in `src/cli.ts` defines the Commander program structure:

```typescript
function createProgram() {
  const program = new Command();

  program
    .name('agent-add')
    .description('Install AI agent assets into different hosts')
    .argument('[sources...]', 'Sources to install')
    .option('--pack <source>', 'Install an Agent Pack manifest', collect, [])
    .option('--mcp <source>', 'Install an MCP server', collect, [])
    .option('--skill <source>', 'Install a Skill directory', collect, [])
    .option('--prompt <source>', 'Install a Prompt file', collect, [])
    .option('--command <source>', 'Install a Command file', collect, [])
    .option('--sub-agent <source>', 'Install a Sub-agent file', collect, [])
    .option('--host <host>', 'Target host ID', collect, [])
    .action(async (options) => { /* ... */ });

  return program;
}
```

资料来源：[src/cli.ts](https://github.com/pea3nut/agent-add/blob/main/src/cli.ts)

## Input Collection

The `collect()` helper function accumulates multiple values when flags are repeated:

```typescript
function collect(value: string, previous: string[]): string[] {
  return [...previous, value];
}
```

This enables usage patterns like:
```bash
agent-add --mcp server1.json --mcp server2.json --skill ./my-skill
```

资料来源：[src/cli.ts](https://github.com/pea3nut/agent-add/blob/main/src/cli.ts)

## Input Validation Flow

```mermaid
graph TD
    A[Parse CLI Options] --> B{Has Asset Flags?}
    B -->|No| C[Error: No asset flags provided]
    C --> D[Exit 2]
    B -->|Yes| E{Host Specified?}
    E -->|No| F{TTY Mode?}
    F -->|Yes| G[Interactive Host Selection]
    F -->|No| H[Error: --host required in CI]
    G --> I[Selected Host]
    E -->|Yes| I
    I --> J[runInstaller cliInput, host, cwd]
    J --> K[printSummary]
    K --> L{Results contain errors?}
    L -->|Yes| M[Exit 1]
    L -->|No| N[Exit 0]
```

### Asset Flag Validation

Before proceeding, the CLI verifies at least one asset flag is provided:

```typescript
const hasAssetFlags =
  cliInput.pack.length > 0 ||
  cliInput.mcp.length > 0 ||
  cliInput.skill.length > 0 ||
  cliInput.prompt.length > 0 ||
  cliInput.command.length > 0 ||
  cliInput.subAgent.length > 0;

if (!hasAssetFlags) {
  process.stderr.write(
    'agent-add error: No asset flags provided. Use --pack, --mcp, --skill, --prompt, --command, or --sub-agent.\n',
  );
  process.exit(2);
}
```

资料来源：[src/cli.ts](https://github.com/pea3nut/agent-add/blob/main/src/cli.ts)

## Host Selection

### Explicit Host Specification

When `--host` is explicitly provided, it is used directly:

```typescript
if (cliInput.host) {
  hostId = cliInput.host;
}
```

### Interactive Host Selection

In TTY (interactive) mode, if no host is specified, the CLI presents an interactive selection menu:

```typescript
else if (process.stdout.isTTY) {
  const selected = await inquirer.prompt([{
    type: 'select',
    name: 'host',
    message: 'Select your AI agent host:',
    choices: getValidHostIds(),
  }]);
  hostId = selected.host;
}
```

### Non-TTY Strict Mode

In CI/non-interactive environments, the CLI requires explicit host specification and exits with code 2 if missing:

```typescript
else {
  const validIds = getValidHostIds().join(', ');
  process.stderr.write(
    `agent-add error: --host flag required in non-TTY environment. Valid hosts: ${validIds}\n`,
  );
  process.exit(2);
}
```

资料来源：[src/cli.ts](https://github.com/pea3nut/agent-add/blob/main/src/cli.ts)

## CliInput Data Model

The `CliInput` interface defines the internal representation of parsed CLI arguments:

```typescript
interface CliInput {
  pack: string[];
  mcp: string[];
  skill: string[];
  prompt: string[];
  command: string[];
  subAgent: string[];
  host?: string;
}
```

This is populated from the command options and passed to the installer:

```typescript
const cliInput: CliInput = {
  mcp: options.mcp,
  skill: options.skill,
  prompt: options.prompt,
  command: options.command,
  subAgent: options.subAgent,
  pack: options.pack,
  host: options.host,
};
```

资料来源：[src/cli.ts](https://github.com/pea3nut/agent-add/blob/main/src/cli.ts)

## Error Handling

### Top-Level Error Handler

The entry point catches all unhandled errors and exits with code 2:

```typescript
program.parseAsync(process.argv).catch((err: Error) => {
  process.stderr.write(`agent-add error: ${err.message}\n`);
  process.exit(2);
});
```

### Action-Level Error Handling

The main action also handles install results for conflicts and errors:

```typescript
const hasConflicts = summary.results.some((r) => r.status === 'conflict');
const hasErrors = summary.results.some((r) => r.status === 'error');

if (hasErrors || hasConflicts) {
  process.exit(1);
}
```

## Exit Codes

| Code | Meaning | Trigger |
|------|---------|---------|
| 0 | Success | All assets installed without errors or conflicts |
| 1 | Partial failure | Install completed but had conflicts or errors |
| 2 | Validation failure | Invalid input, missing flags, or unsupported operations |

资料来源：[src/index.ts:6](https://github.com/pea3nut/agent-add/blob/main/src/index.ts) and [src/cli.ts](https://github.com/pea3nut/agent-add/blob/main/src/cli.ts)

## Usage Examples

### Install Single Asset

```bash
npx -y agent-add --host cursor --mcp ./playwright.json
```

### Install Multiple Assets

```bash
npx -y agent-add --host claude-code \
  --mcp ./mcp/servers.json \
  --skill ./skills/pdf \
  --prompt 'https://raw.githubusercontent.com/.../rules.md'
```

### Install via Pack Manifest

```bash
npx -y agent-add --host cursor --pack ./manifest.json
```

### Interactive Mode

```bash
npx -y agent-add --mcp ./server.json
# (Prompts for host selection if in TTY mode)
```

资料来源：[README.md](https://github.com/pea3nut/agent-add/blob/main/README.md)

## Package Configuration

The CLI binary is registered in `package.json`:

```json
{
  "bin": {
    "agent-add": "./bin/agent-add.js"
  },
  "type": "module",
  "engines": {
    "node": ">=18"
  }
}
```

资料来源：[package.json](https://github.com/pea3nut/agent-add/blob/main/package.json)

---

<a id='testing'></a>

## Testing

### 相关页面

相关主题：[Project Configuration](#configuration)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [package.json](https://github.com/pea3nut/agent-add/blob/main/package.json)
- [README.md](https://github.com/pea3nut/agent-add/blob/main/README.md)
- [vibe/manifest.json](https://github.com/pea3nut/agent-add/blob/main/vibe/manifest.json)
- [vibe/system-prompt.md](https://github.com/pea3nut/agent-add/blob/main/vibe/system-prompt.md)
- [vibe/tasks/verify-host-readme.md](https://github.com/pea3nut/agent-add/blob/main/vibe/tasks/verify-host-readme.md)
- [src/installer.ts](https://github.com/pea3nut/agent-add/blob/main/src/installer.ts)
</details>

# Testing

## Overview

The agent-add project employs a multi-layered testing strategy to ensure reliability across different host environments and asset types. The testing infrastructure validates the CLI tool's functionality through unit tests, integration tests, contract tests, and scenario-based tests executed by AI agents.

## Test Architecture

The testing framework is built on **Vitest** with a three-tier approach:

```mermaid
graph TD
    A[Test Suite] --> B[Unit Tests]
    A --> C[Integration Tests]
    A --> D[Contract Tests]
    A --> E[Scenario Tests]
    
    B --> B1[vitest run]
    C --> C1[vitest run]
    D --> D1[Black-box CLI tests]
    E --> E1[AI Agent execution]
    
    style A fill:#e1f5fe
    style D fill:#fff3e0
    style E fill:#f3e5f5
```

## Test Configuration

The Vitest configuration is defined in `vitest.config.ts`:

| Configuration Aspect | Value |
|---------------------|-------|
| Test Runner | Vitest 4.1.0 |
| TypeScript Target | Node.js 18+ |
| Test Location | `tests/` directory |
| Run Command | `npm test` |

## Test Categories

### Unit Tests

Unit tests verify individual components in isolation. Each host adapter has corresponding unit tests.

**Test Location:** `tests/unit/hosts/<id>.test.ts`

**Example - Cursor Host Test:**
```typescript
npx vitest run tests/unit/hosts/cursor.test.ts
```

Unit tests verify:
- Adapter `id`, `displayName`, and `docs` values
- Asset capabilities match the README matrix
- Supported capabilities have required fields

### Integration Tests

Integration tests validate the interaction between components.

**Command:** `npm run test:integration`

### Contract Tests

Contract tests perform black-box CLI testing without requiring the full test suite.

**Command:** `npm run test:contract`

### Scenario Tests

Scenario tests use Gherkin `.feature` files executed by AI agents via [scenario-test](https://github.com/pea3nut/scenario-test).

**Location Structure:**
```
tests/
├── features/
│   ├── scenario-run-config.md  # Run configuration
│   ├── core/                    # Core behavior tests (7 .feature files)
│   └── host/                    # Host compatibility tests (3 .feature files)
└── fixtures/                    # Static test fixtures
```

**Execution Commands:**
```bash
/scenario-exec tests/features/core
/scenario-exec tests/features/host
```

Each scenario runs in an isolated temporary directory. The run configuration is defined in `tests/features/scenario-run-config.md`.

## Test Fixtures

Static test fixtures support different asset types:

```
tests/fixtures/
├── mcp/
├── skill/
├── prompt/
├── command/
├── sub-agent/
└── pack/
```

Fixtures are used by both unit tests and scenario tests to provide consistent test data.

## Development Testing Workflow

### Setup

Before running tests, build the project:

```bash
npm install
npm run build
```

### Running Tests

| Command | Purpose |
|---------|---------|
| `npm test` | All unit + integration tests |
| `npm run test:contract` | CLI black-box contract tests only |
| `npm run test:integration` | Integration tests |
| `npx vitest run tests/unit/hosts/cursor.test.ts` | Single unit test file |

### Vibe Development Assets

The project uses a custom testing manifest for development:

**File:** `vibe/manifest.json`

```json
{
  "name": "agent-add/dev-pack",
  "assets": [
    { "type": "skill", "source": "https://github.com/pea3nut/scenario-test.git#skills/scenario-test" },
    { "type": "command", "source": "https://github.com/pea3nut/scenario-test.git#commands/scenario-exec.md" },
    { "type": "subAgent", "source": "https://github.com/pea3nut/scenario-test.git#agents/scenario-case-runner.md" },
    { "type": "command", "source": "./vibe/tasks/verify-host-readme.md" },
    { "type": "prompt", "source": "./vibe/system-prompt.md" }
  ]
}
```

Install dev assets via:
```bash
npm run install:vibe
```

This installs:
- **scenario-test skill**: Provides testing infrastructure
- **scenario-exec command**: Triggers scenario test execution
- **scenario-case-runner sub-agent**: AI agent that executes scenarios
- **verify-host-readme command**: Validates host README consistency
- **system-prompt**: Development system prompt

## Host README Verification

The `verify-host-readme.md` task validates consistency between the host capability matrix in `src/hosts/README.md` and actual adapter implementations.

**Validation Criteria:**
- Adapter configuration fields match README matrix values exactly
- Unit tests assert exact values for every field
- New host contributions must update both adapter and README

## Linting and Type Checking

Before test execution, validate code quality:

```bash
npm run lint   # tsc --noEmit type checking
```

## Test Isolation

The testing framework ensures isolation through:

1. **Temporary directories** - Scenario tests run in isolated temp directories
2. **Temp file writes** - MCP config uses temp file + rename for safety
3. **AGENT_ADD_HOME override** - Environment variable redirects install paths for test isolation

## Dependencies

Test infrastructure relies on:

| Package | Version | Purpose |
|---------|---------|---------|
| vitest | ^4.1.0 | Test runner |
| tsx | ^4.21.0 | TypeScript execution |
| typescript | ^5.9.3 | Type checking |
| scenario-test | (external) | Scenario test framework |

---

<a id='configuration'></a>

## Project Configuration

### 相关页面

相关主题：[Testing](#testing)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [package.json](https://github.com/pea3nut/agent-add/blob/main/package.json)
- [tsup.config.ts](https://github.com/pea3nut/agent-add/blob/main/tsup.config.ts)
- [src/cli.ts](https://github.com/pea3nut/agent-add/blob/main/src/cli.ts)
- [src/installer.ts](https://github.com/pea3nut/agent-add/blob/main/src/installer.ts)
- [src/hosts/types.ts](https://github.com/pea3nut/agent-add/blob/main/src/hosts/types.ts)
- [src/hosts/index.ts](https://github.com/pea3nut/agent-add/blob/main/src/hosts/index.ts)
- [src/assets/mcp.ts](https://github.com/pea3nut/agent-add/blob/main/src/assets/mcp.ts)
- [src/assets/skill.ts](https://github.com/pea3nut/agent-add/blob/main/src/assets/skill.ts)
- [src/assets/prompt.ts](https://github.com/pea3nut/agent-add/blob/main/src/assets/prompt.ts)
- [src/manifest/schema.ts](https://github.com/pea3nut/agent-add/blob/main/src/manifest/schema.ts)
</details>

# Project Configuration

## Overview

The agent-add project uses a multi-layered configuration system to support installing various asset types across 18 different AI coding hosts. The configuration architecture encompasses TypeScript compilation settings, build tooling via tsup, package metadata, host adapter definitions, asset handler configurations, and source resolution strategies.

The project targets Node.js 18+ and compiles to CommonJS format for maximum compatibility with AI coding tool environments. 资料来源：[package.json:17]()

## Build System Configuration

### tsup Build Configuration

The project uses [tsup](https://github.com/egoist/tsup) for TypeScript bundling, defined in `tsup.config.ts`:

```typescript
import { defineConfig } from 'tsup';

export default defineConfig({
  entry: ['src/index.ts'],
  format: ['cjs'],
  target: 'node18',
  clean: true,
  sourcemap: true,
  dts: false,
  outDir: 'dist',
  noExternal: [/.*/],
});
```

| Option | Value | Purpose |
|--------|-------|---------|
| `entry` | `['src/index.ts']` | Single entry point for CLI application |
| `format` | `['cjs']` | CommonJS output format for Node.js compatibility |
| `target` | `node18` | Transpile for Node.js 18 environment |
| `clean` | `true` | Remove previous build artifacts before each build |
| `sourcemap` | `true` | Generate source maps for debugging |
| `dts` | `false` | Disable TypeScript declaration generation |
| `outDir` | `'dist'` | Output directory for compiled files |
| `noExternal` | `[/.*/]` | Bundle all dependencies into output |

资料来源：[tsup.config.ts:1-11]()

### Build Scripts

The npm scripts in `package.json` define the development workflow:

```json
{
  "scripts": {
    "build": "tsup",
    "dev": "tsx watch src/index.ts",
    "test": "vitest run",
    "install:vibe": "npx -y agent-add -- --pack vibe/manifest.json"
  }
}
```

| Script | Command | Usage |
|--------|---------|-------|
| `build` | `tsup` | Compile TypeScript to JavaScript |
| `dev` | `tsx watch src/index.ts` | Development mode with hot reload |
| `test` | `vitest run` | Execute unit and integration tests |
| `install:vibe` | `agent-add -- --pack vibe/manifest.json` | Install development assets via pack manifest |

资料来源：[package.json:27-31]()

## Package Configuration

### Engine Requirements

```json
"engines": {
  "node": ">=18"
}
```

The project requires Node.js 18 or higher due to ES module features and modern JavaScript APIs used throughout the codebase. 资料来源：[package.json:35-37]()

### Core Dependencies

The project relies on several key runtime dependencies:

| Dependency | Version | Purpose |
|------------|---------|---------|
| `commander` | ^14.0.3 | CLI argument parsing |
| `smol-toml` | ^1.6.1 | TOML format parsing for Codex/Vibe hosts |
| `yaml` | ^2.8.2 | YAML frontmatter parsing for sub-agents |
| `zod` | ^4.3.6 | Manifest schema validation |

Development dependencies include TypeScript, vitest for testing, and tsx for development execution. 资料来源：[package.json:11-24]()

## Host Adapter Configuration

### Host Adapter Type System

The host configuration system uses a TypeScript interface defined in `src/hosts/types.ts`:

```typescript
interface AssetCapability {
  supported: boolean;
  reason?: string;
  configFile?: string;
  installDir?: string;
  writeStrategy?: 'append-with-marker' | 'create-file-in-dir';
}

interface HostAdapter {
  id: string;
  displayName: string;
  docs: string;
  assets: Record<AssetType, AssetCapability>;
}
```

资料来源：[src/hosts/types.ts]()

### Host Capability Matrix

The project supports 18 distinct hosts, each with unique capability profiles:

| Host ID | MCP | Prompt | Skill | Command | Sub-agent |
|---------|-----|--------|-------|---------|-----------|
| `cursor` | ✅ | ✅ | ✅ | ✅ | ✅ |
| `claude-code` | ✅ | ✅ | ❌ | ✅ | ✅ |
| `claude-desktop` | ✅ | ❌ | ❌ | ❌ | ❌ |
| `windsurf` | ✅ | ✅ | ❌ | ❌ | ❌ |
| `codex` | ✅ | ❌ | ❌ | ❌ | ❌ |
| `vibe` | ✅ | ❌ | ❌ | ❌ | ❌ |

Each host adapter hardcodes its configuration in a dedicated file under `src/hosts/<id>.ts` and registers in `src/hosts/index.ts` through the host registry Map. 资料来源：[src/hosts/README.md](), [src/hosts/index.ts]()

### Write Strategy Configuration

Hosts configure one of two write strategies for prompt assets:

```mermaid
graph TD
    A[Prompt Asset] --> B{Write Strategy}
    B --> C[append-with-marker]
    B --> D[create-file-in-dir]
    C --> E[HTML comment markers<br/>Idempotent append]
    D --> F[Standalone file creation<br/>Skip if exists]
```

**Append with Marker Strategy**: Used by Cursor, Claude Code, and similar hosts. Content is wrapped in HTML comment markers:

```html
<!-- agent-add:code-review-rules -->
# Code Review Rules
...
<!-- /agent-add:code-review-rules -->
```

**Create File in Dir Strategy**: Used by Windsurf, Roo Code, and similar hosts. Creates `<name>.md` in the rules directory, skipping if already exists. 资料来源：[src/assets/prompt.ts]()

## Asset Type Configuration

### MCP Asset Configuration

MCP assets support two JSON formats:

**Format A - Inner Config (Single Server)**:
```json
{
  "command": "npx",
  "args": ["@playwright/mcp@latest"],
  "env": {}
}
```

**Format B - Full Config with mcpServers Wrapper**:
```json
{
  "mcpServers": {
    "playwright": {
      "command": "npx",
      "args": ["@playwright/mcp@latest"]
    }
  }
}
```

The system automatically detects `.toml` extension and dispatches to the TOML handler path for Codex and Vibe hosts. 资料来源：[src/assets/mcp.ts]()

### Skill Asset Configuration

Skills require a specific directory structure with a mandatory `SKILL.md` file:

```markdown
<!-- SKILL.md -->
---
name: my-skill
description: A reusable agent skill.
---

# Skill: my-skill

This skill does something useful.
```

The skill handler validates the presence of `SKILL.md` before installation and recursively copies the directory to the host's skills directory. 资料来源：[src/assets/skill.ts](), [README.md]()

### Sub-agent Asset Configuration

Sub-agents support host specialization through the `agent-add/<host>/<key>` syntax in YAML frontmatter:

```markdown
---
name: playwright-tester
description: A playwright testing agent.
agent-get/cursor/model: fast
agent-get/claude-code/model: haiku
---

# Playwright Test Agent
```

The handler promotes matching `agent-add/<host>/*` values to top-level keys and removes all `agent-add/*` prefixed keys during installation. 资料来源：[src/assets/sub-agent.ts]()

## Manifest Schema Configuration

The pack manifest uses JSON Schema validation via Zod:

```typescript
const ManifestSchema = z.object({
  name: z.string().regex(/^[a-zA-Z0-9_-]+\/[a-zA-Z0-9_-]+$/),
  assets: z.array(AssetDescriptorSchema).min(1),
});
```

| Field | Type | Constraints |
|-------|------|-------------|
| `name` | string | Format `namespace/pack-name`, regex `[a-zA-Z0-9_-]/[a-zA-Z0-9_-]` |
| `assets` | array | Minimum 1 item |
| `assets[].type` | enum | `mcp`, `skill`, `prompt`, `command`, `subAgent` |
| `assets[].source` | string | URI or local path |

资料来源：[src/manifest/schema.ts]()

## Source Resolution Configuration

### Supported Source Types

```mermaid
graph LR
    A[Source Input] --> B{Source Type Detection}
    B --> C[local]
    B --> D[git-ssh]
    B --> E[git-https]
    B --> F[http-file]
    B --> G[inline-json]
    B --> H[inline-md]
```

| Source Type | Detection Rule | Supported Asset Types |
|-------------|----------------|------------------------|
| `local` | File path exists on filesystem | All |
| `git-ssh` | Starts with `git@` | All |
| `git-https` | Starts with `https://` or `http://` | All |
| `http-file` | Direct HTTP/HTTPS URL | MCP, Prompt, Command, Sub-agent |
| `inline-json` | Starts with `{` | MCP only |
| `inline-md` | Contains `\n` | Prompt, Command, Sub-agent |

**Note**: Skill assets do not support inline sources or direct HTTP URLs—exit code 2 is returned for these invalid sources. 资料来源：[src/source/inline.ts](), [src/installer.ts:52-57]()

### Asset Name Inference Rules

| Source Pattern | Name Extraction Rule | Example |
|----------------|---------------------|---------|
| Inline Markdown | First `# Heading` → kebab-case | `# Code Review` → `code-review` |
| Git URL with `#path` | Last segment after `#`, strip extension | `...git#skills/pdf` → `pdf` |
| Git URL without `#` | Repo name, strip `.git` suffix | `...playwright.git` → `playwright` |
| Local path / HTTP | Filename, strip extension | `./mcps/playwright.json` → `playwright` |

资料来源：[src/source/infer-name.ts]()

## Environment Configuration

### AGENT_ADD_HOME Environment Variable

The `AGENT_ADD_HOME` environment variable overrides `os.homedir()` return value in `src/assets/mcp.ts`. This redirects Claude Desktop and Codex host install paths to temporary directories for test isolation:

```typescript
const getHomeDir = (): string => {
  return process.env.AGENT_ADD_HOME || os.homedir();
};
```

资料来源：[src/assets/mcp.ts]()

## Installation Flow Configuration

### Core Data Flow

```mermaid
graph TD
    A[CLI flags / --pack Manifest] --> B[Explicit flag capability check]
    B -->|exit 2 if unsupported| C[AssetDescriptor array]
    C --> D[ResolvedSource array]
    D --> E[InstallJob array]
    E --> F[InstallResult array]
    F --> G[Summary output]
    
    B -.->|--pack skips check| B
```

The installation pipeline follows these stages:

1. **Input Parsing**: CLI flags or pack manifest → `AssetDescriptor[]`
2. **Capability Check**: Verify host supports requested asset types (exits 2 if unsupported)
3. **Source Resolution**: `AssetDescriptor[]` → `ResolvedSource[]` with local paths and temp directories
4. **Validation**: Each asset validated based on type-specific rules
5. **Job Creation**: `ResolvedSource[]` → `InstallJob[]` (skip unsupported assets)
6. **Handler Execution**: Process each job via type-specific handler
7. **Result Aggregation**: Collect `InstallResult[]` with statuses: written, exists, updated, conflict, skipped, error

资料来源：[src/installer.ts](), [src/cli.ts]()

### Explicit Flag Capability Checking

The installer checks explicit flag capability declarations before building jobs. When a host declares `supported: false` for an asset type:

1. Outputs error with reason and README link
2. Exits with code 2

This check is **skipped** for `--pack` sources, allowing pack manifests to include assets that may not be supported by all hosts. 资料来源：[src/installer.ts](), [src/hosts/README.md]()

## License

This project is licensed under the Mozilla Public License 2.0 (MPL-2.0).

---

---

## Doramagic 踩坑日志

项目：pea3nut/agent-add

摘要：发现 9 个潜在踩坑项，其中 0 个为 high/blocking；最高优先级：安装坑 - 来源证据：v1.1.0。

## 1. 安装坑 · 来源证据：v1.1.0

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安装相关的待验证问题：v1.1.0
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 建议检查：来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。
- 防护动作：不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。
- 证据：community_evidence:github | cevd_5c106a51ec5d4f999b8bcef8e68a89ec | https://github.com/pea3nut/agent-add/releases/tag/1.1.0 | 来源类型 github_release 暴露的待验证使用条件。

## 2. 安装坑 · 社区讨论暴露的待验证问题：I built a CLI that installs MCP, skills, prompts, commands and sub ...

- 严重度：medium
- 证据强度：source_linked
- 发现：I built a CLI that installs MCP, skills, prompts, commands and sub ... 6 Apr 2026 · Project & Supported Tools. The source code is hosted on GitHub: https://github.com/pea3nut/agent-add ... r/mcp - I built a tool that auto- ...
- 对用户的影响：这类外部讨论可能代表真实用户在安装、配置、升级或生产使用时遇到阻力；发布前不能只依赖官方 README。
- 建议检查：Pack Agent 需要打开来源链接，确认问题是否仍然存在，并把验证结论写入说明书和边界卡。
- 证据：social_signal:reddit | ssig_6d54ef81557a451081be71b052d0e31b | https://www.reddit.com/r/ClaudeAI/comments/1sdrk6k/i_built_a_cli_that_installs_mcp_skills_prompts/ | I built a CLI that installs MCP, skills, prompts, commands and sub ...

## 3. 配置坑 · 可能修改宿主 AI 配置

- 严重度：medium
- 证据强度：source_linked
- 发现：项目面向 Claude/Cursor/Codex/Gemini/OpenCode 等宿主，或安装命令涉及用户配置目录。
- 对用户的影响：安装可能改变本机 AI 工具行为，用户需要知道写入位置和回滚方法。
- 建议检查：列出会写入的配置文件、目录和卸载/回滚步骤。
- 防护动作：涉及宿主配置目录时必须给回滚路径，不能只给安装命令。
- 证据：capability.host_targets | art_7871f43a97e049c0ba0df6fa5a5b6e88 | https://github.com/pea3nut/agent-add#readme | host_targets=mcp_host, claude, claude_code, cursor, chatgpt

## 4. 能力坑 · 能力判断依赖假设

- 严重度：medium
- 证据强度：source_linked
- 发现：README/documentation is current enough for a first validation pass.
- 对用户的影响：假设不成立时，用户拿不到承诺的能力。
- 建议检查：将假设转成下游验证清单。
- 防护动作：假设必须转成验证项；没有验证结果前不能写成事实。
- 证据：capability.assumptions | art_7871f43a97e049c0ba0df6fa5a5b6e88 | https://github.com/pea3nut/agent-add#readme | README/documentation is current enough for a first validation pass.

## 5. 维护坑 · 维护活跃度未知

- 严重度：medium
- 证据强度：source_linked
- 发现：未记录 last_activity_observed。
- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。
- 建议检查：补 GitHub 最近 commit、release、issue/PR 响应信号。
- 防护动作：维护活跃度未知时，推荐强度不能标为高信任。
- 证据：evidence.maintainer_signals | art_7871f43a97e049c0ba0df6fa5a5b6e88 | https://github.com/pea3nut/agent-add#readme | last_activity_observed missing

## 6. 安全/权限坑 · 下游验证发现风险项

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 对用户的影响：下游已经要求复核，不能在页面中弱化。
- 建议检查：进入安全/权限治理复核队列。
- 防护动作：下游风险存在时必须保持 review/recommendation 降级。
- 证据：downstream_validation.risk_items | art_7871f43a97e049c0ba0df6fa5a5b6e88 | https://github.com/pea3nut/agent-add#readme | no_demo; severity=medium

## 7. 安全/权限坑 · 存在评分风险

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 对用户的影响：风险会影响是否适合普通用户安装。
- 建议检查：把风险写入边界卡，并确认是否需要人工复核。
- 防护动作：评分风险必须进入边界卡，不能只作为内部分数。
- 证据：risks.scoring_risks | art_7871f43a97e049c0ba0df6fa5a5b6e88 | https://github.com/pea3nut/agent-add#readme | no_demo; severity=medium

## 8. 维护坑 · issue/PR 响应质量未知

- 严重度：low
- 证据强度：source_linked
- 发现：issue_or_pr_quality=unknown。
- 对用户的影响：用户无法判断遇到问题后是否有人维护。
- 建议检查：抽样最近 issue/PR，判断是否长期无人处理。
- 防护动作：issue/PR 响应未知时，必须提示维护风险。
- 证据：evidence.maintainer_signals | art_7871f43a97e049c0ba0df6fa5a5b6e88 | https://github.com/pea3nut/agent-add#readme | issue_or_pr_quality=unknown

## 9. 维护坑 · 发布节奏不明确

- 严重度：low
- 证据强度：source_linked
- 发现：release_recency=unknown。
- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。
- 建议检查：确认最近 release/tag 和 README 安装命令是否一致。
- 防护动作：发布节奏未知或过期时，安装说明必须标注可能漂移。
- 证据：evidence.maintainer_signals | art_7871f43a97e049c0ba0df6fa5a5b6e88 | https://github.com/pea3nut/agent-add#readme | release_recency=unknown

<!-- canonical_name: pea3nut/agent-add; human_manual_source: deepwiki_human_wiki -->
