> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nika.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Builtins catalog

> The canonical stdlib: engine-native nika:* tools across 5 categories, all reached through the invoke: verb.

export const CANON = {
  schemaVersion: 1,
  verbs: 4,
  verbNames: ["infer", "exec", "invoke", "agent"],
  namespaces: 5,
  namespaceNames: ["vars", "with", "tasks", "env", "secrets"],
  builtins: 23,
  builtinNames: ["assert", "compose", "convert", "date", "done", "edit", "emit", "fetch", "glob", "grep", "hash", "inspect", "jq", "json_diff", "json_merge_patch", "log", "notify", "prompt", "read", "uuid", "validate", "wait", "write"],
  providers: 14,
  providersCloud: 8,
  providersLocal: 5,
  providersTest: 1,
  providerIdsCloud: ["mistral", "anthropic", "openai", "gemini", "deepseek", "xai", "groq", "openrouter"],
  providerIdsLocal: ["ollama", "lmstudio", "llamacpp", "localai", "vllm"],
  providerIdsTest: ["mock"],
  extractModes: 9,
  extractModeNames: ["article", "feed", "jq", "links", "markdown", "metadata", "selector", "sitemap", "text"],
  errorNamespaces: 14,
  errorNamespaceNames: ["NIKA-AGENT", "NIKA-BUILTIN", "NIKA-CANCEL", "NIKA-DAG", "NIKA-EXEC", "NIKA-IMPL", "NIKA-INFER", "NIKA-INVOKE", "NIKA-MCP", "NIKA-PARSE", "NIKA-PROVIDER", "NIKA-SEC", "NIKA-TIMEOUT", "NIKA-VAR"],
  errorCategories: 12,
  errorCodes: 50,
  pillars: 5
};

export const STATUS = {
  head: "95962d5cd",
  branch: "main",
  version: "0.91.0",
  cratesWorkspace: 39,
  cratesAdmitted: 39,
  cratesTarget: "42",
  wipCrates: [],
  libTests: 2989,
  clippyWarnings: 0,
  adrs: 62,
  adrsAccepted: 42,
  adrsProposed: 18,
  providers: 32,
  capabilityRules: 49,
  hygieneVectors: 38,
  hygieneGreen: 28,
  hygieneYellow: 3,
  hygieneRed: 0,
  lastUpdated: "2026-06-25"
};

The language stays {CANON.verbs} verbs. Everything else is a tool — and the
standard library ships **{CANON.builtins} builtins** under the `nika:*`
namespace, engine-native (no MCP round-trip, no subprocess), all invoked
the same way:

```yaml theme={"system"}
- id: read_config
  invoke:
    tool: "nika:read"
    args: { path: "./config.yaml" }
```

<Info>
  **Canonical source:** [`nika-spec/stdlib/builtins-v0.1.md`](https://github.com/supernovae-st/nika-spec/blob/main/stdlib/builtins-v0.1.md) —
  the Apache-2.0 language spec. The set was curated by the Rams
  "less but better" sweep (ADR-086/087/088): one super-powerful builtin
  with mode args beats five single-purpose ones.
</Info>

## Overview

<CardGroup cols={3}>
  <Card title="Builtins" icon="toolbox">
    **{CANON.builtins}** tools · 5 categories
  </Card>

  <Card title="Extract modes" icon="filter">
    **{CANON.extractModes}** on `nika:fetch`
  </Card>

  <Card title="Namespace" icon="tag">
    `nika:*` · engine-native
  </Card>
</CardGroup>

## Core (6)

The workflow-control family: speak, signal, guard, ask, finish, pause.

| Builtin       | What it does                                                                                                        |
| ------------- | ------------------------------------------------------------------------------------------------------------------- |
| `nika:log`    | Emit a log entry (`debug`/`info`/`warn`/`error`) to the event stream — human-readable diagnostic.                   |
| `nika:emit`   | Emit a custom machine event (consumed by subscribers and the journal). `log` is for humans, `emit` is for machines. |
| `nika:assert` | Fail the task if a CEL `${{ }}` condition is false — the fail-fast guard (`when:` is the skip-guard).               |
| `nika:prompt` | Interactive human confirm — blocks until answered; engines may use `default` in CI.                                 |
| `nika:done`   | Mark the current `agent:` loop complete and exit — valid only inside an agent tool whitelist.                       |
| `nika:wait`   | Temporal pause — relative `duration:` XOR absolute `until:` (ISO 8601), validated at parse time.                    |

```yaml theme={"system"}
- id: gate
  invoke:
    tool: "nika:assert"
    args:
      condition: "${{ tasks.fetch_data.output.count > 0 }}"
      message: "Expected non-empty result"
```

## File (5)

| Builtin      | What it does                                                               |
| ------------ | -------------------------------------------------------------------------- |
| `nika:read`  | Read a file — returns string content.                                      |
| `nika:write` | Write a file — returns the path; binary upstream values are written as-is. |
| `nika:edit`  | In-place find/replace — returns the modified path.                         |
| `nika:glob`  | Glob match — returns an array of paths.                                    |
| `nika:grep`  | Recursive grep — returns an array of `{ path, line, match }`.              |

## Data (8)

`jq` is THE data language — map, filter, reshape, merge. The other seven
cover what jq genuinely cannot do: diff, validate, delete-on-null merge,
format conversion, generation, time, hashing.

| Builtin                 | What it does                                                                                                            |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `nika:jq`               | Run a jq expression — the single transform-and-extraction language, same jq as `output:` bindings.                      |
| `nika:json_diff`        | JSON diff — returns RFC 6902 JSON Patch (jq can't diff).                                                                |
| `nika:validate`         | Validate data against a JSON Schema — `format: json \| yaml`, returns `{ valid, errors }`.                              |
| `nika:json_merge_patch` | RFC 7396 merge patch — `null` deletes a key, the semantics jq's `*` merge does not provide.                             |
| `nika:convert`          | Universal format converter — `json` · `yaml` · `toml` · `csv`, `from:`/`to:` mode args.                                 |
| `nika:uuid`             | Generate a UUID — `v7` default (timestamped/sortable, RFC 9562) or `v4`.                                                |
| `nika:date`             | Timestamp arithmetic — op-discriminated (`now`/`add`/`subtract`/`format`/`parse`/`diff`), timezone-aware, ISO 8601 out. |
| `nika:hash`             | Content hashing — default blake3, or `sha256`/`sha512`; md5/sha1 are not supported.                                     |

```yaml theme={"system"}
# recursive deep-merge of two task outputs — pure jq, no extra builtin
- id: merged
  invoke:
    tool: "nika:jq"
    args:
      input: ["${{ tasks.base.output }}", "${{ tasks.overlay.output }}"]
      expression: ".[0] * .[1]"
```

## Network (2)

| Builtin       | What it does                                                                                                                                                                                                      |
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `nika:fetch`  | HTTP request + content extraction — {CANON.extractModes} extract modes (`article`, `markdown`, `links`, `feed`, `sitemap`, `selector`, `text`, `metadata`, `jq`). Fetching a URL is *calling a tool*, not a verb. |
| `nika:notify` | Send notifications — `channel:` enum (`webhook`/`slack`/`email`/`discord`/`sms`), one builtin not five.                                                                                                           |

<Warning>
  Engines MUST ship SSRF defense on `nika:fetch`: private-network and
  cloud-metadata targets are rejected unless explicitly configured, and
  self-signed TLS is rejected by default.
</Warning>

## Introspection (1)

| Builtin        | What it does                                                                                                                                                                                                 |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `nika:inspect` | Workflow introspection — one builtin, four `view:` modes: `cost` (running USD by task/provider), `records` (full execution record), `dag_info` (nodes/edges/waves), `threads` (engine pool state, advisory). |

```yaml theme={"system"}
- id: budget_check
  invoke:
    tool: "nika:inspect"
    args: { view: cost }
```

## Design rules the set obeys

* **One super-powerful builtin, multi-mode args** — `fetch`+extract,
  `jq`, `convert`, `wait`, `date`, `inspect` all follow the same pattern.
  No per-direction or per-shape builtin slots.
* **jq subsumes** — anything that is a pure JSON transform is a jq
  expression, not a builtin. A builtin earns its slot only by doing what
  jq cannot.
* **Additive forever** — new builtins may join in stdlib v0.x; existing
  arg shapes never break (the language envelope `nika: v1` is frozen).

## See also

<CardGroup cols={2}>
  <Card title="Full stdlib spec" icon="book-open" href="https://github.com/supernovae-st/nika-spec/blob/main/stdlib/builtins-v0.1.md">
    Per-builtin args, error codes (`NIKA-BUILTIN-*`), trust classes, and
    what jq subsumed out of v0.1.
  </Card>

  <Card title="Verbs" icon="code" href="/concepts/verbs">
    How `invoke:` dispatches `nika:*` builtins vs MCP tools.
  </Card>

  <Card title="MCP catalog" icon="plug" href="/reference/mcp-catalog">
    External tools — the MCP server registry Nika knows by id.
  </Card>

  <Card title="Bindings" icon="link" href="/concepts/bindings">
    Templating that pipes output from one `invoke:` to the next.
  </Card>
</CardGroup>
