Skip to content

Architecture

commands / flows (presentation)
core (policy: upload resolution, versioning, auth resolution)
├── packaging (tar, atomic swap, provenance, registry lookup)
├── features (agent table, loaders, install engine, manifests)
└── api (registrar client, auth ladder)
utils

Dependencies point strictly downward; core never imports from the CLI layer, and interactive flows are pure presentation with injected callbacks.

Every supported agent is one row in a declarative table: its directory, instructions filename, MCP emitter, capabilities, and support tier (supported / experimental). Adding an agent means adding a row plus tests — no conditionals in shared code. Help text and the agent matrix derive from the table.

A skillset in ~/.nori/profiles/ is the source; activation translates it through per-agent loaders (instructions, skills, subagents, slash commands, MCP) into the agent’s directory, marks it with .nori-managed, and records SHA-256 manifests per (agent, directory) for local-change detection. Non-destructive invariants: settings files merge rather than clobber, external files get .pre-nori backups, updates swap atomically, downloads verify checksums.

The registrar API is npm-shaped: packuments, dist-tags, tarballs. Auth resolves through a strict ladder — NORI_API_TOKEN env, config API token, unexpired Firebase ID token, refresh-token exchange, legacy password — and org-scoped tokens are never sent cross-registry.

Node 22, Commander, vitest (colocated tests), eslint + prettier + tsc. The repo’s AGENTS.md carries a test-enforced “How to Close the Loop” section — every change class has a concrete end-to-end verification path. Releases are CI-only via npm trusted publishing (skillsets-v* tags → latest; main → @next).

this page as markdown: /skillsets/develop/architecture.md· index for agents: /llms.txt