CCPM - Claude Code Package Manager
A Git-based package manager for Claude Code resources that enables reproducible installations using lockfile-based dependency management, similar to Cargo.
Overview
CCPM (Claude Code Package Manager) is a command-line tool written in Rust that simplifies the deployment and management of Claude agents and snippets across different projects. Using a manifest-based approach with lockfile support, CCPM provides reproducible, version-controlled installations of AI resources directly from Git repositories. CCPM includes specialized Rust development agents with delegation patterns for efficient code development workflows.
Quick Links
- FAQ - Frequently asked questions and quick answers
- Installation - Get started with CCPM
- Quick Start - Basic usage examples
- Documentation - Full documentation links
Table of Contents
- Features
- Resource Types
- Installation
- Quick Start
- Core Commands
- Manifest Format
- Versioning in CCPM
- Lockfile Format
- Configuration-Merged Resources in Detail
- Scripts and Hooks Examples
- Advanced Usage
- Project Structure
- Design Decisions
- Documentation
- Building from Source
- Architecture
- Versioning
- Best Practices
- Troubleshooting
- Contributing
- License
- Inspiration
- Support
Features
- Lockfile-Based Management: Reproducible installations using
ccpm.toml+ccpm.lock(similar to Cargo) - Git-based Distribution: Install resources directly from any Git repository (GitHub, GitLab, Bitbucket, etc.)
- No Central Registry: Fully decentralized - add any Git repository as a source
- Dependency Resolution: Automatic version constraint resolution with conflict detection
- Cross-Platform Support: Works reliably on Windows, macOS, and Linux
- Comprehensive CLI: Full-featured command-line interface with 9 commands plus global options
- Specialized Agents: Includes expert Rust agents with delegation patterns for development workflows
- Parallel Operations: Safe concurrent operations with automatic file locking
Resource Types
CCPM manages two categories of resources based on how they're integrated into Claude Code:
Direct Installation Resources
These resources are copied directly to their target directories and used as standalone files:
Agents
AI assistant configurations with prompts and behavioral definitions. Installed to .claude/agents/ by default.
Snippets
Reusable code templates and documentation fragments. Installed to .claude/ccpm/snippets/ by default.
Commands
Claude Code slash commands that extend Claude Code functionality. Installed to .claude/commands/ by default.
Scripts
Executable files (.sh, .js, .py, etc.) that can be run by hooks or independently for automation tasks. Installed to
.claude/ccpm/scripts/ by default.
Configuration-Merged Resources
These resources are installed to .claude/ccpm/ and then their configurations are merged into Claude Code's settings
files:
Hooks
Event-based automation configurations for Claude Code. JSON files that define when to run scripts based on tool usage or other events (PreToolUse, PostToolUse, UserPromptSubmit, etc.).
- Installation: Files copied to
.claude/ccpm/hooks/ - Configuration: Automatically merged into
.claude/settings.local.json - Behavior: CCPM preserves user-configured hooks while managing its own
MCP Servers
Model Context Protocol servers that extend Claude Code's capabilities with external tools and APIs. JSON configuration files defining how to run external servers.
- Installation: Files copied to
.claude/ccpm/mcp-servers/ - Configuration: Automatically merged into
.mcp.json - Behavior: CCPM only manages servers it installs, preserving user-added servers
Installation
Note: CCPM is currently in active development. Installation will be available once the first release is published.
# Build from source (current method)
# Or install directly with cargo
# Future: Install via cargo (once published)
# cargo install ccpm
Requirements:
- Rust 1.70 or later
- Git 2.0 or later
- Cross-platform support: Windows, macOS, Linux
Quick Start
1. Create a Project Manifest
Create a ccpm.toml file in your project root (or use ccpm init to generate a template):
# Define sources - Git repositories or local directories
[]
= "https://github.com/aig787/ccpm-community.git"
= "./dependencies" # Local directory (no Git required)
# Optional: Customize installation directories
# [target]
# agents = "path/to/agents"
# snippets = "path/to/snippets"
# Agents
[]
= { = "community", = "agents/example.md", = "v1.0.0" }
= { = "local-deps", = "agents/helper.md" } # No version for local paths
# Snippets
[]
= { = "community", = "snippets/example.md", = "v1.0.0" }
= { = "local-deps", = "snippets/utils.md" }
# Scripts - Executable files for automation
[]
= { = "community", = "scripts/security.sh", = "v1.0.0" }
= { = "community", = "scripts/validate.py", = "v1.0.0" }
# Hooks - Event-based automation for Claude Code
[]
= { = "community", = "hooks/pre-bash.json", = "v1.0.0" }
= { = "community", = "hooks/post-tool.json", = "v1.0.0" }
# MCP Servers
[]
= { = "community", = "mcp-servers/filesystem.json", = "v1.0.0" }
= { = "local-deps", = "mcp-servers/postgres.json" }
2. Install Dependencies
# Install all dependencies and generate lockfile
# Output:
# 📦 Installing dependencies from ccpm.toml...
# ✅ Resolved 2 dependencies
# ✅ Installed example-agent v1.0.0
# ✅ Installed example-snippet v1.0.0
# ✅ Generated ccpm.lock
This creates:
ccpm.lock- Lockfile with exact resolved versions.claude/agents/- Directory with installed agent files (default location).claude/ccpm/snippets/- Directory with installed snippet files (default location)
Important: File Naming During Installation
Installed files are named based on the dependency name in ccpm.toml, not their original filename in the source
repository.
For example:
[]
# Source file: scripts/build.sh
# Installed as: .claude/ccpm/scripts/my-builder.sh (uses the key "my-builder")
= { = "tools", = "scripts/build.sh" }
[]
# Source file: agents/code-reviewer.md
# Installed as: .claude/agents/reviewer.md (uses the key "reviewer")
= { = "community", = "agents/code-reviewer.md" }
This naming convention allows you to:
- Give resources meaningful names in your project context
- Avoid naming conflicts when using resources from multiple sources
- Rename resources without modifying the source repository
3. Basic Workflows
# Update dependencies within version constraints
# List installed resources
# Validate manifest and lockfile
# Use exact lockfile versions (for CI/CD)
Core Commands
CCPM provides 9 commands for managing dependencies:
| Command | Purpose | Key Options |
|---|---|---|
init |
Initialize a new ccpm.toml manifest file | --path, --force |
add |
Add sources or dependencies to ccpm.toml | source, dep |
remove |
Remove sources or dependencies from ccpm.toml | source, dep |
install |
Install dependencies from ccpm.toml, generate/update lockfile | --frozen, --no-cache, --force, --max-parallel |
update |
Update dependencies within version constraints | --dry-run, --max-parallel |
list |
Show installed resources from lockfile or manifest | --manifest, --format json |
validate |
Validate ccpm.toml syntax and check dependencies | --resolve, --check-lock |
cache |
Manage the global git cache | clean, clean --all, info |
config |
Manage global configuration | init, show, edit, add-source, list-sources |
Global Options (available for all commands):
--verbose/-v: Enable debug output--quiet/-q: Suppress output except errors--config/-c: Path to custom global config file--manifest-path: Path to custom manifest file (ccpm.toml)--no-progress: Disable progress bars and spinners
Command Examples
Initialize a new project
# Create a new manifest in current directory
# Create in a specific directory
# Force overwrite existing manifest
Add dependencies dynamically
# Add a source repository
# Add dependencies
# Remove dependencies
Manifest Format
ccpm.toml Structure
# Sources can be Git repositories or local directories
[]
= "https://github.com/aig787/ccpm-community.git"
= "git@github.com:mycompany/private-agents.git"
= "./local-resources" # Local directory (no Git required)
# Target directories (optional - defaults shown)
[]
= ".claude/agents" # Where to install agents
= ".claude/ccpm/snippets" # Where to install snippets
= ".claude/ccpm/scripts" # Where to install scripts
= ".claude/ccpm/hooks" # Where to install hooks
# Agents
[]
= { = "community", = "agents/example.md", = "v1.0.0" }
= { = "private", = "agents/custom.md", = "v2.1.0" }
# Snippets
[]
= { = "community", = "snippets/example.md", = "v1.2.0" }
= { = "community", = "snippets/helper.md", = "v1.0.0" }
# Scripts - Executable files for automation
[]
= { = "community", = "scripts/security.sh", = "v1.0.0" }
= { = "private", = "scripts/validate.py", = "v2.0.0" }
# Hooks - Event-based automation configurations
[]
= { = "community", = "hooks/pre-bash.json", = "v1.0.0" }
= { = "private", = "hooks/validation.json", = "v1.1.0" }
# MCP Servers - Model Context Protocol servers
[]
= { = "community", = "mcp-servers/filesystem.json", = "v1.0.0" }
= { = "private", = "mcp-servers/postgres.json", = "v1.0.0" }
Dependency Specification
Dependencies can be specified in multiple ways:
# Exact version (with or without 'v' prefix)
= { = "community", = "agents/agent1.md", = "1.0.0" }
= { = "community", = "agents/agent2.md", = "v1.0.0" }
# Semver ranges (standard cargo/npm-style version constraints)
= { = "community", = "agents/agent3.md", = "^1.2.0" } # Compatible: 1.2.0, 1.3.0, etc. (not 2.0.0)
= { = "community", = "agents/agent4.md", = "~1.2.0" } # Patch only: 1.2.0, 1.2.1, etc. (not 1.3.0)
= { = "community", = "agents/agent5.md", = ">=1.0.0" } # At least 1.0.0
= { = "community", = "agents/agent6.md", = ">=1.0.0, <2.0.0" } # Range
# Special keywords
= { = "community", = "agents/latest.md", = "latest" } # Latest stable (no pre-releases)
= { = "community", = "agents/beta.md", = "latest-prerelease" } # Latest including pre-releases
= { = "community", = "agents/any.md", = "*" } # Any version
# Git references
= { = "community", = "agents/dev.md", = "main" }
= { = "community", = "agents/fixed.md", = "abc123def" }
# Local file (no source needed, no version support)
= { = "../local-agents/helper.md" }
Version Range Syntax
CCPM supports standard semantic versioning (semver) ranges, following the same conventions as Cargo and npm:
| Syntax | Example | Matches | Description |
|---|---|---|---|
1.2.3 or v1.2.3 |
version = "1.2.3" |
Exactly 1.2.3 | Both formats accepted |
^1.2.3 |
version = "^1.2.3" |
>=1.2.3, <2.0.0 | Compatible releases |
~1.2.3 |
version = "~1.2.3" |
>=1.2.3, <1.3.0 | Patch releases only |
>=1.2.3 |
version = ">=1.2.3" |
Any version >= 1.2.3 | Minimum version |
>1.2.3 |
version = ">1.2.3" |
Any version > 1.2.3 | Greater than |
<=1.2.3 |
version = "<=1.2.3" |
Any version <= 1.2.3 | Maximum version |
<1.2.3 |
version = "<1.2.3" |
Any version < 1.2.3 | Less than |
>=1.0.0, <2.0.0 |
version = ">=1.0.0, <2.0.0" |
1.x.x versions | Complex ranges |
* |
version = "*" |
Any version | Wildcard |
latest |
version = "latest" |
Latest stable | Excludes pre-releases |
Versioning in CCPM
CCPM uses Git-based versioning, which means version constraints apply at the repository level, not individual files. Understanding how versioning works is crucial for effectively managing dependencies.
How Versioning Works
-
Repository-Level Versioning: When you specify a version (e.g.,
version = "v1.0.0"), you're referencing a Git tag on the entire repository, not individual files. All resources from that repository at that tag share the same version. -
Git References: CCPM supports multiple ways to reference specific points in a repository's history:
- Git Tags (recommended): Semantic versions like
v1.0.0,v2.1.3 - Git Branches: Branch names like
main,develop,feature/xyz - Git Commits: Specific commit hashes like
abc123def - Special Keywords:
latest(newest tag),*(any version)
- Git Tags (recommended): Semantic versions like
-
No Versioning for Local Directories: Local directory sources and direct file paths don't support versioning because they're not Git repositories. They always use the current state of the files.
Version Reference Types
Git Tags (Recommended)
Git tags are the primary versioning mechanism in CCPM. They provide stable, semantic version numbers:
[]
# Exact version using a git tag
= { = "community", = "agents/example.md", = "v1.0.0" }
# Version ranges using semantic versioning
= { = "community", = "agents/helper.md", = "^1.2.0" } # 1.2.0 to <2.0.0
= { = "community", = "agents/util.md", = "~1.2.3" } # 1.2.3 to <1.3.0
How it works: When CCPM resolves version = "v1.0.0", it:
- Looks for a Git tag named
v1.0.0in the repository - Checks out the repository at that tag
- Retrieves the specified file from that tagged state
Git Branches
Branches reference the latest commit on a specific branch:
[]
# Track the main branch (updates with each install/update)
= { = "community", = "agents/dev.md", = "main" }
# Track a feature branch
= { = "community", = "agents/new.md", = "feature/new-capability" }
Important: Branch references are mutable - they update to the latest commit each time you run ccpm update. Use
tags for stable, reproducible builds.
Git Commit Hashes
For absolute reproducibility, reference specific commits:
[]
# Pin to exact commit (immutable)
= { = "community", = "agents/stable.md", = "abc123def456" }
Use cases:
- Debugging specific versions
- Pinning to commits between releases
- Maximum reproducibility when tags aren't available
Local Resources (No Versioning)
Local resources don't support versioning because they're not in Git:
[]
# Local directory source - no Git, no versions
= "./dependencies"
[]
# ✅ VALID - Local source without version
= { = "local-deps", = "agents/helper.md" }
# ❌ INVALID - Can't use version with local directory source
# bad-agent = { source = "local-deps", path = "agents/helper.md", version = "v1.0.0" } # ERROR!
# Direct file path - also no version support
= { = "../agents/my-agent.md" }
# ❌ INVALID - Can't use version with direct path
# bad-direct = { path = "../agents/my-agent.md", version = "v1.0.0" } # ERROR!
Version Resolution Process
When CCPM installs dependencies, it follows this resolution process:
- Parse Version Constraint: Interpret the version specification (tag, range, branch, etc.)
- Fetch Repository Metadata: Get list of tags/branches from the Git repository
- Match Versions: Find all versions that satisfy the constraint
- Select Best Match: Choose the highest version that satisfies constraints
- Lock Version: Record the exact commit hash in
ccpm.lock
Version Constraints and Ranges
CCPM supports sophisticated version constraints using semantic versioning:
| Constraint | Example | Resolves To | Use Case |
|---|---|---|---|
| Exact | "1.2.3" or "v1.2.3" |
Exactly version 1.2.3 | Pinning to specific release |
| Caret | "^1.2.3" |
>=1.2.3, <2.0.0 | Allow compatible updates |
| Tilde | "~1.2.3" |
>=1.2.3, <1.3.0 | Allow patch updates only |
| Greater | ">1.2.3" |
Any version >1.2.3 | Minimum version requirement |
| Range | ">=1.0.0, <2.0.0" |
1.x.x versions | Complex constraints |
| Latest | "latest" |
Newest stable tag | Always use newest stable |
| Wildcard | "*" |
Any version | No constraints |
Lockfile and Reproducibility
The ccpm.lock file ensures reproducible installations by recording:
[[]]
= "example-agent"
= "community"
= "agents/example.md"
= "v1.0.0" # Original constraint
= "abc123def..." # Exact commit hash
= "v1.0.0" # Actual tag/version used
Key points:
- Original constraint (
version): What was requested inccpm.toml - Resolved commit (
resolved_commit): Exact Git commit hash - Resolved version (
resolved_version): The tag/branch that was resolved
Version Selection Examples
Given available tags: v1.0.0, v1.1.0, v1.2.0, v2.0.0
| Constraint | Selected Version | Explanation |
|---|---|---|
"^1.0.0" |
v1.2.0 |
Highest 1.x.x version |
"~1.0.0" |
v1.0.0 |
Only 1.0.x allowed |
">=1.1.0, <2.0.0" |
v1.2.0 |
Highest within range |
"latest" |
v2.0.0 |
Newest stable tag |
">1.0.0" |
v2.0.0 |
Highest available |
Best Practices for Versioning
- Use Semantic Version Tags: Tag releases with semantic versions (
v1.0.0,v2.1.3) - Prefer Tags Over Branches: Tags are immutable; branches change over time
- Use Caret Ranges:
^1.0.0allows compatible updates while preventing breaking changes - Lock for Production: Commit
ccpm.lockand use--frozenflag in CI/CD - Document Breaking Changes: Use major version bumps (v1.x.x → v2.x.x) for breaking changes
- Test Before Updating: Use
ccpm update --dry-runto preview changes
Common Versioning Scenarios
Scenario 1: Development vs Production
# Development - track latest changes
[]
= { = "community", = "agents/new.md", = "main" }
# Production - stable versions only
[]
= { = "community", = "agents/proven.md", = "^1.0.0" }
Scenario 2: Gradual Updates
# Start conservative
= { = "community", = "agents/example.md", = "~1.2.0" } # Patches only
# After testing, allow minor updates
= { = "community", = "agents/example.md", = "^1.2.0" } # Compatible updates
# Eventually, allow any 1.x version
= { = "community", = "agents/example.md", = ">=1.2.0, <2.0.0" }
Scenario 3: Mixed Sources
[]
= "https://github.com/org/stable-resources.git" # Tagged releases
= "https://github.com/org/dev-resources.git" # Active development
= "./local-resources" # Local directory
[]
= { = "stable-repo", = "agents/prod.md", = "v2.1.0" } # Specific tag
= { = "dev-repo", = "agents/exp.md", = "develop" } # Branch tracking
= { = "local", = "agents/wip.md" } # No version (local)
Local Dependencies
1. Local Directory Sources
You can use local directories as sources without requiring Git. This is perfect for development and testing:
[]
# Local directory as a source - no Git required
= "./dependencies"
= "../shared-resources"
= "/home/user/ccpm-resources"
[]
# Dependencies from local directory sources don't need versions
= { = "local-deps", = "agents/helper.md" }
= { = "shared-resources", = "agents/common.md" }
Security Note: For security, local paths are restricted to:
- Within the current project directory
- Within the CCPM cache directory (
~/.ccpm/cache) - Within
/tmpfor testing
2. Direct File Paths
You can reference individual files directly without a source:
# Direct file paths - NO version support
= { = "../agents/my-agent.md" }
= { = "./snippets/util.md" }
# ❌ INVALID - versions not allowed for direct paths
# local-versioned = { path = "../agents/agent.md", version = "v1.0.0" } # ERROR!
3. Local Git Repositories (file:// URLs)
Use file:// URLs in sources to reference local git repositories with full git functionality:
[]
# Local git repository with full version support
= "file:///home/user/my-git-repo"
[]
# Can use versions, branches, tags with local git repos
= { = "local-repo", = "agents/agent.md", = "v1.0.0" }
= { = "local-repo", = "agents/dev.md", = "develop" }
Important Notes:
- Plain directory paths (
../,./,/) are for simple file references only file://URLs must point to valid git repositories (containing.gitdirectory)- Plain paths as sources are NOT allowed - sources must be git repositories
Lockfile Format
The ccpm.lock file tracks exact resolved versions:
# Auto-generated lockfile - DO NOT EDIT
= 1
[[]]
= "community"
= "https://github.com/aig787/ccpm-community.git"
= "abc123def..."
= "2024-01-01T00:00:00Z"
[[]]
= "example-agent"
= "community"
= "agents/example.md"
= "v1.0.0"
= "abc123def..."
= "sha256:abcdef..."
= "agents/example-agent.md"
Configuration-Merged Resources in Detail
How Configuration Merging Works
Unlike direct installation resources that are simply copied to their target directories, configuration-merged resources (Hooks and MCP Servers) follow a two-step process:
- File Installation: JSON configuration files are installed to
.claude/ccpm/ - Configuration Merging: Settings are automatically merged into Claude Code's configuration files
- Non-destructive Updates: CCPM preserves user-configured entries while managing its own
- Version Control Strategy: By default, CCPM creates
.claude/.gitignoreto exclude installed files from Git. This means:- The
ccpm.tomlmanifest andccpm.locklockfile are committed to version control - Installed resource files (agents, snippets, scripts, etc.) are automatically gitignored
- Team members run
ccpm installto get their own copies of resources - To commit resources to Git instead, set
gitignore = falsein the[target]section ofccpm.toml
- The
Scripts and Hooks Examples
Working with Hooks
Hooks enable event-based automation in Claude Code. They consist of:
- Scripts: Executable files that perform the actual work
- Hook configurations: JSON files that define when scripts should run
Script Example
First, create executable scripts that perform automation tasks:
# scripts/security-check.sh
#!/bin/bash
if [; then
fi
Hook Configuration Example
Then, create hook JSON files that configure when scripts should run:
This hook will run the security check script before Claude Code uses the Bash, Write, or Edit tools.
Hook Events
Available hook events in Claude Code:
PreToolUse- Before a tool is executedPostToolUse- After a tool completesUserPromptSubmit- When user submits a promptUserPromptReceive- When prompt is receivedAssistantResponseReceive- When assistant responds
Installing Scripts and Hooks
# ccpm.toml
[]
= { = "security-tools", = "scripts/security-check.sh", = "v1.0.0" }
= { = "security-tools", = "scripts/validate.py", = "v1.0.0" }
[]
= { = "security-tools", = "hooks/pre-bash.json", = "v1.0.0" }
= { = "security-tools", = "hooks/file-guard.json", = "v1.0.0" }
After running ccpm install:
- Hooks are automatically merged into
.claude/settings.local.json, preserving any existing user-configured hooks
Working with MCP Servers
MCP (Model Context Protocol) servers extend Claude Code's capabilities with external tools and APIs. They provide integrations with databases, file systems, and other services.
MCP Server Configuration Format
MCP server JSON files define how to run the server:
Installing MCP Servers
# ccpm.toml
[]
# MCP server from a repository
= { = "community", = "mcp-servers/filesystem.json", = "v1.0.0" }
= { = "community", = "mcp-servers/github.json", = "v1.2.0" }
# Local MCP server configuration
= { = "local-deps", = "mcp-servers/custom.json" }
After running ccpm install:
- MCP server JSON files are installed to
.claude/ccpm/mcp-servers/ - Configurations are automatically merged into
.mcp.json - CCPM adds metadata (
_ccpm) to track which servers it manages - User-configured servers in
.mcp.jsonare preserved
Example .mcp.json After Installation
Important Notes:
- MCP servers require their runtimes to be installed (Node.js for
npx, Python foruvx, etc.) - Environment variables in configurations support
${VAR}expansion - The
.mcp.jsonfile contains both CCPM-managed and user-managed servers
Advanced Usage
Global Configuration
CCPM supports a global configuration file at ~/.ccpm/config.toml for storing sensitive data like authentication tokens
that shouldn't be committed to version control.
Setting Up Global Config
# Initialize with example configuration
# Edit the config file
# Show current configuration
Global Config Example
# ~/.ccpm/config.toml
[]
# Private sources with authentication
= "https://oauth2:ghp_xxxx@github.com/yourcompany/private-ccpm.git"
Managing Global Sources
# Add a private source with authentication
# List all global sources (tokens are masked)
# Remove a source
Source Priority
Sources are resolved in this order:
- Global sources from
~/.ccpm/config.toml(loaded first) - Local sources from
ccpm.toml(can override global)
This allows teams to share ccpm.toml without exposing credentials.
Security Best Practices
IMPORTANT: Never put credentials in ccpm.toml
- ✅ DO: Store authentication tokens in
~/.ccpm/config.toml(global config) - ✅ DO: Use SSH URLs for public repositories in
ccpm.toml - ✅ DO: Commit
ccpm.tomlto version control - ❌ DON'T: Put tokens, passwords, or secrets in
ccpm.toml - ❌ DON'T: Use HTTPS URLs with embedded credentials in
ccpm.toml - ❌ DON'T: Commit
~/.ccpm/config.tomlto version control
The separation between project manifest (ccpm.toml) and global config (~/.ccpm/config.toml) ensures that sensitive
credentials never end up in your repository.
Private Repositories
For repositories that don't require secrets, you can define them directly in ccpm.toml:
Use SSH authentication:
[]
= "git@github.com:mycompany/private-agents.git"
For repositories with secrets, use the global config instead:
# Add to global config (not committed to git)
Reproducible Builds
For team consistency, commit your lockfile:
Team members install exact versions:
# Install exact versions from lockfile (recommended for CI/CD)
Performance Optimization
CCPM automatically uses parallel operations for maximum performance:
# Installation uses parallel operations by default
# Control parallelism level if needed
Development Workflow
# Update specific dependencies
# Preview updates without making changes
# Validate before committing
Project Structure
After installation, your project structure looks like:
my-project/
├── ccpm.toml # Dependency manifest
├── ccpm.lock # Resolved versions (commit this!)
├── .claude/
│ ├── agents/ # CCPM-installed agents
│ │ └── example-agent.md
│ ├── commands/ # CCPM-installed commands
│ │ └── deploy.md
│ ├── settings.local.json # Hook configurations
│ └── ccpm/
│ ├── snippets/ # CCPM-installed snippets
│ │ └── example-snippet.md
│ ├── scripts/ # CCPM-installed scripts
│ │ └── build.sh
│ ├── hooks/ # Hook JSON files
│ │ └── pre-bash.json
│ └── mcp-servers/ # MCP server configurations
│ └── filesystem.json
└── .mcp.json # MCP server runtime configuration
Cache location: ~/.ccpm/cache/ (Unix/macOS) or %LOCALAPPDATA%\ccpm\cache\ (Windows)
Design Decisions
Installation Model
CCPM copies files from cache to project directories rather than using symlinks:
- Maximum Compatibility: Works identically on Windows, macOS, and Linux
- Git-Friendly: Real files can be tracked and committed
- Editor-Friendly: No symlink confusion in IDEs
- User-Friendly: Edit installed files without affecting the cache
- Name Control: Files are installed with the dependency name from
ccpm.toml, not the source filename
Cache Management
CCPM maintains a global cache at ~/.ccpm/cache/ for cloned repositories:
Benefits:
- Fast reinstalls from cached repositories
- Offline work once cached
- Bandwidth efficient with incremental updates
- Clean projects without heavy directories
Documentation
- USAGE.md - Comprehensive usage guide with all commands and examples
- CONTRIBUTING.md - Guidelines for contributing to CCPM
- LICENSE.md - MIT License terms
Building from Source
Requirements:
- Rust 1.70 or later (required for building)
- Git 2.0 or later (required for repository operations)
- Cross-platform support: Windows 10+, macOS 10.15+, Linux (modern distributions)
# Clone the repository
# Build in release mode
# Run tests
# Install locally
# Build for different targets
Architecture
CCPM is built with Rust and uses system Git for compatibility. Key components:
- manifest: Parses ccpm.toml files
- lockfile: Manages ccpm.lock files
- resolver: Dependency resolution and conflict detection
- git: Git operations with authentication support
- cache: Global repository cache with file locking
- cli: Command implementations with optional manifest path support
- test_utils: Comprehensive testing framework with parallel test safety (no WorkingDirGuard)
Concurrent Operations & File Locking
CCPM uses file locking (similar to Cargo) to prevent cache corruption during concurrent operations. Each cached
repository has a lock file at ~/.ccpm/cache/.locks/<source-name>.lock that ensures:
- Safe parallel installations from different sources
- No git index corruption
- Automatic lock management
- Cross-platform compatibility via fs4
- Safe parallel test execution after eliminating WorkingDirGuard for better performance
Versioning
CCPM follows semantic versioning and uses repository-level versioning (similar to GitHub Actions and Cargo workspaces):
- Repository-level versioning: Versions apply to entire repositories, not individual files
- Git-native: When you specify
version = "v1.1.0", you get the repository at that Git tag - Consistency: All resources from the same repository version share the same resolved commit
- Simplicity: No complex per-file version tracking, just standard Git operations
This design provides Git-native compatibility and operational simplicity while trading off granular per-file version control.
Best Practices
- Always commit ccpm.lock - Ensures reproducible builds across team
- Use semantic versions - Prefer
version = "v1.0.0"over branches - Validate before commits - Run
ccpm validateto catch issues early - Use --frozen in CI/CD - Ensures deterministic builds in automation
- Leverage parallel operations - Automatic parallel processing speeds up installations
- Document custom sources - Add comments in ccpm.toml for team clarity
- Use specialized agents - Leverage built-in Rust development agents:
rust-expert: General Rust development and API designrust-linting-expert: Fast linting fixes with cargo fmt and clippyrust-doc-expert: Comprehensive documentation and rustdoc commentsrust-test-fixer: Fast test failure fixes and assertion debuggingrust-troubleshooter-opus: Advanced debugging and performance analysis
Troubleshooting
Common Issues
No manifest found:
# Or manually create ccpm.toml with your dependencies
Version conflict:
# Update version constraints in ccpm.toml
Authentication failure:
# For SSH: Ensure SSH keys are configured
# For HTTPS: Use personal access tokens in URL
Lockfile out of sync:
Performance issues:
# Parallel processing is automatic
# Adjust parallelism if needed
Contributing
We welcome contributions! Please see our Contributing Guide for details.
# Fork and clone the repository
# Create a feature branch
# Make your changes and run tests
# Submit a pull request
License
MIT License - see LICENSE.md file for details.
Inspiration
CCPM draws inspiration from:
- Cargo - Rust package manager (lockfile approach)
- npm - Node.js package manager
- Helm - Kubernetes package manager
Project Status
CCPM is currently in active development with comprehensive test coverage and cross-platform support. The project includes:
- ✅ Core functionality: All 9 commands implemented and tested
- ✅ Cross-platform support: Windows, macOS, and Linux compatibility
- ✅ Test coverage: Comprehensive test suite with parallel execution safety
- ✅ Documentation: Extensive rustdoc comments and user guides
- ✅ Specialized agents: Built-in Rust development agents with delegation patterns
- 🚧 First release: Preparing for initial public release
Support
For issues and feature requests, please use the GitHub issue tracker.
For questions and discussions, join our GitHub Discussions.