Create a package — all three ways
The three ways to ship a Neuralis package (installed node, project WASM, source markdown) — one PackageDefinition, side by side.
In Neuralis every capability is a package; here are the three reach-paths to
ship one — the PackageDefinition shape is identical across all three, you
only pick where it lives. An installed node package depends on the host and
runs in-process; a project package drops into a project's _packages/ and runs
WASM-sandboxed; a source package is discovered in a synced filesystem source
with no install step at all. Author the same manifest, the same tools/*.json,
the same skills/<name>/SKILL.md — the platform routes it differently based on
the path it arrived through.
The parity matrix
installed node @scope/* | project _packages/ (WASM) | source markdown | |
|---|---|---|---|
| Install | admin: pnpm neuralis:pkg add + rebuild → node_modules/<name> (any scope) | drop a folder in _packages/ | none — discovered in a synced source |
| Discovery | deps-scan (the neuralis block) | ProjectPackageScanner | source vector-index |
| Trust | first-party (host-assigned) | untrusted → trusted | inherits the source trust |
| Runtime code | in-process node | WASM sandbox (neuralis-build generates dispatch) | none — context-only |
| Tools + handlers | ✅ | ✅ generated dispatch | ❌ |
| Routes | ✅ direct | ✅ host-gated (dist/routes.json) | ❌ |
| UI | direct React (a prebuilt module built with neuralis-build ui) | iframe only | ❌ |
| State | live | stateless (lazy-init, ctx.data) | ❌ |
| Hooks | callback executes; script / http are declared but have no executor | declared only — nothing fires today | ❌ |
| skills / rules / instructions / agents / docs | ✅ | ✅ | ✅ (whole surface) |
The PackageDefinition is the same in every column: the same neuralis
manifest block, the same five file categories, the same schema-first tools. What
changes is how the host treats the package once it finds it — whether its
runtime code runs in-process or sandboxed, whether its UI renders directly or in
an iframe, and which contributions it is allowed to carry.
The 3 irreducible differences
Between an installed node package and a project WASM package, only three things genuinely differ — everything else is the same contract:
- UI: direct React vs iframe. A first-party package renders its widgets and
cards as React components running in the workspace itself — shipped as a
prebuilt UI module (
app.module) the host attaches at runtime; a project package's UI loads in a sandboxed iframe instead, isolated from the host runtime. - State: live vs stateless. A node package holds live in-process state for
the instance's lifetime; a WASM package is stateless across calls — its
init(ctx)runs lazily once and durable state persists through the data dir (ctx.data), which the brain sync path chunks, embeds, and makes revertible. - Hooks: in-process callbacks vs nothing that fires. All three handler
kinds (
callback,script,http) are declared inhooks.jsonand validated at load, but onlycallback— an in-process function a node package registers — actually executes. Ascriptorhttphook loads cleanly and then fails at dispatch with a no executor configured error, so a project package effectively has no working hook path today. Do not build a capability whose only trigger is a hook.
A source package is the simpler case: it carries no code at all. It is context-only — skills, rules, instructions, agents, and docs — so it has no tools, no routes, no UI, no state, and no hooks. It contributes the whole markdown surface and nothing else.
Which layer does this value belong in?
Three stores exist and they are not interchangeable. Pick by what the value is, not by what is convenient to read:
| The value is… | Goes in | Read with |
|---|---|---|
| a secret — an API key, token, or client secret | manifest credentials[] | ctx.credentials.resolveCredential(id, scope) |
| a tunable — a cap, timeout, TTL, interval, threshold, model or URL default | manifest configSettings[] | the injected config provider, read per call |
| boot-critical infrastructure — a database URL, an auth secret, a topology address needed before anything is decryptable | .env | the host, at boot |
Two rules follow from the table and are enforced:
- A secret is never a config key. Config values are admin-visible plaintext and appear in the Config tab. Putting a token there publishes it.
- Declare only what something resolves. A credential row an owner can fill in that no code reads is worse than no row — the operator believes the key is configured while the feature stays dark. The same applies to a config key nothing reads. Drift guards assert declarations and consumers match in both directions.
And one that surprises people: there is no credentialFields on a source
connector, and no credentials map on the factory context. A connector's
secrets are ordinary credentials[] declarations, read through the same
resolver as everything else. One vocabulary, one store.
Start from an example
There is one official example per way a package reaches the platform. Read the one that matches your target — each is published to the package registry and readable element by element, so you can pull a single contract instead of a whole tree:
| Your package will… | Example | Read it |
|---|---|---|
| be admin-installed as an npm dependency | @neuralis/example-builtin | neuralweb read '@neuralis/example-builtin#docs/docs.create-package' |
be dropped into a project's _packages/ | @example/project-package | neuralweb read '@example/project-package#docs/<id>' |
| be markdown in a synced source | @neuralis-examples/example-source | neuralweb read '@neuralis-examples/example-source#skill/<id>' |
Markdown elements (skills, rules, agents, instructions, docs, workflows, team
members) read as plain text — one request, an optional --path for a
multi-file element and an fs-read-style --line-start/--line-end window;
the tarball bundle exists too, but it is the install rail, not the read rail.
Tool, connector, credential and config-setting contracts travel as a JSON
document instead: neuralweb info '<identity>#tool/<id>'. The full picture,
including what the examples do and do not promise, is on
Contract examples; the registry
itself is on the marketplace page.
Where to go for depth
- WASM build — the project-package build pipeline (
neuralis-build, the generated dispatcher,dist/package.wasm, the route manifest): /docs/package-system/wasm-build. - Lifecycle and routes — how loaded packages are dispatched and how feature-gated route handlers work: /docs/package-system/lifecycle + /docs/package-system/routes.
- Source packages — the no-install import path, recognized layouts, per-file control, and the security model: /docs/package-system/source-packages.
- The manifest — the
neuralisblock: identity, runtime, trust,requires, surfaces: /docs/package-system/manifest. - Tools — schema-first tool authoring with the
x-neuralisextension: /docs/package-system/tools.
Skill launcher
A reusable Skill launcher prefills the chat composer without sending and derives visibility from the skills the caller can use.
Building your own first-party package
Develop a Neuralis package in its own repository: administrator-assigned first-party trust, sandboxed alternatives, build requirements and kernel peers.