@nomai/nomai
v0.2.0
Published
Install Nomai skills, hooks, and commands into AI coding harnesses
Downloads
29
Readme
nomai
Installer CLI for Nomai — skills, commands, and hooks for AI coding harnesses (Claude Code first; Codex, Cursor, Gemini CLI, ... later).
npx @nomai/nomai installAn interactive wizard (built on @clack/prompts) signs you in to your Nomai account, detects which harnesses you use, asks whether to install per-project or globally, downloads the Nomai payload from this repo, installs it, and pulls in your Nomai account skills (personal + organization). A SessionStart hook keeps those skills fresh automatically — publish a skill in Nomai and your next Claude Code session has it.
The payload also ships two slash commands that bring Nomai into the session:
/nomai:project <name> loads a project's full context (instructions, roster,
knowledge brain) so the agent starts working already grounded in it, and
/nomai:ask <question> answers from the knowledge brains you have access to,
with sources. Both run this CLI (nomai project / nomai ask) against the
Nomai backend using your paired token.
Commands
| Command | What it does |
| --- | --- |
| npx @nomai/nomai install | Wizard: log in, pick harnesses + scope, install, sync skills |
| npx @nomai/nomai update | Re-apply the latest payload + re-sync skills (never prompts) |
| npx @nomai/nomai sync | Pull your Nomai account skills now (--hook = silent session mode) |
| npx @nomai/nomai status [--json] | Show account, detection/install/drift, synced skills (never prompts) |
| npx @nomai/nomai login | Connect your Nomai account (approve in the browser, paste the code) |
| npx @nomai/nomai logout | Sign out and revoke this machine's token |
| npx @nomai/nomai whoami [--verify] | Show the signed-in account |
| npx @nomai/nomai project <name-or-id> [--json] | Print a Nomai project's full context (record + instructions + agents/teams/collaborators + brain) — what /nomai:project runs |
| npx @nomai/nomai ask <question> [--project <name-or-id>] [--brain <id>] | Ask your Nomai knowledge brains a question (answer + sources; up to ~90s) — what /nomai:ask runs |
| npx @nomai/nomai uninstall | Remove exactly the files Nomai installed (payload + synced skills + hook) |
Useful flags (target commands): --harness <id> (repeatable), --scope project|global,
--dir <path>. Install/update also take --source <path|owner/repo#ref> (payload
override), --dry-run, --force, and -y/--yes for CI. Non-interactive sessions
(pipes, CI, AI agents) exit with code 2 unless --yes is passed — the CLI never
hangs on a prompt. Headless logins: set NOMAI_TOKEN (a personal access token)
or pass --skip-login; point at another deployment with NOMAI_API_URL /
NOMAI_FRONTEND_URL.
How it works
- The npm package is a single bundled
dist/cli.jswith zero runtime dependencies (@clack/prompts,commander, and@vercel/detect-agentare inlined at build time). - The installable payload lives in
payload/in this repo and is downloaded at install time as a GitHub tarball — pushing tomainships payload updates without an npm release. - Every install writes a
nomai-manifest.jsonreceipt (file list + sha256) into the harness config dir. That receipt makes installs idempotent, updates orphan-safe, and uninstalls surgical: Nomai only ever deletes files it wrote, keeps files you modified (unless--force), and never removes the harness dir itself. - Account skills: after login (a personal access token minted via the
Nomai web app's
/clipairing page, stored at~/.nomai/credentials.jsonwith 0600 permissions),syncpulls your personal + organization skills intoskills/<slug>/next to the payload, tracked by a second receipt (nomai-skills-manifest.json) with the same ownership semantics. - Auto-sync: install registers a Claude Code SessionStart hook that runs
node ~/.nomai/bin/nomai.mjs sync --hook(a self-contained copy of this CLI — no npx on session start). Hook mode is silent, throttled to once per 5 minutes, deadlined at 10s, and always exits 0 — offline sessions just start without a refresh. It logs to~/.nomai/logs/sync.log. - The API client under
src/sdk/is generated from the Nomai product's OpenAPI contract (vendored atsdk/openapi.json) viascripts/generate-sdk.sh;src/core/api.tsis the only module that touches it.
Development
npm install
npm run dev -- install --dry-run --source . # run the CLI from source
npm test # vitest
npm run typecheck # tsc --noEmit
npm run build # tsdown → dist/--source . points the installer at your local checkout instead of GitHub.
Without it, the payload comes from
A-MCode/nomai-installer at main
(DEFAULT_SOURCE in src/core/payload.ts).
Adding a harness
Create
src/harnesses/<id>.ts:import { defineHarness } from "./define.js"; export const codex = defineHarness({ id: "codex", displayName: "Codex CLI", configDirName: ".agents", });Register it in
src/harnesses/index.ts(one line).Optionally add
payload/<id>/for harness-specific files.
Defaults cover detection (config dir exists at project/global scope), install
location, and file copying. Override transformPayload for per-harness
compilation, or install/uninstall/status wholesale for harnesses that
need custom mechanics (e.g. merging hooks into a settings.json).
Architecture
src/
├── cli.ts # bin entry: commander program (install/update/status/uninstall)
├── index.ts # public API for programmatic use
├── commands/ # one file per subcommand + shared flag/context helpers
├── wizard/ # the @clack/prompts install wizard (flag-bypassable)
├── core/
│ ├── types.ts # HarnessAdapter contract + all shared types
│ ├── registry.ts # harness lookup
│ ├── detect.ts # which harnesses does this user have?
│ ├── payload.ts # payload sources: GitHub tarball / local path
│ ├── installer.ts # generic engine — the only module that writes to disk
│ └── manifest.ts # install receipts (idempotency, updates, clean uninstall)
├── harnesses/ # defineHarness() factory + one adapter per harness
└── test-utils/ # temp-dir fixtures for tests
payload/ # the installable content (fetched from GitHub, not npm)