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:
- 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/.
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).
- Write each
files[path] entry to <skills-dir>/<name>/<path>, preserving the directory structure.
- 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
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.
Background
Ornn is rolling out a public-skill mirror to
ChronoAIProject/ornn-skillson 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 skillsworks bygit cloneand 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
nyxidso the agent UX stays "one command, one skill installed."Goal
Ship
nyxid skill install <name>(and minimallylist/remove/updatefor symmetry withnpx 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 asnpx skills, but riding NyxID identity.Scope
Subcommand:
nyxid skill install <name>Internally:
~/.claude/skills/, Codex CLI →~/.codex/skills/(where applicable), Cursor → workspace.cursor/rules/, project-local fallback./skills/.nyxid proxy request ornn-api /api/v1/skills/<name>/jsonto fetch the canonical payload{ name, description, metadata, files: { "SKILL.md": "...", "references/...": "...", "scripts/...": "..." } }(this endpoint already exists; tracked in ornn-agent-manual-cli §1).files[path]entry to<skills-dir>/<name>/<path>, preserving the directory structure.~/.ornn/installed-skills.jsonper the agent-manual contract:{ name, ornnGuid, installedVersion, installedAt, localPath }. If the skill is already in the registry, bumpinstalledVersion+installedAtin 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 entrynyxid skill check/update <name>— compareinstalledVersionagainst Ornn's latest; pull if newernyxid skill find <query>— proxy to Ornn's/api/v1/skill-searchwith the caller's identity, so private / shared skills the user has access to also surfaceOut of scope for this issue
nyxid skill create / publish) — keep that on the agent manual + Ornn web UI for nownyxid skill install ornn-org/<org-id>to pull every skill shared with my org) — useful, but defer until basic install landsWhy 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:nyxid loginsessionornnbinary to add)nyxid proxy requestWhen Ornn eventually ships its own CLI,
nyxid skill *andornn 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
nyxid proxy request <service> <path>plumbing — it's the same call, just wrapped with file writes--target ~/.claude/skills) for cases where probing failsnyxidalready handles this for the config dirSKILL_NOT_FOUND→ "skill 'X' doesn't exist or you don't have access. Trynyxid skill find X.";AUTH_MISSING→ "session expired, runnyxid login."Acceptance criteria
nyxid skill install <public-skill-name>works against a freshnyxid loginsession 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 directsharedWithUsersgrant — 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.jsonis created if missing and updated idempotently on repeat installs of the same skill (bumps version + timestamp, no duplicates).list/remove/updatecommands round-trip cleanly: install → list shows it → update bumps to latest → remove deletes the local copy and the registry entry.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:npx skills add ChronoAIProject/ornn-skills/<name>(anonymous, GitHub-cloned)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.