CLI tool that fetches dependency source code for LLM context.
LLMs hallucinate APIs and rely on stale training data. When documentation is missing or lacking, the source code is the only truth. This tool makes dependency source one file read away.
Manually add dependencies you need to explore. Clone their repos, symlink into .deps/ for easy LLM browsing.
- Auto-fetching all dependencies
- Transitive dependencies
- 100% repo detection accuracy
- Automatic sync
- Private registry authentication
dotdeps add <ecosystem>:<package>[@<version>]
dotdeps remove <ecosystem>:<package>
dotdeps list
dotdeps --clean
dotdeps add python:requests # version from lockfile
dotdeps add python:requests@2.31.0 # explicit version
dotdeps add node:lodash@4.17.21
dotdeps add node:@org/pkg # scoped package
dotdeps add go:github.com/org/repo/v2
dotdeps remove python:requests
dotdeps list
dotdeps --clean # remove all .deps
<ecosystem>:<package>@<version>
| Component | Required | Notes |
|---|---|---|
| ecosystem | Yes | python, node, go, rust, ruby |
| package | Yes | Native package name (including scopes, paths) |
| version | No | Inferred from lockfile if omitted |
| Ecosystem | Format | Example |
|---|---|---|
| Node.js | name or @scope/name | lodash, @org/pkg |
| Python | name | requests |
| Go | module path | github.com/org/repo/v2 |
| Rust | name | serde |
| Ruby | name | rails |
Package names are normalized to lowercase. Requests and requests resolve to the same cache entry.
~/.cache/dotdeps/<ecosystem>/<package>/<version>/
Package paths are preserved as nested directories:
~/.cache/dotdeps/node/@org/pkg/4.17.21/
~/.cache/dotdeps/go/github.com/org/repo/v2/1.0.0/
Versions are stored without v prefix. Tag resolution handles prefix at clone time.
Tag: v2.31.0 → Cache: ~/.cache/dotdeps/python/requests/2.31.0/
Pre-release versions are stored as-is: 1.0.0-beta.1
.deps/<ecosystem>/<package> → ~/.cache/dotdeps/<ecosystem>/<package>/<version>
Symlinks use absolute paths. Created in current working directory.
~/.config/dotdeps/config.json
{
"cache_limit_gb": 5,
"overrides": {
"python": {
"some-obscure-lib": {
"repo": "https://github.com/someone/some-obscure-lib"
}
}
}
}LRU by filesystem atime. Default cap: 5GB.
Priority order for implementation:
| Ecosystem | Lockfile priority | Registry |
|---|---|---|
| Node.js | pnpm-lock.yaml > yarn.lock > package-lock.json | npm |
| Python | poetry.lock > uv.lock > requirements.txt > pyproject.toml | PyPI |
| Go | go.sum | Go module proxy |
| Rust | Cargo.lock | crates.io |
| Ruby | Gemfile.lock | RubyGems |
When multiple lockfiles exist, first match in priority order wins.
Best-effort. Each registry has metadata fields for repository URL:
- npm:
repositoryfield - PyPI:
project_urls - crates.io:
repository - RubyGems:
source_code_uri - Go: module path often is the repo
When detection fails, fall back to global config overrides.
Shallow clone (--depth 1) by default. LLMs read current code, not history.
Try in order:
v{version}(e.g.,v2.31.0){version}(e.g.,2.31.0)- Default branch (warn user)
Uses system git config. SSH keys, credential helpers, and .netrc work automatically. No built-in auth handling.
Dependencies specified as local paths (file:../local-pkg) are skipped silently. Already local; nothing to fetch.
Dependencies specified as git URLs (git+https://...) in lockfiles:
- Clone from the git URL directly
- Use commit hash as version in cache path
- Checkout the specific commit
~/.cache/dotdeps/python/some-git-dep/a1b2c3d4/
- Verify cache directory is writable (fail fast if not)
- Parse ecosystem, package, version from argument
- Normalize package name to lowercase
- If version omitted:
- Find nearest lockfile by walking up from cwd
- If no lockfile found, error with prompt for explicit version
- Look up version in lockfile
- If local path dep, skip silently
- If git dep, extract URL and commit hash
- Normalize version (strip
vprefix if present) - Check cache for existing clone
- If missing:
- Detect repo URL (or use override, or use git URL for git deps)
- Shallow clone at matching tag/commit
- On clone failure, delete partial directory and error
- Create/overwrite symlink in
.deps/(cwd) - If broken symlinks exist for same package, remove them
- Evict cache entries if over limit
- Remove symlink from
.deps/ - Do not delete from cache (other projects may use it)
- Leave
.deps/directory even if empty
- List current
.deps/symlinks with versions - Warn on any broken symlinks (cache evicted)
- Remove
.deps/directory in cwd
| Failure | Behavior |
|---|---|
| Cache not writable | Error: "Cannot write to ~/.cache/dotdeps. Check permissions." |
| Version not in lockfile | Error: "Version not found. Specify explicitly: dotdeps add python:foo@1.0.0" |
| No lockfile found | Error: "No lockfile found. Specify version explicitly." |
| Lockfile parse error | Error: "Failed to parse {file}:{line}: {details}" |
| Repo URL not found | Error: "Repository not found. Add override to ~/.config/dotdeps/config.json" |
| Tag not found | Warn, fall back to default branch |
| Clone fails | Delete partial directory, error with git message |
| Network error mid-clone | Delete partial directory, error |
| Disk full | Error: "Disk full. Free space or reduce cache_limit_gb." |
Symlinks work normally.
Symlinks require admin privileges. Detect Windows and copy files instead of symlinking. Document that Windows uses copies (more disk, but functional).
No explicit protection. Concurrent dotdeps add may result in redundant clones but no corruption. Acceptable tradeoff for simplicity.
Inherit from parent directory. No special handling.
Not managed by dotdeps. User's responsibility to add .deps/ to .gitignore if desired.
Provide Claude Code skills that teach:
- When encountering unfamiliar API, run
dotdeps add <ecosystem>:<package> - Browse
.deps/<ecosystem>/<package>to understand implementation - Remove when no longer needed
$ cd my-project
$ dotdeps add python:requests
Fetching requests 2.31.0... ok
Created .deps/python/requests
$ dotdeps add python:requests@2.32.0
Fetching requests 2.32.0... ok
Updated .deps/python/requests
$ dotdeps add python:obscure-lib
Error: Repository not found for obscure-lib
Add override to ~/.config/dotdeps/config.json
$ dotdeps list
python:requests@2.32.0
$ tree .deps
.deps/
python/
requests -> /home/user/.cache/dotdeps/python/requests/2.32.0
.deps/created in cwd (where command is run)- Version lookup walks up from cwd to find nearest lockfile
- Different subdirectories can have different
.deps/if desired