Skip to content

The Declarative Contract

Everything Nanokit does starts from a single file: nanokit.yml. It is not a template or a script generator — it is the complete description of desired state, and the only thing an agent (or a human) needs to write to change infrastructure.

yaml
name: nanokit
activeEnv: local

env:
  SMTP_HOST: '${SMTP_HOST:-service://mail}'

databases:
  nk_db_postgres:
    engine: postgres
    mode: local
    rootPassword: '${DB_PASSWORD_POSTGRES}'
    branching:
      enabled: true

services:
  api-gateway:
    runtime: node
    path: ./apps/api-gateway
    start: npm run start
    expose: 4000
    updateStrategy: recreate
  docs:
    runtime: static
    path: ./dist/apps/docs
    expose: 80

Three things in that example matter to an agent:

  • References, not values. ${DB_PASSWORD_POSTGRES} and service://mail resolve at apply time — from the environment or the secrets vault. Secrets never enter the file, so an agent can write config without ever handling credentials.
  • Declarations, not steps. There is no "restart after env change" instruction. The reconciler derives what must happen from the difference between this file and reality.
  • One file, many targets. environments override slices of this document per context; deploy targets decide where a context lands. Same contract, laptop or cloud.

From file to outcome

When the config changes (or nkapp up / nkapp plan runs), Nanokit executes a deterministic loop:

  1. Observe — query the active provider for current state.
  2. Diff — compare desired vs. current, gated by drift hashes so unchanged resources are provably skipped.
  3. Plan — produce a typed plan of CREATE / UPDATE / DELETE / NO_OP actions, ordered by the dependency graph.
  4. Execute proportionally — touch only what the diff justifies; health checks gate each step.
  5. Report — expose resulting state (see Machine-Readable State).

The properties an agent can rely on:

PropertyGuarantee
DeterminismSame config + same current state ⇒ same plan, every time
IdempotenceRe-applying is a no-op when drift hashes match
ProportionalityA one-service change produces a one-service deploy
Reversibilitynkapp deploy --rollback restores the previous reconciler state
Constrained scopeOnly what the schema expresses is executable

What this means in practice

An agent that needs "a staging environment with Redis" does not run twelve commands. It edits the contract — add the database block, maybe an environment override — and lets reconcile do the rest. If the edit was wrong, the plan shows it before execution; if the apply fails midway, rollback returns to the last good state rather than leaving a half-built stack.

The full schema (services, databases, runtimes, networks, cron, volumes, infra providers) is documented under Configuration.

Direction

Explicit agent-facing primitives on top of this contract — such as create_environment operations exposed through an MCP server or tool API — are planned but not shipped. Today, editing nanokit.yml and invoking the CLI is the integration surface.