Skip to content

feat(cli): agent integration — norbix ai init, agent contract + recipe docs, fast startup - #28

Merged
Domantas merged 18 commits into
mainfrom
feat/agent-native-cli-3
Oct 4, 2026
Merged

Domantas merged 18 commits into
mainfrom
feat/agent-native-cli-3

Conversation

@Domantas

@Domantas Domantas commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

PR 3 of 3 for "Agent-native CLI" (docs/tasks/agent-native-cli.md). Stacked on #27 (feat/agent-native-cli-2), which stacks on #26 — the base of this PR is the PR 2 branch, so the diff shows only this PR's work; merge #26, then #27, then this one (retarget as each lands).

What changed

  • norbix ai init (src/commands/ai/init.ts, src/lib/agent-files.ts): writes into the current project (or --dir) a Claude Code skill at .claude/skills/norbix/SKILL.md plus a ~10-line block in CLAUDE.md (--target claude, the default); the same block in AGENTS.md (--target agents); a Cursor rule .cursor/rules/norbix.mdc (--target cursor); or --target all. --dry-run lists what it would write. An existing file is never overwritten and an existing block never duplicated without --force, which rewrites the file / replaces the block in place between its markers. The files are short on purpose: norbix schema --json and --help stay the source of truth.
  • docs/agent-contract.md: the eight rules, the exit-code table, the JSON error envelope, what a dry run prints, which commands confirm / dry-run, and which src/lib files the MCP server can share. norbix schema --json names it.
  • docs/AGENTS.md: the recipe an agent follows — auth without a terminal (profile or NORBIX_*), always --json, discover with schema / --help / hub <module> --json, change in two steps (--dry-run then --yes), branch on exit codes, norbix ai init.
  • README: "Use with Claude Code / AI agents" section; schema and ai init in the command table.
  • Startup: bin/run.js answers norbix --version from package.json without loading oclif — 0.17 s → 0.03 s on an idle machine (0.5–3.2 s → 0.03 s under the load this was built on). npm run build now ends with oclif manifest, so dev runs and tests use the manifest instead of scanning dist/commands (users delete --help 0.18 s → 0.12 s). Choice: the manifest stays gitignored and postpack still removes it — a committed manifest goes stale with every flag change. @inquirer/prompts was already lazy after feat(cli): agent contract — exit codes, error envelope, confirmation without a terminal, dry run #26.

Tests

tests/ai-init.test.ts: --dry-run lists files and writes nothing; a run writes the skill and the block; a second run without --force refuses with exit 2; an existing CLAUDE.md is appended to, not rewritten; --force replaces the block in place; --target all; the --version string. 199 tests green; the §6 harness is unchanged except time --version = 0.038 s.

Open question (not blocking)

Where should docs/AGENTS.md live for the hub/portal docs team? Recommended default: publish it unchanged under the CLI docs and keep the repo copy as the source.

🤖 Generated with Claude Code

Domantas and others added 17 commits October 2, 2026 12:36
…without a terminal, dry run

Plan step [1] of docs/tasks/agent-native-cli.md.

- src/lib/exit-codes.ts: the documented exit-code table (0–9), identical
  with and without --json. No oclif import, so the MCP server can share it.
- src/lib/cli-error.ts: CliError + toEnvelope, one shape for every failure
  (SDK errors, parser errors, JSON input, prompts, bugs): code, message,
  status, exit, fieldErrors, url, traceId, hint, docs. No oclif import.
- BaseCommand.catch prints the envelope (stdout with --json, stderr as text)
  and exits with the documented code; oclif's own JSON error path (22k-line
  parse-context dump) never runs. Unknown commands go through a
  command_not_found hook and get the same envelope.
- confirmOrFail: destructive commands (delete, stop, regenerate, block,
  disable, --many updates) ask in a terminal; without a terminal and without
  --yes they exit 3 and send nothing; "no" at the prompt exits 9. The old
  `isTTY` check let `norbix users delete x </dev/null` (or `| tee`) delete
  silently.
- --dry-run on destructive commands: the SDK builds the request with the
  real auth/region/project and a transport middleware stops it before fetch;
  the SDK call and the HTTP request are printed, exit 0.
- login / configure: every prompt is guarded; a non-interactive shell gets
  exit 2 with the flag-based alternatives instead of a stack trace.
- hub/api: --yes / --dry-run are oclif flags now; context is resolved before
  the confirmation or the dry run.
- No ANSI codes with --json, NO_COLOR or a pipe (init hook).
- README: "Errors and exit codes".

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ive sweep

Plan step [1] of docs/tasks/agent-native-cli.md.

The built CLI runs as a child process (pipes everywhere, like an agent sees
it) against a fake gateway on a free port. Covers: every destructive command
exits 3 without --yes and sends nothing, runs with --yes; --dry-run prints
the call and sends nothing, and still fails on a missing region or key; the
JSON envelope and exit code for 404, 400 with fieldErrors, 401, 500, network,
usage, unknown command, bad JSON input, unknown profile and login without a
terminal — the same exit code with and without --json, stdout one JSON
document, stderr empty; no ANSI codes. Plus unit tests for toEnvelope.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The handover (target behaviour, verified findings, specification, PR order,
reproduction harness, acceptance tests) plus the work log kept while
implementing it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Plan step [2] of docs/tasks/agent-native-cli.md.

- scripts/gen-request-fields.mjs reads the installed @norbix.ai/ts (dist/
  index.js for method → route, dist/types/*.d.ts for the request DTO) and
  writes src/generated/request-fields.json: 578 methods with their fields,
  kinds and required flags. `npm run gen:fields` after an SDK bump; the
  build copies it into dist/.
- `norbix hub <module> --help` lists every method with its fields;
  `--json` returns them as data (words, destructive, http, path, fields).
- Values are typed from the map: a string field keeps "0042", a boolean
  flag no longer swallows the word after it (it goes back to being the id).
  Explicit types win: --field:str / :num / :bool / :json.
- --body '<json>' (or -) passes the whole request; mixing it with --field
  flags is a usage error (exit 2), never a silent merge.
- disable / block count as destructive verbs, like the named commands.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…data

Plan step [2] of docs/tasks/agent-native-cli.md.

Every command with its args, flags (type, env var, default, global),
examples, and two booleans an agent branches on: `destructive` (asks for
confirmation; exit 3 without a terminal unless --yes) and `supportsDryRun`.
Plus the exit-code table, the contract path and how to discover the
dynamic hub/api methods. Without --json: a compact table. The builder in
src/lib/schema.ts has no oclif import so the MCP server can emit the same
document.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Plan step [2] of docs/tasks/agent-native-cli.md.

- Every command that changes something takes --dry-run: SDK calls are
  stopped in the transport (auth, region and project resolved first);
  config set/unset, env use, logout, raw and files publish/unpublish print
  the file or the HTTP request they would write / send. Read-only commands
  get no flag.
- Every example uses real-looking ids; every mutating command shows the
  --dry-run pattern and every destructive one the --yes pattern.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Plan step [2] of docs/tasks/agent-native-cli.md.

- schema: lists every file in dist/commands, booleans present, destructive
  implies dry-run, every mutating command has a --dry-run example and no
  placeholder values, one command / one topic / unknown, snapshot of ids,
  args, flags and markers.
- dispatch: string keeps zeros, number rejects text, boolean gives the next
  token back, explicit types, JSON fields, destructive verbs.
- agent mode: dry run on users invite, files publish (raw hub request),
  config set (file untouched), hub typed fields, --body and its mixing
  error.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Plan step [3] of docs/tasks/agent-native-cli.md.

- bin/run.js answers `norbix --version` from package.json without loading
  oclif: 0.17 s → 0.03 s on an idle machine (0.5–3 s → 0.03 s under load).
- `npm run build` ends with `oclif manifest`, so dev runs and the tests use
  the manifest instead of scanning dist/commands (`users delete --help`
  0.18 s → 0.12 s). The manifest stays gitignored and `postpack` still
  removes it; `prepack` is just the build now.
- `ai` topic for `norbix ai init`.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…her agents

Plan step [3] of docs/tasks/agent-native-cli.md.

Writes into the current project (or --dir): a Claude Code skill at
.claude/skills/norbix/SKILL.md plus a short block in CLAUDE.md (--target
claude, the default); the same block in AGENTS.md (--target agents); a
Cursor rule at .cursor/rules/norbix.mdc (--target cursor); or all three.
The files are short on purpose — `norbix schema --json` and `--help` stay
the source of truth. --dry-run lists what would be written; an existing
file is never overwritten and an existing block never duplicated without
--force, which rewrites the file / replaces the block in place between its
markers.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Plan step [3] of docs/tasks/agent-native-cli.md.

- docs/agent-contract.md: the eight rules, the exit-code table, the JSON
  error envelope, what a dry run prints, which commands confirm / dry-run,
  and which src/lib files the MCP server can share.
- docs/AGENTS.md: the recipe an agent follows — auth without a terminal,
  always --json, discover with schema / --help / hub --json, change in two
  steps (--dry-run then --yes), branch on exit codes, `norbix ai init`.
- README: "Use with Claude Code / AI agents"; schema and ai init in the
  command table.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Each of the three tests spawns the CLI once per destructive command, four
at a time. Windows runners take ~3 s per spawn, so they ran past vitest's
20 s default, and the timed-out pool kept sending requests into the next
test (the --dry-run test then saw DELETE/PUT hits it never made).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…/agent-native-cli-2

# Conflicts:
#	src/commands/raw.ts
… sms, project)

Merging main brought in 115 commands written before the contract. They now
follow it the same way the older commands do:

- destructive ones (delete, disable, revoke-key, cors remove) take
  mutatingFlags and call confirmOrFail — exit 3 without --yes when there is
  no terminal, and --dry-run. The four integration disables and cors remove
  had no confirmation at all.
- every other mutating command takes dryRunFlags and has a --dry-run example.
- examples carry real-looking IDs instead of `66b2f0a1...`.
- ProjectCommand.confirmOrStop is gone (confirmOrFail replaces it), and
  projectClient also returns `reader`: in a dry run the read before a write
  (current origins, current AI settings) goes out live and only the write is
  stopped, so the printed request is the change itself.

Tests: --yes added where the commands now confirm, the destructive ones
added to agent-mode's DESTRUCTIVE list, schema snapshot regenerated (115
entries added, none of the existing ones changed).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…at/agent-native-cli-3

# Conflicts:
#	package.json
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Domantas
Domantas changed the base branch from feat/agent-native-cli-2 to main October 4, 2026 06:12
@Domantas
Domantas merged commit 7e8034a into main Oct 4, 2026
11 checks passed
@Domantas
Domantas deleted the feat/agent-native-cli-3 branch October 4, 2026 06:19
@github-actions

github-actions Bot commented Oct 4, 2026

Copy link
Copy Markdown

🎉 This PR is included in version 1.8.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Domantas added a commit that referenced this pull request Oct 6, 2026
…r env on webhook and log rows

Report for the 2026-10-06 regenerate from gateway refactoringV2 b8fb4152a:
sdk-ts v4.13.0, sdk-net v3.11.0, sdk-go v2.14.0, sdk-swift #25 and
sdk-dart #28 (references only), cloud face90e1. New fields: env on
PaymentsWebhookLogEntry and TenantLogEntryDto.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant