Develop
Adapter Toolkit
NILScript is an open standard, not a framework. You get JSON schemas, a CLI, a typed Python SDK, and the ability to build a conformant adapter in any language — proven by an independent ERPNext adapter built from the public docs alone.
The toolkit
| Package | Install | What’s inside |
|---|---|---|
| Core + CLI | pip install nilscript | JSON schemas, docs, and the nilscript CLI — zero deps |
| SDK | pip install "nilscript[sdk]" | Typed Python client (httpx + pydantic) |
| JS / TS | npm install nilscript | The spec + JSON Schemas |
Explore with the CLI
Three commands explore the standard — no account, key, or waitlist.
pip install nilscript
nilscript verbs # list every standard verb
nilscript profile commerce.process_refund # one verb's full contract
nilscript export-openapi > nil.json # OpenAPI 3.1 for the six endpointsA round-trip with the SDK
The safety model is visible in one PROPOSE → COMMIT round trip: propose with no side effects, read the preview and tier, commit with an idempotency key. Refusals are 200 OK outcomes, not exceptions.
from nilscript.sdk import Client
client = Client(base_url="https://shop.example.com/nil", grant=GRANT_TOKEN)
# 1. PROPOSE — no side effects. Server validates, resolves, prices.
proposal = client.propose(
verb="commerce.process_refund",
args={
"refund_target": {"type": "payment", "id": "pay_8812"},
"amount": {"value": "49.00", "currency": "USD"},
"reason": "customer_request",
},
)
# Handle refusals as data, not exceptions.
if proposal.outcome == "AMBIGUOUS":
pick = choose(proposal.candidates)
proposal = client.propose(..., disambiguate=pick.id)
if proposal.outcome == "PROPOSAL":
print(proposal.preview, proposal.tier)
# 2. COMMIT — idempotent. Same token replays the outcome.
result = client.commit(proposal.commit_token, idempotency_key="refund-8812")Scaffold from OpenAPI
export-openapi emits an OpenAPI 3.1 document for the six endpoints. Feed it to any generator and you have endpoint stubs; fill in the translation layer.
nilscript export-openapi > nil.json
# TypeScript server stubs
npx openapi-typescript-codegen --input nil.json --output ./nil-server
# Go server stubs
oapi-codegen -generate types,server nil.json > nil_server.gen.goBuild an SDK in any language
The core package is JSON schemas plus docs with zero runtime dependencies. Generate models from the schemas, wrap an HTTP client, and match the Python SDK’s surface — propose, commit, query, status, plus refusal handling as data.
The ERPNext proof
An independent developer built a conformant ERPNext adapter from the public standard and CLI alone — no privileged knowledge, no insider access. It is a stateless FastAPI shim that proves the published standard is sufficient on its own.
A reusable three-layer structure
| Layer | File | Role | Reusable? |
|---|---|---|---|
| NIL edge | shim.py | Endpoints, envelopes, auth, idempotency, EVENT emission | Generic across any backend |
| Translation core | translate.py | Maps NIL verbs → ERPNext DocTypes, builds previews | The one backend-specific file |
| System client | erpnext.py | Frappe REST client + in-memory test double | Swappable protocol |
shim.py as-is, rewrite translate.py, and implement the client protocol — the same recipe builds adapters for Odoo, SAP, or NetSuite.