Skip to content

feat(skills): install skill bundles from a git repository - #1166

Open
addyCooks wants to merge 2 commits into
Nano-Collective:mainfrom
addyCooks:feat/skills-install-from-repo
Open

feat(skills): install skill bundles from a git repository#1166
addyCooks wants to merge 2 commits into
Nano-Collective:mainfrom
addyCooks:feat/skills-install-from-repo

Conversation

@addyCooks

Copy link
Copy Markdown
Contributor

Closes #1163.

Description

Adds nanocoder skills add, the install path for skill bundles described above. Seven files: two new (source/skills/install.ts, source/skills/install.spec.ts), three small edits to existing skills/CLI code, plus docs and a changeset.

The trust prompt as it actually renders:

Skill "pr-reviewer" v0.1.0 by nano-collective
  Reviews pull requests and posts findings.

  from: https://github.com/Nano-Collective/nanocoder-skills
  into: /repo/.nanocoder/skills/pr-reviewer

  Commands: /pr-reviewer:review
  Agent:    reviewer
  Tools (visible only to this skill's agent):
    - gh_pr_diff · shell script · approval: never (runs WITHOUT asking) · read-only
  Event subscriptions (the daemon fires these unattended):
    - file.changed → agent:reviewer · paths src/**

Installing a skill means running its code. Only install skills you trust.
Install this skill? [y/N]

--yes still prints that summary before installing, so an unattended install leaves a record of what it agreed to.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update

Changeset

  • Added a changeset (pnpm changeset) describing this change for the changelog

Testing

Automated Tests

  • New features include passing tests in .spec.ts/tsx files
  • All existing tests pass (pnpm test:all completes successfully)
  • Tests cover both success and error scenarios

Manual Testing

  • Tested with Ollama
  • Tested with OpenRouter
  • Tested with OpenAI-compatible API
  • Tested MCP integration (if applicable)

Checklist

  • If this was for an open issue, I was assigned to it
  • Code follows project style guidelines
  • Self-review completed
  • Documentation updated (if needed)
  • No breaking changes (or clearly documented)
  • Appropriate logging added using structured logging (see CONTRIBUTING.md)

docs/features/skills.md calls a bundle "one shareable artifact", but
there was no install path anywhere in source/skills/ - every skill had
to be hand-authored into .nanocoder/skills/. This adds the fetch half.

`nanocoder skills add <name|owner/repo|git-url|path>` is a CLI fast path
mirroring `nanocoder daemon`: it loads only the installer, no Ink, no
providers, no tool registry.

Installing a skill is arbitrary code execution - a bundle tool is a
shell script, `approval: never` skips confirmation entirely, and a
`subscribe:` block makes the daemon fire it headless. So nothing is
written into the project until the user has seen what that means:

  1. shallow-clone into a temp dir (git is already a hard dependency,
     so no tarball library is needed) and strip .git
  2. reject any bundle containing a symlink - a bundle is markdown and
     YAML, so a symlink is only ever an escape attempt
  3. validate through parseSkillManifest and the /skills check linter
  4. render a trust prompt naming every tool WITH its declared approval
     policy and every subscription with its trigger - names alone don't
     tell you what you are agreeing to
  5. land it through applyPromotion, so collision and --force behave
     exactly like /skills promote

Bare names resolve through a plain skills.json index hosted in a git
repo - no registry service. NANOCODER_SKILLS_INDEX or --index points at
another list, including a local file a team checks into its own repo. An
index entry that promises one name but delivers a bundle declaring
another is refused.

Reuse rather than new machinery: checkSkillBundle gains an optional
bundle-path override (so it can lint a clone that is not in the project
yet) and returns the loaded Skill for the trust prompt; PromotionPlan
gains a `remote` origin.

Tests are hermetic - they clone from local git fixtures in a temp dir
and never touch the network - and cover the adversarial bundles:
symlink escape (staged as a git mode-120000 entry so the fixture works
without symlink privileges), path traversal via --subdir and via the
manifest's include globs, and an index/manifest name mismatch.

Refs Nano-Collective#1163.
Implements issue Nano-Collective#1162 in three phases:

Phase 1 - Resources:
- Add MCPResource types and client methods (listResources, readResource)
- Integrate resources into mention system as @-mentions
- Add RESOURCE placeholder type and formatter

Phase 2 - Prompts:
- Add MCPPrompt types and client methods (listPrompts, getPrompt)
- Register MCP prompts as slash commands (mcp:server:prompt format)
- Integrate into lazy command registry

Phase 3 - Sampling:
- Add sampling capability to MCP client
- Implement setSamplingHandler for server-initiated sampling requests
- Add MCPSamplingRequest/Result types

All phases include comprehensive test coverage.

Resolves Nano-Collective#1162
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:docs Documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Install and share skills (nanocoder skills add)

1 participant