A dependency manager for agent skills — versioned, resolved, and installed for your AI tools.
Installation · Quick Start · Why melon? · How it works · Manifest Reference · Commands · Organization Setup
Melon manages markdown-based packages that AI coding assistants read as context. It resolves dependencies from GitHub, fetches them into a local cache, and places them into your agent's expected directory (e.g. .claude/skills/) so they are available immediately.
📦 Global install
npm install -g @playsthisgame/melon🐹 Go
go install github.com/playsthisgame/melon/cmd/melon@latestRequires Git to be available on your PATH.
1. Initialize a project
melon initThis creates a melon.yaml manifest and the .melon/ cache directory. You'll be prompted for a package name, type, and which AI tools you use.
2. Add a dependency
Edit melon.yaml directly:
dependencies:
github.com/playsthisgame/melon-index/skills/video-to-gif: "^1.0.2"
github.com/anthropics/skills/skills/skill-creator: "main"Dependency names are GitHub paths. You can use:
- A full repo:
github.com/owner/repo - A monorepo subdirectory:
github.com/owner/repo/path/to/skill - A GitHub web URL:
github.com/owner/repo/tree/main/path/to/skill(thetree/<branch>/is stripped automatically)
Versions can be a semver constraint (^1.2.0, ~2.0.0, 1.0.0) or a branch name ("main").
3. Install
melon installMelon resolves each dependency, fetches it via sparse git checkout, writes melon.lock, and places skills into your tool directories.
resolving github.com/playsthisgame/melon-index/skills/video-to-gif (^1.0.2)...
fetching github.com/playsthisgame/melon-index/skills/video-to-gif@1.0.2...
+ github.com/playsthisgame/melon-index/skills/video-to-gif@1.0.2
linked github.com/playsthisgame/melon-index/skills/video-to-gif -> .claude/playsthisgame/video-to-gif
melon.yaml — declares your dependencies and target AI tools ← commit
melon.lock — pins exact versions, git tags, and content hashes ← commit
.melon/ — local cache; one directory per dep@version
.claude/skills/ — symlinks into .melon/ created by melon install
Skills are fetched once into .melon/ and symlinked into the configured tools directories.
By default (vendor: true, the implicit setting), .melon/ and the generated symlinks are committed to your repo, so anyone who clones gets the skills without running melon install. If you prefer to keep deps out of git, set vendor: false in melon.yaml (or opt out during melon init). Melon will automatically maintain a .gitignore block for .melon/ and all managed symlink paths, keeping it in sync as you add or remove dependencies.
# melon.yaml
name: my-agent
version: 0.1.0
description: "My coding agent"
dependencies:
github.com/anthropics/skills/skills/skill-creator: "main"
github.com/playsthisgame/melon-index/skills/video-to-gif: "^1.0.2"
# tool_compat drives where melon install places skills.
# Melon knows the conventions for each agent automatically:
# claude-code -> .claude/skills/
# cursor -> .agents/skills/
# windsurf -> .windsurf/skills/
# roo -> .roo/skills/
# ... (and more)
tool_compat:
- claude-code
# outputs is optional. Use it to override the automatic placement paths.
# outputs:
# .claude/skills/: "*"
# vendor controls whether melon manages .gitignore for its cache and symlinks.
# true (default): .melon/ and skill symlinks are committed to your repo.
# false: melon auto-manages .gitignore; add/remove keeps it in sync.
# vendor: false
# index is optional. Use it to point melon search/info at private registries.
# Melon supports GitHub paths and web URLs:
# - github.com/owner/repo/path/to/index.yaml
# - github.com/owner/repo/tree/main/path/to/index.yaml
# - https://raw.githubusercontent.com/owner/repo/main/path/to/index.yaml
# index:
# urls:
# - github.com/my-company/skill-registry/index.yaml
# - https://example.com/index.yaml
# public_index: true # false = suppress the default public melon index, default is true
# policy is optional. Use it to restrict which sources can be installed.
# Patterns use glob syntax; a trailing * matches any suffix.
# policy:
# allowed_sources:
# - github.com/my-company/* # any repo under this org
# - github.com/trusted-partner/* # another approved org
tags: []| AI tool | Project skills directory |
|---|---|
claude-code |
.claude/skills/ |
cursor |
.agents/skills/ |
windsurf |
.windsurf/skills/ |
roo |
.roo/skills/ |
codex |
.agents/skills/ |
opencode |
.agents/skills/ |
gemini-cli |
.agents/skills/ |
github-copilot |
.agents/skills/ |
cline |
.agents/skills/ |
amp |
.agents/skills/ |
Scaffold a new melon.yaml and create the .melon/ store directory.
melon init
melon init --yes # accept all defaults (for scripting)
melon init --dir ./app # initialize in a different directoryResolve dependencies, fetch them into .melon/, write melon.lock, and symlink skills into tool directories.
melon install
melon install --frozen # fail if melon.lock would change (useful in CI)
melon install --no-place # fetch and lock only; skip placement into agent dirsIf a policy.allowed_sources block is configured in melon.yaml, melon install validates all dependencies against the allowlist before fetching anything. Any blocked dependency causes a non-zero exit listing all violations.
Add a dependency to melon.yaml and run install. If no version is specified, the latest semver tag is resolved automatically.
melon add github.com/playsthisgame/melon-index/skills/video-to-gif # resolves latest tag → ^1.2.0
melon add github.com/playsthisgame/melon-index/skills/video-to-gif@^1.0.0 # explicit constraint
melon add github.com/playsthisgame/melon-index/skills/video-to-gif@main # branch pinIf a policy.allowed_sources block is configured, melon add checks the dependency source before writing to melon.yaml and exits with an error if the source is not permitted.
Remove a dependency from melon.yaml, unlink its agent symlinks, and delete its .melon/ cache entry.
melon remove github.com/playsthisgame/melon-index/skills/video-to-gifUpdate dependencies to the latest version satisfying their existing constraints. Without arguments, shows an interactive multi-select list (TTY only), where the first option updates all deps. With a dep name, targets that dep directly.
melon update # interactive: pick which deps to update
melon update github.com/playsthisgame/melon-index/skills/video-to-gif # update a specific depIf a newer major version exists outside your constraint, a hint is printed showing how to upgrade with melon add.
Show which dependencies have newer versions available, without modifying anything. Exits with code 1 if any dep is outdated, which is useful in CI.
melon outdatedOutput includes current locked version, latest compatible version, and absolute latest (when a newer major exists outside your constraint). Branch-pinned deps are skipped.
Show the content changes between the currently locked version of a dependency and a target version, so you can see exactly what an AI agent's context will change before you run melon update. By default the target is the latest version satisfying the dep's constraint; append @<version> or @<branch> to diff against a specific target.
melon diff github.com/playsthisgame/melon-index/skills/video-to-gif # locked vs. latest compatible
melon diff github.com/playsthisgame/melon-index/skills/video-to-gif --stat # per-file summary only
melon diff github.com/playsthisgame/melon-index/skills/video-to-gif --no-color # disable colored outputChecking against a specific version
Append @<version> to compare your locked version against any published tag. This is useful for previewing a major upgrade that sits outside your current constraint:
melon diff github.com/playsthisgame/melon-index/skills/video-to-gif@2.0.0Checking a branch-pinned dependency against main
When a dependency is pinned to a branch (e.g. main), it's locked to the exact commit SHA you installed. "Latest" is undefined for a moving branch, so melon diff requires an explicit target. Pass the branch name to diff your locked commit against the current branch tip:
melon diff github.com/anthropics/skills/skills/skill-creator@mainIf main has advanced since you installed, you'll see a unified diff of what changed; if it hasn't moved, melon prints No changes.
The target version is fetched into .melon/ if not already cached. That is the only side effect, since melon.yaml and melon.lock are never modified. Added, removed, and changed files are shown as a unified diff; binary files are reported as changed without hunks. If the two versions have identical content, melon prints No changes.
Show installed skills and audit installation state.
melon list # list all installed skills
melon list --pending # show skills in melon.yaml not yet installed
melon list --check # verify skill symlinks exist in all tool directories
melon list --pending --check # combine both checksDefault output:
github.com/anthropics/skills/skills/skill-creator main
github.com/playsthisgame/melon-index/skills/video-to-gif 1.2.0
With --check:
OK github.com/playsthisgame/melon-index/skills/video-to-gif@1.2.0 .claude/skills/video-to-gif
MISSING github.com/anthropics/skills/skills/skill-creator@main .claude/skills/skill-creator
With --pending:
Pending (not installed):
github.com/owner/repo/some-new-skill
Use --json for machine-readable output. Combines with --pending and --check:
melon list --json
melon list --json --pending --check{
"installed": [
{
"name": "github.com/playsthisgame/melon-index/skills/video-to-gif",
"version": "1.2.0",
"git_tag": "v1.2.0",
"repo_url": "https://github.com/playsthisgame/melon-index",
"subdir": "skills/video-to-gif",
"entrypoint": "SKILL.md",
"tree_hash": "abc123..."
}
],
"pending": ["github.com/owner/repo/some-new-skill"],
"check": [
{ "name": "github.com/playsthisgame/melon-index/skills/video-to-gif", "path": ".claude/skills/video-to-gif", "status": "ok" }
]
}Search for skills by keyword against the melon-index curated list. In a terminal, results are shown in an interactive list: navigate with ↑↓, press Enter to select, and melon will offer to run melon add for you.
melon search spec # find spec-related skills
melon search git workflow # find git workflow skillsFeatured skills appear at the top of results. If nothing matches, melon will tell you and suggest submitting to the index.
If your project has an index block in melon.yaml, search queries your custom registry instead of (or in addition to) the public melon index. Set public_index: true to see only your private skills.
Show metadata for a specific skill (description, author, and available versions) before installing it.
melon info github.com/playsthisgame/melon-index/skills/video-to-gif
melon info github.com/owner/repo/path/to/skill
melon info github.com/owner/repo --json # machine-readable outputWith --json:
{
"name": "github.com/owner/repo",
"description": "Does something useful",
"author": "owner",
"latest_version": "v1.2.0",
"versions": ["v1.2.0", "v1.1.0", "v1.0.0"],
"branches": []
}If the repo has no semver tags, versions is [] and branches lists available branches instead.
Remove cached entries in .melon/ that are no longer referenced by melon.lock. Any corresponding symlinks in agent skill directories are removed as well. This reclaims disk space left behind after removing or upgrading dependencies.
melon cleanIf melon.lock does not exist, the command prints a reminder to run melon install first and exits without modifying anything.
melon.lock is generated by melon install and should be committed to version control. It pins the exact version, git tag, repo URL, subdirectory, and a SHA-256 tree hash for each dependency.
generated_at: "2025-03-31T12:00:00Z"
dependencies:
- name: github.com/playsthisgame/melon-index/skills/video-to-gif
version: "1.2.0"
git_tag: v1.2.0
repo_url: https://github.com/playsthisgame/melon-index
subdir: "skills/video-to-gif"
entrypoint: SKILL.md
tree_hash: "sha256:abc123..."
files:
- SKILL.mdUse --frozen in CI to ensure the lock file is always up to date:
melon install --frozenTeams can use melon to control exactly which skills developers are allowed to install and to surface a curated internal registry instead of (or alongside) the public melon index. Two melon.yaml fields work together for this: policy for source restrictions and index for a private skill registry.
Add a policy.allowed_sources block to melon.yaml to define which GitHub organizations or repos may be installed. Patterns use glob syntax; a trailing * matches any suffix:
policy:
allowed_sources:
- github.com/my-company/* # any repo under your org
- github.com/trusted-partner/* # an approved external orgMelon enforces the allowlist on both melon add and melon install:
melon addchecks the source before writing tomelon.yamland exits with an error if the dependency is not permitted, so blocked skills never enter the manifest.melon installvalidates every entry inmelon.yamlagainst the allowlist before fetching anything. Any violation causes a non-zero exit listing all blocked dependencies.
This means a developer cannot accidentally (or intentionally) add an unapproved skill, and CI will catch any attempts that bypass the local check.
Use the index block to point melon search and melon info at your own registry:
index:
urls:
- github.com/my-company/skill-registry/index.yaml
public_index: false # show only internal skills, hide the public melon indexThe index URL can be a GitHub path (github.com/owner/repo/path/to/index.yaml), a GitHub tree URL, or a raw HTTPS URL. With public_index: false, search results and info lookups are scoped to your internal registry, so developers see only the approved, curated list of skills without the noise of the full public index.
Set public_index: true (the default) if you want to layer your private registry on top of the public one, giving developers access to both.
Commit melon.yaml, including the index and policy blocks, to a shared project template or internal scaffolding tool. When a developer initializes a new project from that template they inherit the policy automatically, with no extra setup step.
For monorepos, place the policy in the root melon.yaml so every project in the tree shares the same configuration.
As AI coding assistants become more capable, teams are building and sharing libraries of skills. Without a proper dependency manager, keeping these skills consistent across developers, environments, and CI becomes a manual, error-prone process.
Melon gives you a single source of truth. Define all the skills your project needs in one melon.yaml file, commit it alongside your code, and every developer (and your CI pipeline) gets exactly the same set of skills with a single melon install.
Skills are versioned, not just copied. Melon pins exact versions, git tags, and SHA-256 content hashes in melon.lock. If a skill author publishes a breaking change, your team won't silently pick it up, you'll see the diff in the lock file and upgrade intentionally. This means you can trust that the skill running in CI today is the same one that ran last week.
It works naturally with CI. Run melon install --frozen in your pipeline to fail fast if the lock file is out of sync with the manifest. No surprises, no drift. With the default vendor: true setting, .melon/ and the generated symlinks are committed to the repo so CI doesn't even need network access; everything is already there. If you prefer to keep deps out of git, set vendor: false and CI will fetch them fresh on each run using the pinned versions in melon.lock.
Works across your whole team and all your tools. List the AI tools your project uses under tool_compat and melon places each skill into every agent's expected directory at once. One manifest, one install command, every agent ready to go.
Many agent skill collections ship a one-liner like npx install-skill <name> that copies files into your project. Melon takes a different approach:
| melon | npx installers | |
|---|---|---|
| Reproducibility | melon.lock pins exact versions and content hashes |
Each run may fetch a different version |
| Transitive deps | Resolves the full dependency graph | Usually single-package only |
| Multiple agents | tool_compat places skills for all your tools at once |
Typically one target agent |
| Offline / CI | Already-fetched deps are cached in .melon/ |
Always fetches from the network |
| Node.js required | No, pure Go binary, no runtime needed | Yes |
| Removal | melon remove unlinks symlinks and purges the cache |
Usually manual |