Skip to content

[Feature] nyxid skill install — local install for limited-access Ornn skills via NyxID CLI #613

@chronoai-shining

Description

@chronoai-shining

Background

Ornn is rolling out a public-skill mirror to ChronoAIProject/ornn-skills on GitHub so any user can install public / system skills via the community-standard CLI: npx skills add ChronoAIProject/ornn-skills/<name> (tracked in ChronoAIProject/Ornn).

That mirror does not include limited-access skills — anything that's private or shared with specific users / orgs stays Ornn-side. Reason: npx skills works by git clone and assumes anonymous access; mapping NyxID identity into GitHub collaborator ACLs would require linking every NyxID user to a GitHub username and reflecting ACL changes via the GitHub API in real time. That's a brittle two-system identity dance with poor revocation semantics.

The clean path is to keep the limited-access fetch on Ornn's API (already gated by NyxID's identity proxy and the per-skill ACL list), and expose it through a one-line CLI command in nyxid so the agent UX stays "one command, one skill installed."

Goal

Ship nyxid skill install <name> (and minimally list / remove / update for symmetry with npx skills) so a NyxID user can pull any Ornn skill they have access to — public, system, OR limited — into their local agent skills directory with one command. Same UX shape as npx skills, but riding NyxID identity.

# After `nyxid login`, agent runtime auto-detected:
nyxid skill install my-private-fetcher
# → calls ornn-api /api/v1/skills/my-private-fetcher/json via the NyxID proxy
# → writes the SKILL.md + references/ + scripts/ to ~/.claude/skills/my-private-fetcher/
# → records in ~/.ornn/installed-skills.json so the agent's manual knows it's installed

Scope

Subcommand: nyxid skill install <name>

Internally:

  1. Resolve target agent runtime's skills dir (auto-detect; fallback to flag override): Claude Code → ~/.claude/skills/, Codex CLI → ~/.codex/skills/ (where applicable), Cursor → workspace .cursor/rules/, project-local fallback ./skills/.
  2. nyxid proxy request ornn-api /api/v1/skills/<name>/json to fetch the canonical payload { name, description, metadata, files: { "SKILL.md": "...", "references/...": "...", "scripts/...": "..." } } (this endpoint already exists; tracked in ornn-agent-manual-cli §1).
  3. Write each files[path] entry to <skills-dir>/<name>/<path>, preserving the directory structure.
  4. Append a record to ~/.ornn/installed-skills.json per the agent-manual contract: { name, ornnGuid, installedVersion, installedAt, localPath }. If the skill is already in the registry, bump installedVersion + installedAt in place.

Symmetric operations

  • nyxid skill list — walk ~/.ornn/installed-skills.json, render a table (name + version + last installed at)
  • nyxid skill remove <name> — delete <skills-dir>/<name>/ and remove the registry entry
  • nyxid skill check / update <name> — compare installedVersion against Ornn's latest; pull if newer
  • nyxid skill find <query> — proxy to Ornn's /api/v1/skill-search with the caller's identity, so private / shared skills the user has access to also surface

Out of scope for this issue

  • Authoring / publishing flow (nyxid skill create / publish) — keep that on the agent manual + Ornn web UI for now
  • Multi-skill bulk install (nyxid skill install ornn-org/<org-id> to pull every skill shared with my org) — useful, but defer until basic install lands

Why a NyxID CLI command (not Ornn's CLI)

Ornn doesn't have a CLI today (Phase 2 roadmap). NyxID does, and it already handles the auth + token-refresh lifecycle. Riding nyxid skill * means:

  • Zero new auth surface — reuses the existing nyxid login session
  • One CLI for users to install (no ornn binary to add)
  • Token refresh is already battle-tested in nyxid proxy request

When Ornn eventually ships its own CLI, nyxid skill * and ornn skill * can coexist or one can wrap the other; the API contract (/api/v1/skills/:name/json) doesn't care which CLI is calling it.

Implementation hints

  • Reuse nyxid proxy request <service> <path> plumbing — it's the same call, just wrapped with file writes
  • Agent runtime detection: probe well-known directories at startup; document the override flag (--target ~/.claude/skills) for cases where probing fails
  • Cross-platform: macOS / Linux / Windows path conventions; today's nyxid already handles this for the config dir
  • Error mapping: surface Ornn's error codes into actionable messages — SKILL_NOT_FOUND → "skill 'X' doesn't exist or you don't have access. Try nyxid skill find X."; AUTH_MISSING → "session expired, run nyxid login."

Acceptance criteria

  • nyxid skill install <public-skill-name> works against a fresh nyxid login session and lands the skill in the right directory for the auto-detected agent runtime.
  • nyxid skill install <skill-shared-with-me> works for a skill the caller has via direct sharedWithUsers grant — and rejects with a clear error for a skill the caller cannot see.
  • nyxid skill install <skill-shared-with-my-org> works for any skill shared with an org the caller is admin or member of (uses NyxID's existing org-resolve middleware on the Ornn side, no NyxID-CLI changes needed).
  • ~/.ornn/installed-skills.json is created if missing and updated idempotently on repeat installs of the same skill (bumps version + timestamp, no duplicates).
  • Symmetric list / remove / update commands round-trip cleanly: install → list shows it → update bumps to latest → remove deletes the local copy and the registry entry.
  • All commands exit with sensible non-zero codes on failure and print actionable messages mapping Ornn error codes to user-facing remediation.

Companion

  • ChronoAIProject/Ornn — [Feature] Auto-mirror public + system skills to ChronoAIProject/ornn-skills GitHub repo — the public-skill side of this story. Together they form the unified install UX:

    • Public / system skills → npx skills add ChronoAIProject/ornn-skills/<name> (anonymous, GitHub-cloned)
    • Limited-access skills → nyxid skill install <name> (NyxID-authed, Ornn-fetched)

    Two paths because they reflect two genuinely-different permission models. Each path is one line — no UX regression.

Metadata

Metadata

Labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions