Doramagic Project Pack · Human Manual

agent-add

Related topics: Getting Started, System Architecture

Introduction

Related topics: Getting Started, System Architecture

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Quick Install

Continue reading this section for the full explanation and source context.

Section CLI Options

Continue reading this section for the full explanation and source context.

Related topics: Getting Started, System Architecture

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

Sources: README.md:1-50

Supported Hosts

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

Host IDConfiguration FormatInstall Directory
cursorJSON.cursor/
claude-codeJSON.claude/
claude-desktopJSON~/Library/Application Support/Claude/
windsurfJSON.windsurf/rules/
github-copilotJSON.github/copilot/
geminiJSON.gemini/
roo-codeJSON.roo/rules/
kilo-codeJSON.kilocode/
qwen-codeJSON.qwen/
opencodeJSON.opencode/
augmentJSON.augment/
kiroJSON.kiro/
tabnineJSON.tabnine/
kimiJSON.kimi/
traeJSON.trae/
openclawJSON.openclaw/
codexTOML.codex/
vibeTOML.vibe/

Sources: vibe/system-prompt.md:30-35

Supported Asset Types

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

Asset TypeDescriptionInstall Behavior
mcpModel Context Protocol server configurationsJSON shallow merge or TOML array append
skillReusable agent skill directoriesRecursive directory copy
promptSystem prompts or rule filesAppend-with-marker or create-file-in-dir
commandSlash commandsCreate in commands directory
subAgentSub-agent configurationsCreate in agents directory

Sources: src/installer.ts:1-50

Architecture Overview

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

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:

LayerModuleResponsibility
Inputsrc/cli.tsCommander.js argument parsing, TTY detection, interactive host selection
Coresrc/installer.tsOrchestration: input parsing → capability check → source resolution → validation → handler execution → summary
Resolutionsrc/source/Local file access, Git URL handling, HTTP fetching, inline content parsing
Adaptationsrc/hosts/Host-specific directory paths, capability declarations, write strategies
Executionsrc/assets/Type-specific installation logic (MCP merge, skill copy, prompt append, etc.)

Sources: vibe/system-prompt.md:45-65

Core Data Flow

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

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

Sources: src/cli.ts:1-80

Write Strategies

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

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]
StrategyUsed ByBehavior
append-with-markerPrompt (Cursor, Claude Code)Wraps content in HTML comment markers, idempotent append
create-file-in-dirPrompt (Windsurf, Roo Code), Command, Sub-agentCreates <name>.md in rules/commands/agents directory
atomic-json-mergeMCP (JSON hosts)Shallow merge with temp file + rename for safety
toml-array-appendMCP (Codex, Vibe)Append to [[mcp_servers]] array
directory-copySkillRecursive copy to host's skills directory

Sources: src/installer.ts:50-120

Source Resolution

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

Source FormatExampleName Inference
Git URL + #pathhttps://github.com/user/repo.git#skills/pdfLast segment after # (strip extension)
Git URL without #https://github.com/user/playwright.gitRepo name (strip .git)
Local path./mcps/playwright.jsonFilename (strip extension)
HTTP URLhttps://example.com/config.jsonFilename (strip extension)
Inline JSON{"playwright":{...}}Top-level key as name
Inline Markdown# Code Review\n\nRules...First # Heading in kebab-case

Sources: src/source/infer-name.ts:1-50

Installation and Usage

Quick Install

# 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

FlagDescriptionCan Repeat
--host <id>Target host ID (required in CI, optional in TTY)No
--pack <source>Install from a pack manifestYes
--mcp <source>Install MCP server configurationYes
--skill <source>Install skill directoryYes
--prompt <source>Install prompt/rule fileYes
--command <source>Install slash commandYes
--sub-agent <source>Install sub-agent fileYes

Sources: src/cli.ts:40-60

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. Sources: vibe/system-prompt.md:70-72

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.

Sources: src/installer.ts:80-100

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

Sources: README.md:80-100

Development

# 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

Sources: README.md:100-120

Sources: README.md:1-50

Getting Started

Related topics: Introduction, CLI Interface

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Using npx (Recommended for One-time Use)

Continue reading this section for the full explanation and source context.

Section Global Installation

Continue reading this section for the full explanation and source context.

Section Local Installation

Continue reading this section for the full explanation and source context.

Related topics: Introduction, CLI Interface

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. Sources: 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

npx -y agent-add --help

Global Installation

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

Local Installation

npm install
npm run build

The CLI entry point is located at bin/agent-add.js. Sources: README.md

Basic Usage

Interactive Mode

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

npx -y agent-add

The CLI detects available hosts in the current directory and presents an interactive selection menu. Sources: src/cli.ts:56-77

Non-interactive Mode

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

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

If --host is omitted in non-TTY environments, the CLI exits with error code 2. Sources: src/cli.ts:46-55

Supported Hosts

The following 18 hosts are supported:

Host IDTypeNotes
cursorJSONCursor IDE
claude-codeMarkdownClaude Code CLI
claude-desktopJSONClaude Desktop
windsurfJSONWindsurf IDE
github-copilotJSONGitHub Copilot
geminiJSONGoogle Gemini
roo-codeJSONRoo Code
kilo-codeJSONKilo Code
qwen-codeJSONQwen Code
opencodeJSONOpenCode
augmentJSONAugment
kiroJSONKiro
tabnineJSONTabnine
kimiJSONKimi
traeJSONTrae
openclawJSONOpenClaw
codexTOMLCodex
vibeTOMLVibe

Sources: README.md

Asset Types

1. MCP Server

Installs Model Context Protocol server configurations.

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

2. Skill

Installs reusable agent skill directories containing SKILL.md.

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. Sources: src/installer.ts:80-84

3. Prompt

Installs system prompts or rule files.

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.

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

5. Sub-agent

Installs specialized agent configurations.

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 TypeSyntax ExampleName Inference
Git URL with path...git#skills/pdfLast segment after #, stripped extension
Git URL without path...playwright.gitRepository name (strip .git)
Local path./mcps/playwright.jsonFilename (strip extension)
HTTP URLhttps://example.com/config.jsonFilename (strip extension)
Inline JSON{"playwright":{...}}Single top-level key
Inline Markdown# Heading\nContentFirst # Heading, kebab-cased

Sources: src/source/infer-name.ts:1-41

Pack Manifests

Bundles multiple assets for distribution via a JSON manifest:

{
  "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:

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

Pack names must follow namespace/pack-name format with only [a-zA-Z0-9_-] characters. Sources: src/manifest/parser.ts:1-31

Workflow Diagram

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

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

Sources: src/cli.ts:27-34

Examples

Install MCP Server from GitHub

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

Install Multiple Assets

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

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

Inline MCP Configuration

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

Directory Expansion

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

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. Sources: 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

Sources: src/installer.ts:78-107

Next Steps

Sources: README.md

System Architecture

Related topics: Host Integration, Source Resolution

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Pipeline Stages

Continue reading this section for the full explanation and source context.

Section Host Registry

Continue reading this section for the full explanation and source context.

Section Supported Hosts

Continue reading this section for the full explanation and source context.

Related topics: Host Integration, Source Resolution

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.

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

Sources: 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

Sources: README.md:1-45

Core Data Flow

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

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

StageInputOutputKey Operations
CLI Parsingprocess.argvCliInput objectTTY detection, host selection
Capability CheckCliInputAssetDescriptor[]Validates --host exists, checks explicit flags against host capabilities
Source ResolutionAssetDescriptor[]ResolvedSource[]Downloads Git/HTTP, extracts archives, writes inline sources to temp
Job CreationResolvedSource[]InstallJob[]Filters assets unsupported by target host
Handler ExecutionInstallJob[]InstallResult[]Writes files using host-specific strategies
SummaryInstallResult[]Console outputFormatted install summary

Sources: 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:

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()],
]);

Sources: src/hosts/index.ts Sources: src/hosts/README.md:1-100

Supported Hosts

Host IDMCPPromptSkillCommandSub-agentConfig Format
cursorJSON
claude-codeJSON
claude-desktopJSON
windsurfJSON
github-copilotJSON
codexTOML
vibeTOML

Sources: src/hosts/README.md:1-150

HostAdapter Interface

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

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;
}

Sources: src/hosts/types.ts

Write Strategies

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

StrategyDescriptionUsed By
append-with-markerAppends content wrapped in HTML comment markers (<!-- agent-add:name -->)Cursor, Claude Code
create-file-in-dirCreates standalone <name>.md file in rules directoryWindsurf, Roo Code, Kilo Code
json-mergeShallow JSON merge for MCP configMost hosts
toml-mergeTOML merge for Codex/Vibecodex, vibe

Sources: src/hosts/types.ts Sources: src/assets/prompt.ts Sources: src/assets/mcp.ts

Asset Handler Layer

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

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

Sources: src/assets/mcp.ts Sources: 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

Sources: src/assets/skill.ts Sources: src/installer.ts:50-100

Prompt Handler

The Prompt handler supports two write strategies:

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

  1. Append Mode (Cursor, Claude Code): Content is wrapped in idempotent HTML markers
  1. Standalone File Mode (Windsurf, Roo Code): Creates <name>.md in rules directory

Sources: src/assets/prompt.ts Sources: README.md:80-120

Sub-agent Handler

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

Sources: src/index.ts:1-7

Host Integration

Related topics: System Architecture, Asset Types

Section Related Pages

Continue reading this section for the full explanation and source context.

Section System Architecture

Continue reading this section for the full explanation and source context.

Section Data Flow

Continue reading this section for the full explanation and source context.

Section Interface Definition

Continue reading this section for the full explanation and source context.

Related topics: System Architecture, Asset Types

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

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

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

// 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

PropertyTypeDescription
idstringUnique identifier for the host (e.g., "cursor", "claude-code")
displayNamestringHuman-readable name (e.g., "Claude Code")
docsstringURL to official documentation
detection.pathsstring[]Directory paths that indicate this host is active
assetsRecord<AssetType, AssetCapability>Capability definitions for each asset type

Sources: src/hosts/types.ts

AssetCapability Types

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

AssetType Enum

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

Capability Structure

// 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 TypePurposeInstall Method
mcpModel Context Protocol serversModify config file (JSON or TOML)
skillReusable agent skill directoriesCopy directory recursively
promptSystem prompts / rule filesAppend or create standalone file
commandCustom slash commandsCopy markdown file
subAgentSub-agent configurationsCopy configuration file

Sources: src/hosts/types.ts

Write Strategies

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

Strategy Types

StrategyDescriptionSupported Asset Types
inject-json-keyInject configuration into existing JSON/TOML fileMCP, Prompt (append mode)
append-with-markerAppend content wrapped in HTML comment markersPrompt
copy-fileCopy file directly to target directorySkill, Command, Sub-agent
create-file-in-dirCreate file at installDir/<name>.mdPrompt (standalone mode)

Marker Block Format

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

<!-- 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:

// 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.

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

// 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 IDDisplay NameConfig Format
cursorCursor AIJSON
claude-codeClaude CodeJSON
claude-desktopClaude DesktopJSON
windsurfWindsurfTOML
github-copilotGitHub CopilotJSON
geminiGoogle GeminiJSON
roo-codeRoo CodeJSON
kilo-codeKilo CodeJSON
qwen-codeQwen CodeJSON
opencodeOpenCodeJSON
augmentAugment CodeJSON
kiroKiroJSON
tabnineTabnineJSON
kimiKimiJSON
traeTraeJSON
openclawOpenClawJSON
codexCodex CLITOML
vibeVibeTOML

Example Host Adapters

Claude Code Adapter

// 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',
    },
  };
}

Sources: src/hosts/claude-code.ts

Cursor Adapter

// 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',
    },
  };
}

Sources: src/hosts/cursor.ts

Unsupported Assets

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

// 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

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:

// 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:

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:

HostMCPPromptSkillCommandSub-agent
New Host.newhost/mcp.json

Step 4: Add Unit Tests

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

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:

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:

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:

// 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:

// 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

Sources: src/hosts/types.ts

Source Resolution

Related topics: System Architecture, Asset Types

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Local Files and Directories

Continue reading this section for the full explanation and source context.

Section Git URLs

Continue reading this section for the full explanation and source context.

Section HTTP/HTTPS URLs

Continue reading this section for the full explanation and source context.

Related topics: System Architecture, Asset Types

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.

Sources: src/source/index.ts

Architecture

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

ModulePurpose
index.tsMain entry point; orchestrates resolution pipeline
git.tsResolves Git URLs (SSH and HTTPS) with sparse checkout support
http-file.tsDownloads assets from HTTP/HTTPS URLs
local.tsResolves local filesystem paths
inline.tsHandles inline JSON and Markdown content
infer-name.tsExtracts asset names from source strings

Sources: src/source/index.ts

Resolution Pipeline

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

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:

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
}

Sources: 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
// 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

Sources: src/source/local.ts

Git URLs

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

FormatExampleBehavior
SSH[email protected]:user/repo.git#path/to/assetClones via SSH, extracts specified path
HTTPShttps://github.com/user/repo.git#path/to/assetClones via HTTPS, extracts specified path
Without fragment[email protected]:user/repo.gitClones 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.

// Example: Extract only the playwright skill from a monorepo
[email protected]:anthropics/skills.git#skills/playwright

The resolver supports both formats:

  • Directory path: Extracts all files within the directory
  • File path: Extracts a single file

Sources: 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 TypeHTTP Support
MCP✅ Yes
Skill❌ No (validation rejects)
Prompt✅ Yes
Command✅ Yes
Sub-agent✅ Yes

Sources: 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)

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

Asset name is inferred from the MCP config filename.

Format B: Wrapped config with mcpServers

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

The wrapper is automatically unwrapped and the inner server name becomes the asset name.

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

Sources: 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:

# Code Review Rules

Always review for security first.

→ Asset name: code-review-rules

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

Sources: src/source/inline.ts Sources: 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 TypeRuleExample InputInferred Name
Inline JSONExtract top-level key{"playwright":{...}}playwright
Inline MarkdownFirst # Heading → kebab-case# Code Reviewcode-review
Git URL + #pathLast segment, strip extension...git#skills/pdfpdf
Git URL without #Repository name, strip .git...playwright.gitplaywright
Local path / HTTPFilename, strip extension./mcps/playwright.jsonplaywright

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)
// 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"

Sources: 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:

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

Sources: src/source/index.ts

Integration with Installation Pipeline

Source Resolution integrates into the broader installation workflow as follows:

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
// 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');
  // ...
}

Sources: src/installer.ts

Error Handling

The resolution system provides specific error messages for common failures:

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

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

Sources: src/source/infer-name.ts Sources: src/installer.ts

Sources: src/source/index.ts

Asset Types

Related topics: Manifest System, Host Integration

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Supported JSON Formats

Continue reading this section for the full explanation and source context.

Section Installation Behavior

Continue reading this section for the full explanation and source context.

Section Structure Requirements

Continue reading this section for the full explanation and source context.

Related topics: Manifest System, Host Integration

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.

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 TypeIdentifierSource FormatValidation Requirement
MCP ServermcpJSON file.json extension required
SkillskillDirectoryMust contain SKILL.md
PromptpromptMarkdown fileFirst # Heading required
CommandcommandMarkdown with YAML frontmatterOptional description field
Sub-agentsubAgentMarkdown with YAML frontmatterOptional host specialization

Sources: 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)

{
  "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

{
  "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.

Sources: README.md - Asset Developer Guide

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
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:

Sources: src/manifest/schema.ts and src/manifest/parser.ts:30-35

Manifest System

Related topics: Asset Types, CLI Interface

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Schema Structure

Continue reading this section for the full explanation and source context.

Section Asset Definition

Continue reading this section for the full explanation and source context.

Section Example Manifest

Continue reading this section for the full explanation and source context.

Related topics: Asset Types, CLI Interface

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.

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:

FieldTypeRequiredDescription
namestringYesPack identifier in namespace/pack-name format. Only [a-zA-Z0-9_-] characters allowed
assetsAsset[]YesArray of asset definitions, minimum 1 item

Asset Definition

Each asset in the assets array has the following structure:

FieldTypeRequiredDescription
typestringYesAsset type: mcp, skill, prompt, command, or subAgent
sourcestringYesSource location (Git URL, local path, or HTTP URL)

Sources: README.md

Example Manifest

{
  "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" }
  ]
}

Sources: README.md

Source Syntax for Manifests

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

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 FormatName Extraction RuleExample
Git URL with #pathTake last segment after #, strip extension...git#skills/pdfpdf
Git URL without #Take repo name, strip .git suffix...playwright.gitplaywright
Local path / HTTP URLTake filename, strip extension./mcps/playwright.jsonplaywright

Sources: src/source/infer-name.ts

Inline Sources

Manifests support two inline source formats:

FormatDetectionName Source
inline-jsonStarts with {Single top-level JSON key
inline-mdContains \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:

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

Sources: src/manifest/parser.ts

Error Handling

The parser provides structured error messages for common validation failures:

Error ConditionMessage
Invalid asset typeUnsupported asset type: '<type>'. Supported: mcp, skill, prompt, command, subAgent
Invalid name formatManifest name must match namespace/pack-name format
Missing required fieldManifest missing required field: <field path>
JSON parse failureInvalid Manifest format

Sources: src/manifest/parser.ts

Integration with Installer

Processing Pipeline

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

Sources: 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

# 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

FlagDescriptionCollectable
--pack <source>Install an Agent Pack manifestYes (repeatable)

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

Development and Testing

Test Coverage

The manifest system is tested through:

Test TypeLocationPurpose
Unit teststests/unit/Parser validation, name inference
Contract teststests/contract/CLI black-box behavior
Feature teststests/features/End-to-end scenarios

Running Tests

# 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

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.

ComponentFileRole
Schemasrc/manifest/schema.tsZod schema definition for ManifestData
Parsersrc/manifest/parser.tsParsing and validation logic
Name Inferencesrc/source/infer-name.tsExtracts asset names from sources
Installersrc/installer.tsOrchestrates manifest processing
CLIsrc/cli.tsCommand-line argument handling

Key Design Decisions

DecisionRationale
Pack sources skip unsupported typesEnables cross-host manifest sharing without per-host variants
Explicit flags error on unsupported typesForces developers to handle host compatibility explicitly
Atomic JSON writes for MCPEnsures config file integrity during concurrent operations
Temp file + rename strategyProvides atomicity for manifest-based MCP installations
Zod for schema validationRuntime type checking with detailed error messages

Sources: README.md

CLI Interface

Related topics: Getting Started, Manifest System

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Binary Entry Point

Continue reading this section for the full explanation and source context.

Section Module Entry Point

Continue reading this section for the full explanation and source context.

Section Global Options

Continue reading this section for the full explanation and source context.

Related topics: Getting Started, Manifest System

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.

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]

Sources: src/index.ts:1-8

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.

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

Sources: bin/agent-add.js

Module Entry Point

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

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);
});

Sources: src/index.ts:1-8

Command Structure

Global Options

OptionTypeDescription
--host <host>stringTarget host ID (cursor, claude-code, claude-desktop, etc.)
-V, --versionbooleanShow version number
-h, --helpbooleanShow 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:

FlagTypeDescription
--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

Sources: src/cli.ts

Command Definition

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

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;
}

Sources: src/cli.ts

Input Collection

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

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

This enables usage patterns like:

agent-add --mcp server1.json --mcp server2.json --skill ./my-skill

Sources: src/cli.ts

Input Validation Flow

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:

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);
}

Sources: src/cli.ts

Host Selection

Explicit Host Specification

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

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:

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:

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);
}

Sources: src/cli.ts

CliInput Data Model

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

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:

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

Sources: src/cli.ts

Error Handling

Top-Level Error Handler

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

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:

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

CodeMeaningTrigger
0SuccessAll assets installed without errors or conflicts
1Partial failureInstall completed but had conflicts or errors
2Validation failureInvalid input, missing flags, or unsupported operations

Sources: src/index.ts:6 and src/cli.ts

Usage Examples

Install Single Asset

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

Install Multiple Assets

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

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

Interactive Mode

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

Sources: README.md

Package Configuration

The CLI binary is registered in package.json:

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

Sources: package.json

Sources: src/index.ts:1-8

Testing

Related topics: Project Configuration

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Unit Tests

Continue reading this section for the full explanation and source context.

Section Integration Tests

Continue reading this section for the full explanation and source context.

Section Contract Tests

Continue reading this section for the full explanation and source context.

Related topics: Project Configuration

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:

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 AspectValue
Test RunnerVitest 4.1.0
TypeScript TargetNode.js 18+
Test Locationtests/ directory
Run Commandnpm 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:

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.

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:

/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:

npm install
npm run build

Running Tests

CommandPurpose
npm testAll unit + integration tests
npm run test:contractCLI black-box contract tests only
npm run test:integrationIntegration tests
npx vitest run tests/unit/hosts/cursor.test.tsSingle unit test file

Vibe Development Assets

The project uses a custom testing manifest for development:

File: vibe/manifest.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:

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:

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:

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

Source: https://github.com/pea3nut/agent-add / Human Manual

Project Configuration

Related topics: Testing

Section Related Pages

Continue reading this section for the full explanation and source context.

Section tsup Build Configuration

Continue reading this section for the full explanation and source context.

Section Build Scripts

Continue reading this section for the full explanation and source context.

Section Engine Requirements

Continue reading this section for the full explanation and source context.

Related topics: Testing

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. Sources: package.json:17

Build System Configuration

tsup Build Configuration

The project uses tsup for TypeScript bundling, defined in tsup.config.ts:

import { defineConfig } from 'tsup';

export default defineConfig({
  entry: ['src/index.ts'],
  format: ['cjs'],
  target: 'node18',
  clean: true,
  sourcemap: true,
  dts: false,
  outDir: 'dist',
  noExternal: [/.*/],
});
OptionValuePurpose
entry['src/index.ts']Single entry point for CLI application
format['cjs']CommonJS output format for Node.js compatibility
targetnode18Transpile for Node.js 18 environment
cleantrueRemove previous build artifacts before each build
sourcemaptrueGenerate source maps for debugging
dtsfalseDisable TypeScript declaration generation
outDir'dist'Output directory for compiled files
noExternal[/.*/]Bundle all dependencies into output

Sources: tsup.config.ts:1-11

Build Scripts

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

{
  "scripts": {
    "build": "tsup",
    "dev": "tsx watch src/index.ts",
    "test": "vitest run",
    "install:vibe": "npx -y agent-add -- --pack vibe/manifest.json"
  }
}
ScriptCommandUsage
buildtsupCompile TypeScript to JavaScript
devtsx watch src/index.tsDevelopment mode with hot reload
testvitest runExecute unit and integration tests
install:vibeagent-add -- --pack vibe/manifest.jsonInstall development assets via pack manifest

Sources: package.json:27-31

Package Configuration

Engine Requirements

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

The project requires Node.js 18 or higher due to ES module features and modern JavaScript APIs used throughout the codebase. Sources: package.json:35-37

Core Dependencies

The project relies on several key runtime dependencies:

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

Development dependencies include TypeScript, vitest for testing, and tsx for development execution. Sources: 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:

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>;
}

Sources: src/hosts/types.ts

Host Capability Matrix

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

Host IDMCPPromptSkillCommandSub-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. Sources: src/hosts/README.md, src/hosts/index.ts

Write Strategy Configuration

Hosts configure one of two write strategies for prompt assets:

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:

<!-- 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. Sources: src/assets/prompt.ts

Asset Type Configuration

MCP Asset Configuration

MCP assets support two JSON formats:

Format A - Inner Config (Single Server):

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

Format B - Full Config with mcpServers Wrapper:

{
  "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. Sources: src/assets/mcp.ts

Skill Asset Configuration

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

<!-- SKILL.md -->

Sources: tsup.config.ts:1-11

Doramagic Pitfall Log

Source-linked risks stay visible on the manual page so the preview does not read like a recommendation.

medium v1.1.0

First-time setup may fail or require extra isolation and rollback planning.

medium I built a CLI that installs MCP, skills, prompts, commands and sub ...

First-time setup may fail or require extra isolation and rollback planning.

medium Configuration risk needs validation

Users may get misleading failures or incomplete behavior unless configuration is checked carefully.

medium README/documentation is current enough for a first validation pass.

The project should not be treated as fully validated until this signal is reviewed.

Doramagic Pitfall Log

Doramagic extracted 9 source-linked risk signals. Review them before installing or handing real data to the project.

1. Installation risk: v1.1.0

  • Severity: medium
  • Finding: Installation risk is backed by a source signal: v1.1.0. Treat it as a review item until the current version is checked.
  • User impact: First-time setup may fail or require extra isolation and rollback planning.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: Source-linked evidence: https://github.com/pea3nut/agent-add/releases/tag/1.1.0

2. Installation risk: I built a CLI that installs MCP, skills, prompts, commands and sub ...

  • Severity: medium
  • Finding: 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- ...
  • User impact: First-time setup may fail or require extra isolation and rollback planning.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: 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. Configuration risk: Configuration risk needs validation

  • Severity: medium
  • Finding: Configuration risk is backed by a source signal: Configuration risk needs validation. Treat it as a review item until the current version is checked.
  • User impact: Users may get misleading failures or incomplete behavior unless configuration is checked carefully.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: capability.host_targets | art_7871f43a97e049c0ba0df6fa5a5b6e88 | https://github.com/pea3nut/agent-add#readme | host_targets=mcp_host, claude, claude_code, cursor, chatgpt

4. Capability assumption: README/documentation is current enough for a first validation pass.

  • Severity: medium
  • Finding: README/documentation is current enough for a first validation pass.
  • User impact: The project should not be treated as fully validated until this signal is reviewed.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: capability.assumptions | art_7871f43a97e049c0ba0df6fa5a5b6e88 | https://github.com/pea3nut/agent-add#readme | README/documentation is current enough for a first validation pass.

5. Maintenance risk: Maintainer activity is unknown

  • Severity: medium
  • Finding: Maintenance risk is backed by a source signal: Maintainer activity is unknown. Treat it as a review item until the current version is checked.
  • User impact: Users cannot judge support quality until recent activity, releases, and issue response are checked.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: evidence.maintainer_signals | art_7871f43a97e049c0ba0df6fa5a5b6e88 | https://github.com/pea3nut/agent-add#readme | last_activity_observed missing

6. Security or permission risk: no_demo

  • Severity: medium
  • Finding: no_demo
  • User impact: The project may affect permissions, credentials, data exposure, or host boundaries.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: downstream_validation.risk_items | art_7871f43a97e049c0ba0df6fa5a5b6e88 | https://github.com/pea3nut/agent-add#readme | no_demo; severity=medium

7. Security or permission risk: no_demo

  • Severity: medium
  • Finding: no_demo
  • User impact: The project may affect permissions, credentials, data exposure, or host boundaries.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: risks.scoring_risks | art_7871f43a97e049c0ba0df6fa5a5b6e88 | https://github.com/pea3nut/agent-add#readme | no_demo; severity=medium

8. Maintenance risk: issue_or_pr_quality=unknown

  • Severity: low
  • Finding: issue_or_pr_quality=unknown。
  • User impact: Users cannot judge support quality until recent activity, releases, and issue response are checked.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: evidence.maintainer_signals | art_7871f43a97e049c0ba0df6fa5a5b6e88 | https://github.com/pea3nut/agent-add#readme | issue_or_pr_quality=unknown

9. Maintenance risk: release_recency=unknown

  • Severity: low
  • Finding: release_recency=unknown。
  • User impact: Users cannot judge support quality until recent activity, releases, and issue response are checked.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: evidence.maintainer_signals | art_7871f43a97e049c0ba0df6fa5a5b6e88 | https://github.com/pea3nut/agent-add#readme | release_recency=unknown

Source: Doramagic discovery, validation, and Project Pack records

Community Discussion Evidence

These external discussion links are review inputs, not standalone proof that the project is production-ready.

Sources 3

Count of project-level external discussion links exposed on this manual page.

Use Review before install

Open the linked issues or discussions before treating the pack as ready for your environment.

Community Discussion Evidence

Doramagic exposes project-level community discussion separately from official documentation. Review these links before using agent-add with real data or production workflows.

Source: Project Pack community evidence and pitfall evidence