Expand description
Manifest file parsing and validation for CCPM projects.
This module handles the ccpm.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
ccpm.toml - Reproducible installations via lockfile generation
- Support for multiple Git-based source repositories
- Local and remote dependency resolution
- Version constraint specification and validation
- 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 ccpm.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/ccpm-official.git"
community = "https://github.com/community/ccpm-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: ".claude/ccpm/snippets")
snippets = ".claude/ccpm/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/ccpm-resources.git"
community = "https://gitlab.com/group/ccpm-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 = ".claude/ccpm/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
CCPM 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 ccpm.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 ~/.ccpm/config.toml
# Or use SSH keys with git@ URLs
[sources]
private = "git@github.com:company/repo.git"Authentication should be configured globally in ~/.ccpm/config.toml or
through SSH keys for git@ URLs. See crate::config for details.
§Relationship to Lockfile
The manifest works together with the lockfile (ccpm.lock):
- Manifest (
ccpm.toml): Declares dependencies and constraints - Lockfile (
ccpm.lock): Records exact resolved versions and checksums
When you run ccpm install:
- Reads dependencies from
ccpm.toml - Resolves versions within constraints
- Generates/updates
ccpm.lockwith exact commits - Installs resources to target directories
See crate::lockfile for lockfile format details.
§Cross-Platform Compatibility
CCPM 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
ccpm.tomlto git - Validate regularly: Run
ccpm validatebefore commits - Use lockfiles: Commit
ccpm.lockfor reproducible builds
§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 CCPM modules:
§With crate::resolver
use ccpm::manifest::Manifest;
use ccpm::resolver::DependencyResolver;
let manifest = Manifest::load(&project_path.join("ccpm.toml"))?;
let resolver = DependencyResolver::new(&manifest);
let resolved = resolver.resolve_all().await?;§With crate::lockfile
use ccpm::manifest::Manifest;
use ccpm::lockfile::LockFile;
let manifest = Manifest::load(&project_path.join("ccpm.toml"))?;
let lockfile = LockFile::generate_from_manifest(&manifest).await?;
lockfile.save(&project_path.join("ccpm.lock"))?;§With crate::git for Source Management
use ccpm::manifest::Manifest;
use ccpm::git::GitManager;
let manifest = Manifest::load(&project_path.join("ccpm.toml"))?;
let git = GitManager::new(&cache_dir);
for (name, url) in &manifest.sources {
git.clone_or_update(name, url).await?;
}Structs§
- Detailed
Dependency - Detailed dependency specification with full control over source resolution.
- Manifest
- The main manifest file structure representing a complete
ccpm.tomlfile. - Target
Config - Target directories configuration specifying where resources are installed.
Enums§
- Resource
Dependency - A resource dependency specification supporting multiple formats.
Functions§
- find_
manifest - Find the manifest file by searching up the directory tree from the current directory.
- find_
manifest_ from - Find the manifest file by searching up from a specific starting directory.
- find_
manifest_ with_ optional - Find the manifest file, using an explicit path if provided.