Experimental — This framework is under active development and not yet fit for production usage. APIs, schemas, and conventions may change without notice. We welcome early feedback and contributions.
Coding agents are most useful when they're loaded with the right skills, MCP servers, and references for the task at hand — not the union of every tool you've ever installed. AIR is an open-source, git-native catalog framework for assembling that focused configuration once per session, on top of open standards. Designed for engineering teams, extensible to any knowledge work.
Today, every Claude Code session ships the kitchen sink: every MCP server you've configured globally, every skill in your ~/.claude/skills directory. Auth prompts pile up. Useful skills are buried in noise. With AIR, you compose a small, scoped slice — exactly the artifacts this session needs.
| Without AIR All MCP servers loaded, every skill in scope — 5 servers needing auth, your entire skill catalog visible at once |
With AIRair start claude composes a focused subset — 2 servers, only the skills this session needs |
without-air.mp4 |
with-air.mp4 |
| ~30s demos — press play on either side. | |
A catalog is a directory (or git repo) that ships AIR artifacts — skills, MCP servers, references, plugins, hooks, roots — each defined as a JSON index validated against an open schema. Anyone can publish one. Your team maintains its own. Org catalogs, team catalogs, personal catalogs — they're all the same shape.
The shape comes through clearest in the examples/ directory of this repo:
examples/
├── air.json # Composition file: which catalogs are layered, what's excluded
├── skills/skills.json # Skill index — each entry points at a SKILL.md with reusable instructions
├── mcp/mcp.json # MCP server configs (GitHub, Postgres, Analytics)
├── references/references.json # Shared knowledge docs that skills depend on
├── plugins/plugins.json # Bundles of skills + servers + hooks
├── roots/roots.json # Per-project agent workspaces with their own defaults
└── hooks/hooks.json # Lifecycle hooks (pre-commit, session-start, etc.)
Browse examples/air.json for the composition file, examples/skills/skills.json for a skill index, and examples/mcp/mcp.json for a real MCP server set — each artifact validated by a JSON Schema in schemas/.
You install AIR once and write one composition file at ~/.air/air.json. After that, every agent session is one command.
$ air start claude
# Claude Code boots with exactly the artifacts composed above — nothing more, nothing less.- Layer multiple catalogs. Org → team → personal. Composition is additive, not later-wins.
- Scoped identity. Every artifact is
@scope/id, so duplicates hard-fail andexcludeis the only knob to drop something. - Pluggable agents. Claude Code, the OpenAI Codex CLI, the Cursor CLI, and the Pi coding agent today, more agents soon — adapter packages translate AIR config into agent-specific formats.
- No proprietary backend. Catalogs live in git repos. AIR fetches them on demand and composes them at session start.
Quickstart → · air.json reference → · Writing a catalog →
As teams adopt agents, they accumulate configuration: MCP server definitions, reusable skills, coding conventions, environment setups. Without structure, this configuration drifts, duplicates, and becomes impossible to share.
AIR solves this by:
- Orienting around open standards — Agent Skills, MCP, Plugins, and more to come. The agentic ecosystem will constantly evolve, but agreed-upon standards and interfaces will be the deterministic mainstays that the ecosystem builds on top of. Everything else is just custom glue.
- Keeping everything in git — All configuration is version-controlled, reviewable, and composable. No proprietary backends.
- Being maximally DRY — No copy/pasting, drift, or unclear ownership. If someone in your org does the work once and catalogs it properly, nobody ever has to touch it again.
- Single-session configs — Not per-user or per-project (those don't scale). Each session assembles exactly what it needs from composable layers.
- Working with any coding agent — AIR is a common layer across the ecosystem of opinionated agent implementations. Start with one agent, switch later to the newest frontier implementation without undoing your organization's work.
AIR endorses and builds on these standards and patterns. Their maturity reflects how broadly adopted and stable they are across the ecosystem:
| Standard | Adoption | How We Think About It |
|---|---|---|
| Agent Skills | High | Reusable, invocable units of work defined as structured Markdown (SKILL.md) and associated files. Skills represent internal (often proprietary) knowledge or processes where foundation models cannot be trained or have been proven to underperform. |
| MCP | High | Open protocol for connecting AI agents to wholly or partially deterministic tools and data sources. Handles auth and access boundaries. |
| References | Medium | Shared knowledge documents attached to skills. Broken out separately to stay DRY — one reference can serve many skills. |
| Plugins | Medium | Named groupings of AIR primitives (skills, MCP servers, hooks) for bundling and distribution. Plugins reference existing artifacts by ID — a compositional layer, not a separate artifact format. Users can always "eject" and work at the primitive level. Modeled after the Open Plugins spec and Claude Code Plugins with translation layers for other agents. |
| Hooks | Medium | Shell commands triggered at agent lifecycle events (session start, pre-commit, etc.). |
| Roots | Medium | Self-contained agent workspaces — a git repo (or subdirectory) with a file hierarchy (including AGENTS.md files) an agent needs for a specific project. |
| Rules | Emerging | Persistent AI guidance files (.mdc) that remain in context throughout a session. Optionally scoped by file glob patterns. Distinct from skills (on-demand activation) and CLAUDE.md/AGENTS.md (per-root). Originated by Cursor, adopted by the Open Plugins spec. Not yet supported in AIR — planned for a future release. |
Note: CLI tools are themselves not a standard. While you can shoehorn them inside a Skill or MCP server in a pinch, they provide no scalable path to managing auth and access boundaries and no ecosystem investment in future enrichments.
AIR generates agent-specific configuration at session start time via adapter extensions. Install the adapter for your agent:
| Agent | Adapter Package | Status |
|---|---|---|
| Claude Code | @pulsemcp/air-adapter-claude |
Officially maintained |
| OpenAI Codex CLI | @pulsemcp/air-adapter-codex |
Officially maintained |
| Cursor CLI | @pulsemcp/air-adapter-cursor |
Officially maintained |
| Pi | @pulsemcp/air-adapter-pi |
Officially maintained (skills-only) |
| OpenCode | @pulsemcp/air-adapter-opencode |
Community / planned |
To add support for a new agent, publish an adapter package implementing the AgentAdapter interface from @pulsemcp/air-core.
AIR organizes agent configuration into artifact types, each with its own index file and JSON schema:
~/.air/ # User-level AIR configuration
├── air.json # Root config — points to all artifact indexes
├── skills/
│ ├── skills.json # Skills index
│ ├── deploy-staging/
│ │ └── SKILL.md
│ └── pr-review/
│ └── SKILL.md
├── references/
│ ├── references.json # Shared reference documents index
│ ├── GIT_WORKFLOW.md
│ └── CODE_STANDARDS.md
├── mcp/
│ └── mcp.json # MCP server configurations
├── plugins/
│ └── plugins.json # Agent plugins index
├── roots/
│ └── roots.json # Agent root workspaces index
└── hooks/
└── hooks.json # Lifecycle hooks index
Your own air.json at ~/.air/air.json is where you assemble whichever artifacts you want — purely local directories you maintain yourself, catalogs your team ships, remote org-wide defaults, or any combination. Orgs and teams can publish ready-made index files as building blocks; nothing is compulsory.
Every AIR configuration starts with an air.json file. Each artifact property is an array of paths to index files. Paths can be local (relative to air.json) or remote URIs like github:// when a catalog provider is installed. Every artifact is identified by @scope/id — local entries contribute under @local/ and remote catalogs use a provider-derived scope (@<owner>/<repo>/). Composition is additive; duplicate qualified IDs hard-fail, and the only way to drop an artifact is exclude:
{
"name": "acme-engineering",
"description": "Acme Corp engineering team agent configs",
"skills": [
"github://acme/air-org/skills/skills.json",
"./skills/skills.json"
],
"mcp": [
"github://acme/air-org/mcp/mcp.json",
"./mcp/mcp.json"
]
}~/.air/air.json is the single composition surface — everything active in a session comes from the arrays you list here. Each artifact field accepts any number of local or remote index paths, and you mix and match to fit your situation. A few shapes:
Local-only. A solo developer or a small team using only their own artifacts:
{
"name": "just-me",
"skills": ["./skills/skills.json"],
"mcp": ["./mcp/mcp.json"]
}Local catalog + shared remote catalog. Your private team skills live in a directory you maintain (e.g., a sibling repo checked into ~/.air/ or an absolute path elsewhere on disk), layered with an org-wide catalog for shared defaults. AIR walks each catalog up to 3 levels deep and discovers artifact indexes by filename or $schema, so catalogs lets you reference each source with a single entry regardless of its internal folder layout:
{
"name": "platform-team",
"catalogs": [
"github://acme/air-org",
"./platform-team-catalog"
]
}AIR expands each catalog into all six artifact arrays automatically — missing files within a catalog are silently skipped. If you need finer-grained control (e.g., pull only skills from a remote source), use the per-type arrays instead:
{
"name": "platform-team",
"skills": [
"github://acme/air-org/skills/skills.json",
"./platform-team-catalog/skills/skills.json"
],
"mcp": [
"github://acme/air-org/mcp/mcp.json",
"./platform-team-catalog/mcp/mcp.json"
]
}catalogs and the per-type arrays compose: catalogs expand first, per-type arrays layer on top. Local paths resolve relative to air.json, so ./platform-team-catalog above points at ~/.air/platform-team-catalog.
Stacked remotes plus local additions. Layer org and team catalogs with project-specific additions:
{
"name": "frontend-team",
"catalogs": [
"github://acme/air-org",
"github://acme/air-frontend"
],
"mcp": ["./mcp/mcp.json"],
"exclude": {
"mcp": ["@acme/air-org/legacy-server"]
}
}Each catalog contributes artifacts under its own scope (@acme/air-org/..., @acme/air-frontend/..., @local/...). Composition is additive — duplicate qualified IDs hard-fail, and exclude is the only way to drop an artifact. No separate config file is needed — air.json is the single composition point.
Skills are reusable, invocable units of work defined as structured Markdown (SKILL.md) and associated files. They represent internal (often proprietary) knowledge or processes where foundation models cannot be trained or have been proven to underperform.
References are shared knowledge documents that skills depend on. By breaking references out of skills into their own index, you keep things DRY — one reference about your git workflow can be used by your deploy skill, your PR review skill, and your release skill.
// skills.json
{
"deploy-staging": {
"id": "deploy-staging",
"description": "Deploy the current PR branch to staging",
"path": "skills/deploy-staging",
"references": ["git-workflow", "staging-env"]
}
}
// references.json
{
"git-workflow": {
"id": "git-workflow",
"description": "Git branching, naming, and PR conventions",
"file": "references/GIT_WORKFLOW.md"
}
}MCP is the open protocol for connecting AI agents to wholly or partially deterministic tools and data sources. It handles auth and access boundaries. AIR uses the mcp.json format for MCP server configuration — a flat map of server names to fully-resolved connection configs:
{
"github": {
"title": "GitHub",
"type": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github@0.6.2"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_PERSONAL_ACCESS_TOKEN}"
}
}
}Three transport types are supported: stdio (local processes), sse (Server-Sent Events), and streamable-http (HTTP streaming).
Plugins are named groupings of AIR primitives (skills, MCP servers, hooks) — a compositional unit for bundling and distributing related capabilities. They provide a more tractable layer of abstraction for distribution and sharing; users who want finer-grained control can always "eject" and work directly at the more primitive skills/mcp/hooks layer. Both approaches are fully supported.
A plugin entry in plugins.json declares which AIR artifacts it bundles by referencing their IDs. This enables the CLI to deduplicate — if you request both a skill and a plugin that already bundles that skill, only the plugin needs to be activated:
{
"code-quality": {
"id": "code-quality",
"title": "Code Quality Suite",
"description": "Linting, formatting, and static analysis tools bundled with coding standards skills",
"version": "1.2.0",
"skills": ["lint-fix", "format-check"],
"mcp_servers": ["eslint-server"],
"hooks": ["lint-pre-commit"],
"author": { "name": "Acme Engineering" },
"license": "MIT",
"keywords": ["linting", "formatting", "eslint", "prettier"]
}
}Roots are self-contained agent workspaces — a git repo (or subdirectory) with a file hierarchy (including AGENTS.md files) an agent needs for a specific project. Each root declares its default MCP servers, skills, plugins, hooks, and the agent runtime it runs on:
{
"web-app": {
"name": "web-app",
"display_name": "Web Application",
"description": "Main web app — Rails backend, React frontend",
"url": "https://github.com/acme/web-app.git",
"default_mcp_servers": ["github", "postgres-prod"],
"default_skills": ["deploy-staging", "pr-review"],
"default_runtime": "claude_code",
"user_invocable": true
}
}default_runtime is optional and selects the agent runtime for sessions and subagents spawned under the root (default: claude_code). It is an open string field — common values are claude_code, codex, pi, opencode, amp, gemini, and github_copilot, but any identifier a downstream consumer recognizes is accepted, so new agents don't require a schema change. See the roots guide for the full field reference.
Hooks are shell commands that fire at agent lifecycle events. Use them for notifications, guardrails, or automation:
{
"lint-pre-commit": {
"id": "lint-pre-commit",
"description": "Run linting before commits",
"event": "pre_commit",
"command": "npx",
"args": ["lint-staged"]
}
}A hook entry can also point its path at a remote directory (e.g. "path": "github://acme/air-org@v1.2.0/hooks/notify-session-start") and carry an x-config overlay that AIR deep-merges into the materialized HOOK.json's x-config at resolve time — so consumers can override defaults without forking the hook. See the hooks guide for details.
AIR is a single-session configuration layer — it resolves, validates, and translates agent configs for one session at a time. It is not an orchestration platform.
| AIR handles | Orchestration platforms handle |
|---|---|
| Config resolution & composition | Session persistence & status tracking |
| JSON Schema validation | Subagent invocation & coordination |
| Agent-specific translation | Job queuing, retries, scheduling |
Single-session setup (air start / air prepare) |
Secret management & credential vaults |
${ENV_VAR} interpolation in configs |
Git clone lifecycle & working directories |
| Monitoring, cost tracking, dashboards | |
| Running multiple sessions in parallel |
Each air start or air prepare call sets up exactly one agent session in one working directory. If you need to run multiple sessions concurrently, you need separate working directories and a way to manage them — see Running Sessions for practical tips, or Orchestration for building a full orchestration layer on top of AIR.
npm install -g @pulsemcp/air-cliair initThis creates ~/.air/air.json and artifact subdirectories with empty index files.
air validate ~/.air/air.json
air validate ~/.air/mcp/mcp.json
air validate ~/.air/skills/skills.json# Start Claude Code with your AIR configuration
air start claude
# Start with a specific root
air start claude --root web-app
# Dry run — see what would be activated
air start claude --root web-app --dry-runSee docs/cli.md for the full CLI reference. Key commands:
| Command | Description |
|---|---|
air init |
Initialize a new AIR configuration at ~/.air/ |
air validate <file> |
Validate a JSON file against its AIR schema |
air start <agent> |
Start an agent session with AIR configs loaded |
air list <type> |
List available artifacts (skills, mcp, plugins, roots, hooks) |
| Document | Description |
|---|---|
| Core Concepts | Architecture, design principles, and composition model |
| Design Document | Canonical user scenarios and design decisions (core + CLI) |
| Skills | How to write and manage skills |
| References | Shared knowledge documents |
| MCP Servers | MCP server configuration |
| mcp.json Proposal | Proposed client-side MCP configuration format |
| Plugins | Agent plugins and translation layers |
| Roots | Agent root workspaces |
| Hooks | Lifecycle hooks |
| CLI | Full CLI reference |
| Configuration | Configuration loading, composition, and layering |
| Orchestration | Scope boundaries, multi-agent patterns, and building on top of AIR |
All AIR JSON files can be validated against their schemas:
# Using the AIR CLI
air validate ~/.air/air.json
air validate ~/.air/mcp/mcp.json
# Using ajv-cli directly
npx ajv-cli validate -s schemas/air.schema.json -d ~/.air/air.json --spec=draft7 --strict=falseSchemas are in the schemas/ directory. Point your editor's JSON schema support at them for autocomplete and inline validation.
- Open standards are the building blocks. Ecosystems build deterministic layers around open standards. Orient around them.
- Bias towards git and files. All data lives in git repos. Use open-source tooling or roll your own.
- Maximally DRY. Don't duplicate anything that semantically represents the same thing. Compose, don't copy.
- Single-session configs. Per-user and per-project configs don't scale — they drift. Each
air startassembles what one session needs from reusable layers. - Carefully collaborate. Treat shared configs like software other people use. Make scope crystal clear. If it's org-level, anyone in the org should understand the description.
- Build for everyone. AI agents aren't just for engineers — engineers are the early adopters. Don't build infrastructure only engineers can use.
- Fork and make it your own. Teams are encouraged to fork this framework and adapt it. The patterns matter more than the specific implementation.
AIR is structured as a monorepo with a thin core and pluggable extensions:
air/
├── schemas/ # JSON Schema files for all artifact types
├── examples/ # Example configurations
├── docs/ # Documentation
├── packages/
│ ├── core/ # @pulsemcp/air-core
│ │ └── Config resolution, validation, schemas, extension interfaces
│ ├── cli/ # @pulsemcp/air-cli
│ │ └── CLI commands (validate, list, init, start)
│ └── extensions/
│ ├── adapter-claude/ # @pulsemcp/air-adapter-claude
│ │ └── Translates AIR config → Claude Code format
│ ├── adapter-codex/ # @pulsemcp/air-adapter-codex
│ │ └── Translates AIR config → OpenAI Codex CLI format
│ ├── adapter-cursor/ # @pulsemcp/air-adapter-cursor
│ │ └── Translates AIR config → Cursor CLI format
│ ├── adapter-pi/ # @pulsemcp/air-adapter-pi
│ │ └── Injects AIR skills → Pi coding agent (.pi/skills/, skills-only)
│ └── provider-github/ # @pulsemcp/air-provider-github
│ └── Resolves github:// URIs in air.json
The core defines four extension interfaces:
| Extension Point | Interface | Built-in | Official Extensions |
|---|---|---|---|
| Catalog Providers | CatalogProvider |
Local filesystem | @pulsemcp/air-provider-github |
| Agent Adapters | AgentAdapter |
None | @pulsemcp/air-adapter-claude, @pulsemcp/air-adapter-codex, @pulsemcp/air-adapter-cursor, @pulsemcp/air-adapter-pi |
| Transforms | PrepareTransform |
None | @pulsemcp/air-secrets-env, @pulsemcp/air-secrets-file |
| Transports | Consume SDK | CLI | None yet |
Community extensions follow the @pulsemcp/air-adapter-* and @pulsemcp/air-provider-* naming convention.
| Package | Description |
|---|---|
@pulsemcp/air-core |
Config resolution, validation, schemas, and extension interfaces. No agent-specific code. |
@pulsemcp/air-cli |
CLI wrapper. Discovers installed adapters for air start. |
@pulsemcp/air-adapter-claude |
Claude Code adapter. Translates MCP servers, plugins, skills to Claude format. |
@pulsemcp/air-adapter-codex |
OpenAI Codex CLI adapter. Translates MCP servers, skills, and hooks to Codex's config.toml / .agents/skills/ format. |
@pulsemcp/air-adapter-cursor |
Cursor CLI adapter. Translates MCP servers, skills, and hooks to Cursor's .cursor/mcp.json / .cursor/hooks.json / .cursor/skills/ format. |
@pulsemcp/air-adapter-pi |
Pi coding agent adapter (skills-only). Injects skills into .pi/skills/; does not translate MCP servers, hooks, or standalone references. |
@pulsemcp/air-provider-github |
GitHub catalog provider. Fetches remote artifact indexes via the GitHub REST API. |
This project is in its early experimental phase. We welcome issues, discussions, and pull requests. Please read the documentation thoroughly before contributing.
# Install all dependencies
npm install
# Build core (required before other packages can type-check)
npm run build -w packages/core
# Run all tests
npx vitest run
# Type-check a specific package
npx tsc --noEmit -p packages/core/tsconfig.jsonMIT