Expand description
Lockfile management for reproducible installations across environments.
This module provides comprehensive lockfile functionality for AGPM, similar to Cargo’s
Cargo.lock
but designed specifically for managing Claude Code resources (agents,
snippets, and commands) from Git repositories. The lockfile ensures that all team members and CI/CD
systems install identical versions of dependencies.
§Overview
The lockfile (agpm.lock
) is automatically generated from the manifest (agpm.toml
)
during installation and contains exact resolved versions of all dependencies. Unlike
the manifest which specifies version constraints, the lockfile pins exact commit hashes
and file checksums for reproducibility.
§Key Concepts
- Version Resolution: Converts version constraints to exact commits
- Dependency Pinning: Locks all transitive dependencies at specific versions
- Reproducibility: Guarantees identical installations across environments
- Integrity Verification: Uses SHA-256 checksums to detect file corruption
- Atomic Operations: All lockfile updates are atomic to prevent corruption
§Lockfile Format Specification
The lockfile uses TOML format with the following structure:
# Auto-generated lockfile - DO NOT EDIT
version = 1
# Source repositories with resolved commits
[[sources]]
name = "community" # Source name from manifest
url = "https://github.com/example/repo.git" # Repository URL
commit = "a1b2c3d4e5f6..." # Resolved commit hash (40 chars)
fetched_at = "2024-01-01T00:00:00Z" # Last fetch timestamp (RFC 3339)
# Agent resources
[[agents]]
name = "example-agent" # Resource name
source = "community" # Source name (optional for local)
url = "https://github.com/example/repo.git" # Source URL (optional for local)
path = "agents/example.md" # Path in source repository
version = "v1.0.0" # Requested version constraint
resolved_commit = "a1b2c3d4e5f6..." # Resolved commit for this resource
checksum = "sha256:abcdef123456..." # SHA-256 checksum of installed file
installed_at = "agents/example-agent.md" # Installation path (relative to project)
# Snippet resources (same structure as agents)
[[snippets]]
name = "example-snippet"
source = "community"
path = "snippets/example.md"
version = "^1.0"
resolved_commit = "a1b2c3d4e5f6..."
checksum = "sha256:fedcba654321..."
installed_at = "snippets/example-snippet.md"
# Command resources (same structure as agents)
[[commands]]
name = "build-command"
source = "community"
path = "commands/build.md"
version = "v1.0.0"
resolved_commit = "a1b2c3d4e5f6..."
checksum = "sha256:123456abcdef..."
installed_at = ".claude/commands/build-command.md"
§Field Details
§Version Field
- Type: Integer
- Purpose: Lockfile format version for future compatibility
- Current: 1
§Sources Array
- name: Unique identifier for the source repository
- url: Full Git repository URL (HTTP/HTTPS/SSH)
- commit: 40-character SHA-1 commit hash at time of resolution
fetched_at
: ISO 8601 timestamp of last successful fetch
§Resources Arrays (agents/snippets/commands)
- name: Unique resource identifier within its type
- source: Source name (omitted for local resources)
- url: Repository URL (omitted for local resources)
- path: Relative path within source repository or filesystem
- version: Original version constraint from manifest (omitted for local)
resolved_commit
: Exact commit containing this resource (omitted for local)- checksum: SHA-256 hash prefixed with “sha256:” for integrity verification
installed_at
: Relative path where resource is installed in project
§Relationship to Manifest
The lockfile is generated from the manifest (agpm.toml
) through dependency resolution:
# agpm.toml (manifest)
[sources]
community = "https://github.com/example/repo.git"
[agents]
example-agent = { source = "community", path = "agents/example.md", version = "^1.0" }
local-agent = { path = "../local/helper.md" }
During agpm install
, this becomes:
# agpm.lock (lockfile)
version = 1
[[sources]]
name = "community"
url = "https://github.com/example/repo.git"
commit = "a1b2c3d4e5f6..."
fetched_at = "2024-01-01T00:00:00Z"
[[agents]]
name = "example-agent"
source = "community"
url = "https://github.com/example/repo.git"
path = "agents/example.md"
version = "^1.0"
resolved_commit = "a1b2c3d4e5f6..."
checksum = "sha256:abcdef..."
installed_at = "agents/example-agent.md"
[[agents]]
name = "local-agent"
path = "../local/helper.md"
checksum = "sha256:123abc..."
installed_at = "agents/local-agent.md"
§Version Resolution and Pinning
AGPM resolves version constraints to exact commits using Git tags and branches:
§Version Constraint Resolution
- Exact versions (
"v1.2.3"
): Match exact Git tag - Semantic ranges (
"^1.0"
,"~1.2"
): Find latest compatible tag - Branch names (
"main"
,"develop"
): Use latest commit on branch - Commit hashes (
"a1b2c3d"
): Use exact commit (must be full 40-char hash)
§Resolution Process
- Fetch Repository: Clone or update source repository cache
- Enumerate Tags: List all Git tags matching semantic version pattern
- Apply Constraints: Filter tags that satisfy version constraint
- Select Latest: Choose highest version within constraint
- Resolve Commit: Map tag to commit hash
- Verify Resource: Ensure resource exists at that commit
- Calculate Checksum: Generate SHA-256 hash of resource content
- Record Entry: Add resolved information to lockfile
§Install vs Update Semantics
§Install Behavior
- Uses existing lockfile if present (respects pinned versions)
- Only resolves dependencies not in lockfile
- Preserves existing pins even if newer versions available
- Ensures reproducible installations
§Update Behavior
- Ignores existing lockfile constraints
- Re-resolves all dependencies against current manifest constraints
- Updates to latest compatible versions within constraints
- Regenerates entire lockfile
# Install exact versions from lockfile (if available)
agpm install
# Update to latest within manifest constraints
agpm update
# Update specific resource
agpm update example-agent
§Checksum Verification
AGPM uses SHA-256 checksums to ensure file integrity:
§Checksum Format
- Algorithm: SHA-256
- Encoding: Hexadecimal
- Prefix: “sha256:”
- Example: “sha256:a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3”
§Verification Process
- During Installation: Calculate checksum of installed file
- During Validation: Compare stored checksum with file content
- On Mismatch: Report corruption and suggest re-installation
§Best Practices
§Commit Lockfile to Version Control
The lockfile should always be committed to version control:
# Commit both manifest and lockfile together
git add agpm.toml agpm.lock
git commit -m "Add new agent dependency"
This ensures all team members get identical dependency versions.
§Don’t Edit Lockfile Manually
The lockfile is auto-generated and should not be edited manually:
- Use
agpm install
to update lockfile from manifest changes - Use
agpm update
to update dependency versions - Delete lockfile and run
agpm install
to regenerate from scratch
§Lockfile Conflicts
During Git merges, lockfile conflicts may occur:
# Resolve by regenerating lockfile
rm agpm.lock
agpm install
git add agpm.lock
git commit -m "Resolve lockfile conflict"
§Migration and Upgrades
§Format Version Compatibility
AGPM checks lockfile format version and provides clear error messages:
Error: Lockfile version 2 is newer than supported version 1.
This lockfile was created by a newer version of agpm.
Please update agpm to the latest version to use this lockfile.
§Upgrading Lockfiles
Future format versions will include automatic migration:
# Future: Migrate lockfile to newer format
agpm install --migrate-lockfile
§Comparison with Cargo.lock
AGPM’s lockfile design is inspired by Cargo but adapted for Git-based resources:
Feature | Cargo.lock | agpm.lock |
---|---|---|
Format | TOML | TOML |
Versioning | Semantic | Git tags/branches/commits |
Integrity | Checksums | SHA-256 checksums |
Sources | crates.io + git | Git repositories only |
Resources | Crates | Agents + Snippets |
Resolution | Dependency graph | Flat dependency list |
§Error Handling
The lockfile module provides detailed error messages with actionable suggestions:
- Parse Errors: TOML syntax issues with fix suggestions
- Version Errors: Incompatible format versions with upgrade instructions
- IO Errors: File system issues with permission/space guidance
- Corruption: Checksum mismatches with re-installation steps
§Cross-Platform Considerations
Lockfiles are fully cross-platform compatible:
- Path Separators: Always use forward slashes in lockfile paths
- Line Endings: Normalize to LF for consistent checksums
- File Permissions: Not stored in lockfile (Git handles this)
- Case Sensitivity: Preserve case from source repositories
§Performance Characteristics
- Parsing: O(n) where n is number of locked resources
- Checksum Calculation: O(m) where m is total file size
- Lookups: O(n) linear search (suitable for typical dependency counts)
- Atomic Writes: Single fsync per lockfile update
§Thread Safety
The LockFile
struct is not thread-safe by itself, but the module provides
atomic operations for concurrent access:
- File Locking: Uses OS file locking during atomic writes
- Process Safety: Multiple agpm instances coordinate via lockfile
- Concurrent Reads: Safe to read lockfile from multiple threads
Re-exports§
pub use private_lock::PrivateLockFile;
Modules§
- patch_
display - Helper functions for displaying patch information with original and overridden values.
- private_
lock - Private lockfile management for user-level patches.
Structs§
- Lock
File - The main lockfile structure representing a complete
agpm.lock
file. - Locked
Resource - A locked resource (agent or snippet) with resolved version and integrity information.
- Locked
Source - A locked source repository with resolved commit information.
Enums§
- Staleness
Reason - Reasons why a lockfile might be considered stale.
Functions§
- find_
lockfile - Find the lockfile in the current or parent directories.