Expand description
Manifest file parsing and validation for AGPM projects.
This module handles the agpm.toml manifest file that defines project
dependencies and configuration. The manifest uses TOML format and follows
a structure similar to Cargo.toml, providing a lockfile-based dependency
management system for Claude Code resources.
§Overview
The manifest system enables:
- Declarative dependency management through
agpm.toml - Reproducible installations via lockfile generation
- Support for multiple Git-based source repositories
- Local and remote dependency resolution
- Version constraint specification and validation
- Transitive dependency resolution from resource metadata
- Cross-platform path handling and installation
- MCP (Model Context Protocol) server configuration management
- Atomic file operations for reliability
§Complete TOML Format Specification
§Basic Structure
A agpm.toml manifest file consists of four main sections:
# Named source repositories (optional)
[sources]
# Git repository URLs mapped to convenient names
official = "https://github.com/example-org/agpm-official.git"
community = "https://github.com/community/agpm-resources.git"
private = "git@github.com:company/private-resources.git"
# Installation target directories (optional)
[target]
# Where agents should be installed (default: ".claude/agents")
agents = ".claude/agents"
# Where snippets should be installed (default: ".agpm/snippets")
snippets = ".agpm/snippets"
# Where commands should be installed (default: ".claude/commands")
commands = ".claude/commands"
# Agent dependencies (optional)
[agents]
# Various dependency specification formats
simple-agent = "../local/agents/helper.md" # Local path
remote-agent = { source = "official", path = "agents/reviewer.md", version = "v1.0.0" }
latest-agent = { source = "community", path = "agents/utils.md", version = "latest" }
branch-agent = { source = "private", path = "agents/internal.md", git = "develop" }
commit-agent = { source = "official", path = "agents/stable.md", git = "abc123..." }
# Custom target installation directory (relative to .claude)
custom-agent = { source = "official", path = "agents/special.md", version = "v1.0.0", target = "integrations/ai" }
# Snippet dependencies (optional)
[snippets]
# Same formats as agents
local-snippet = "../shared/snippets/common.md"
remote-snippet = { source = "community", path = "snippets/utils.md", version = "v2.1.0" }
# Custom target for special snippets
integration-snippet = { source = "community", path = "snippets/api.md", version = "v1.0.0", target = "tools/snippets" }
# Command dependencies (optional)
[commands]
# Same formats as agents and snippets
local-command = "../shared/commands/helper.md"
remote-command = { source = "community", path = "commands/build.md", version = "v1.0.0" }§Sources Section
The [sources] section maps convenient names to Git repository URLs:
[sources]
# HTTPS URLs (recommended for public repositories)
official = "https://github.com/owner/agpm-resources.git"
community = "https://gitlab.com/group/agpm-community.git"
# SSH URLs (for private repositories with key authentication)
private = "git@github.com:company/private-resources.git"
internal = "git@gitlab.company.com:team/internal-resources.git"
# Local Git repository URLs
local-repo = "file:///absolute/path/to/local/repo"
# Environment variable expansion (useful for CI/CD)
dynamic = "https://github.com/${GITHUB_ORG}/resources.git"
home-repo = "file://${HOME}/git/resources"§Target Section
The [target] section configures where resources are installed:
[target]
# Default values shown - these can be customized
agents = ".claude/agents" # Where agent .md files are copied
snippets = ".agpm/snippets" # Where snippet .md files are copied
commands = ".claude/commands" # Where command .md files are copied
# Alternative configurations
agents = "resources/agents"
snippets = "resources/snippets"
commands = "resources/commands"
# Absolute paths are supported
agents = "/opt/claude/agents"
snippets = "/opt/claude/snippets"
commands = "/opt/claude/commands"§Dependency Sections
Both [agents] and [snippets] sections support multiple dependency formats:
§1. Local Path Dependencies
For resources in your local filesystem:
[agents]
# Relative paths from manifest directory
local-helper = "../shared/agents/helper.md"
nearby-agent = "./local-agents/custom.md"
# Absolute paths (not recommended for portability)
system-agent = "/usr/local/share/claude/agents/system.md"Local dependencies:
- Do not support version constraints
- Are copied directly from the filesystem
- Are not cached or managed through Git
- Must exist at install time
§2. Remote Source Dependencies
For resources from Git repositories:
[agents]
# Basic remote dependency with semantic version
code-reviewer = { source = "official", path = "agents/reviewer.md", version = "v1.0.0" }
# Using latest version (not recommended for production)
utils = { source = "community", path = "agents/utils.md", version = "latest" }
# Specific Git branch
bleeding-edge = { source = "official", path = "agents/experimental.md", git = "develop" }
# Specific Git commit (maximum reproducibility)
stable = { source = "official", path = "agents/stable.md", git = "a1b2c3d4e5f6..." }
# Git tag (alternative to version field)
tagged = { source = "community", path = "agents/tagged.md", git = "release-2.0" }§3. Custom Target Installation
Dependencies can specify a custom installation directory using the target field:
[agents]
# Install to .claude/integrations/ai/ instead of .claude/agents/
integration-agent = {
source = "official",
path = "agents/integration.md",
version = "v1.0.0",
target = "integrations/ai"
}
# Organize tools in a custom structure
debug-tool = {
source = "community",
path = "agents/debugger.md",
version = "v2.0.0",
target = "development/tools"
}
[snippets]
# Custom location for API snippets
api-helper = {
source = "community",
path = "snippets/api.md",
version = "v1.0.0",
target = "api/snippets"
}Custom targets:
- Are always relative to the
.claudedirectory - Leading
.claude/or/are automatically stripped - Directories are created if they don’t exist
- Help organize resources in complex projects
§4. Custom Filenames
Dependencies can specify a custom filename using the filename field:
[agents]
# Install as "ai-assistant.md" instead of "my-ai.md"
my-ai = {
source = "official",
path = "agents/complex-long-name-v2.md",
version = "v1.0.0",
filename = "ai-assistant.md"
}
# Change both filename and extension
doc-helper = {
source = "community",
path = "agents/documentation.md",
version = "v2.0.0",
filename = "docs.txt"
}
# Combine custom target and filename
special-tool = {
source = "official",
path = "agents/debug-analyzer-enhanced.md",
version = "v1.0.0",
target = "tools/debugging",
filename = "analyzer.markdown"
}
[scripts]
# Rename script during installation
data-processor = {
source = "community",
path = "scripts/data-processor-v3.py",
version = "v1.0.0",
filename = "process.py"
}Custom filenames:
- Include the full filename with extension
- Override the default name (based on dependency key)
- Work with any resource type
- Can be combined with custom targets
§Version Constraint Syntax
AGPM supports flexible version constraints:
"v1.0.0"- Exact semantic version"1.0.0"- Exact version (v prefix optional)"latest"- Always use the latest available version"main"- Use the main/master branch HEAD"develop"- Use a specific branch"a1b2c3d4..."- Use a specific commit SHA"release-1.0"- Use a specific Git tag
§Complete Examples
§Minimal Manifest
[agents]
helper = "../agents/helper.md"§Production Manifest
[sources]
official = "https://github.com/claude-org/official-resources.git"
community = "https://github.com/claude-community/resources.git"
company = "git@github.com:mycompany/claude-resources.git"
[target]
agents = "resources/agents"
snippets = "resources/snippets"
[agents]
# Production agents with pinned versions
code-reviewer = { source = "official", path = "agents/code-reviewer.md", version = "v2.1.0" }
documentation = { source = "community", path = "agents/doc-writer.md", version = "v1.5.2" }
internal-helper = { source = "company", path = "agents/helper.md", version = "v1.0.0" }
# Local customizations
custom-agent = "./local/agents/custom.md"
[snippets]
# Utility snippets
common-patterns = { source = "community", path = "snippets/patterns.md", version = "v1.2.0" }
company-templates = { source = "company", path = "snippets/templates.md", version = "latest" }§Security Considerations
CRITICAL: Never include authentication credentials in agpm.toml:
# ❌ NEVER DO THIS - credentials will be committed to git
[sources]
private = "https://token:ghp_xxxx@github.com/company/repo.git"
# ✅ Instead, use global configuration in ~/.agpm/config.toml
# Or use SSH keys with git@ URLs
[sources]
private = "git@github.com:company/repo.git"Authentication should be configured globally in ~/.agpm/config.toml or
through SSH keys for git@ URLs. See crate::config for details.
§Relationship to Lockfile
The manifest works together with the lockfile (agpm.lock):
- Manifest (
agpm.toml): Declares dependencies and constraints - Lockfile (
agpm.lock): Records exact resolved versions and checksums
When you run agpm install:
- Reads dependencies from
agpm.toml - Resolves versions within constraints
- Generates/updates
agpm.lockwith exact commits - Installs resources to target directories
See crate::lockfile for lockfile format details.
§Cross-Platform Compatibility
AGPM handles platform differences automatically:
- Path separators (/ vs \) are normalized
- Home directory expansion (~) is supported
- Environment variable expansion is available
- Git commands work on Windows, macOS, and Linux
- Long path support on Windows (>260 characters)
- Unicode filenames and paths are fully supported
§Best Practices
- Use semantic versions: Prefer
v1.0.0overlatest - Pin production dependencies: Use exact versions in production
- Organize sources logically: Group by organization or purpose
- Document dependencies: Add comments explaining why each is needed
- Keep manifests simple: Avoid overly complex dependency trees
- Use SSH for private repos: More secure than HTTPS tokens
- Test across platforms: Verify paths work on all target systems
- Version control manifests: Always commit
agpm.tomlto git - Validate regularly: Run
agpm validatebefore commits - Use lockfiles: Commit
agpm.lockfor reproducible builds
§Transitive Dependencies
Resources can declare their own dependencies within their files using structured metadata. This enables automatic dependency resolution without manual manifest updates.
§Supported Formats
§Markdown Files (YAML Frontmatter)
---
dependencies:
agents:
- path: agents/helper.md
version: v1.0.0
- path: agents/reviewer.md
snippets:
- path: snippets/utils.md
---
# My Command Documentation
...§JSON Files (Top-Level Field)
{
"events": ["UserPromptSubmit"],
"type": "command",
"command": ".claude/scripts/test.js",
"dependencies": {
"scripts": [
{ "path": "scripts/test-runner.sh", "version": "v1.0.0" },
{ "path": "scripts/validator.py" }
],
"agents": [
{ "path": "agents/code-analyzer.md", "version": "~1.2.0" }
]
}
}§Key Features
- Automatic Discovery: Dependencies extracted during resolution
- Version Inheritance: If no version specified, parent’s version is used
- Same-Source Model: Transitive deps inherit parent’s source repository
- Cycle Detection: Circular dependency loops are detected and prevented
- Topological Ordering: Dependencies installed in correct order
- Optional Resolution: Can be disabled with
--no-transitiveflag
§Data Structures
Transitive dependencies are represented by:
DependencySpec: Individual dependency specification (path + optional version)DependencyMetadata: Collection of dependencies by resource typeDetailedDependency::dependencies: Field storing extracted transitive deps
§Processing Flow
- Manifest dependencies are resolved first
- Resource files are checked for metadata (YAML frontmatter or JSON fields)
- Discovered dependencies are added to dependency graph
- Graph is validated for cycles
- Dependencies are resolved in topological order
- All resources (direct + transitive) are installed
See dependency_spec module for detailed specification formats.
§Error Handling
The manifest module provides comprehensive error handling with:
- Context-rich errors: Detailed messages with actionable suggestions
- Validation errors: Clear explanations of manifest problems
- I/O errors: Helpful context for file system issues
- TOML parsing errors: Specific syntax error locations
- Security validation: Detection of potential security issues
All errors implement std::error::Error and provide both user-friendly
messages and programmatic access to error details.
§Performance Characteristics
- Parsing: O(n) where n is the manifest file size
- Validation: O(d) where d is the number of dependencies
- Serialization: O(n) where n is the total data size
- Memory usage: Proportional to manifest complexity
- Thread safety: All operations are thread-safe
§Integration with Other Modules
The manifest module works closely with other AGPM modules:
§With crate::resolver
use agpm_cli::manifest::Manifest;
use agpm_cli::resolver::DependencyResolver;
let manifest = Manifest::load(&project_path.join("agpm.toml"))?;
let resolver = DependencyResolver::new(&manifest);
let resolved = resolver.resolve_all().await?;§With crate::lockfile
use agpm_cli::manifest::Manifest;
use agpm_cli::lockfile::LockFile;
let manifest = Manifest::load(&project_path.join("agpm.toml"))?;
let lockfile = LockFile::generate_from_manifest(&manifest).await?;
lockfile.save(&project_path.join("agpm.lock"))?;§With crate::git for Source Management
use agpm_cli::manifest::Manifest;
use agpm_cli::git::GitManager;
let manifest = Manifest::load(&project_path.join("agpm.toml"))?;
let git = GitManager::new(&cache_dir);
for (name, url) in &manifest.sources {
git.clone_or_update(name, url).await?;
}Re-exports§
pub use dependency_spec::DependencyMetadata;pub use dependency_spec::DependencySpec;pub use helpers::expand_url;pub use helpers::find_manifest;pub use helpers::find_manifest_from;pub use helpers::find_manifest_with_optional;pub use patches::ManifestPatches;pub use patches::PatchConflict;pub use patches::PatchData;pub use patches::PatchOrigin;pub use resource_dependency::DetailedDependency;pub use resource_dependency::ResourceDependency;pub use tool_config::ArtifactTypeConfig;pub use tool_config::ResourceConfig;pub use tool_config::ToolsConfig;pub use tool_config::WellKnownTool;
Modules§
- dependency_
spec - Transitive dependency specifications for resources.
- helpers
- Helper functions for manifest file operations.
- patches
- Manifest patch support for overriding resource metadata.
- resource_
dependency - Resource dependency types and implementations.
- tool_
config - Tool configuration types for multi-tool support.
Structs§
- Manifest
- Project
Config - The main manifest file structure representing a complete
agpm.tomlfile.