Publish a package by example (x07-package.json → x07.io)
This page is a step-by-step workflow for creating and publishing an X07 package to the public registry.
It is written to keep the story consistent across:
x07(toolchain)- x07lang.org docs
- x07.io (registry UI)
If you just want the reference flags, see Publishing.
Mental model
Two similar-looking JSON files have different jobs:
x07.json— project manifest (apps + local dev). Defines module roots, entrypoint, profiles, dependencies.x07-package.json— package manifest (publish contract). Defines name/version, module root, and which module IDs are included in the artifact.
A package repo will typically contain both:
x07-package.json(publish)x07.json(local tests, demos, CI)
Example package: acme-hello-demo
This tutorial publishes a tiny library module plus a published tests module:
ext.acme_hello_demoext.acme_hello_demo.tests
If you are publishing to the public registry, choose a unique package name (for example, include your org/handle).
Companion example (in the x07 repo):
docs/examples/tutorials/package_publish_acme_hello_demo/
Step 0: create the skeleton (publish-ready)
mkdir acme-hello-demo
cd acme-hello-demo
x07 init --package
This creates a publish-ready repo:
acme-hello-demo/
.gitignore
AGENT.md
x07-toolchain.toml
x07.json
x07.lock.json
x07-package.json
.agent/
docs/
...
skills/
...
modules/
ext/
acme_hello_demo.x07.json
acme_hello_demo/
tests.x07.json
tests/
tests.json
Step 1: library module
x07 init --package generates modules/ext/acme_hello_demo.x07.json:
{
"schema_version": "x07.x07ast@0.4.0",
"kind": "module",
"module_id": "ext.acme_hello_demo",
"imports": [],
"decls": [
{ "kind": "export", "names": ["ext.acme_hello_demo.hello_v1"] },
{
"kind": "defn",
"name": "ext.acme_hello_demo.hello_v1",
"params": [{ "name": "name", "ty": "bytes_view" }],
"result": "bytes",
"body": [
"begin",
["let", "prefix", ["bytes.concat", ["bytes.lit", "hello,"], ["bytes1", 32]]],
["let", "tmp", ["bytes.concat", "prefix", ["view.to_bytes", "name"]]],
["bytes.concat", "tmp", ["bytes1", 10]]
]
}
]
}
Step 2: published tests module (recommended)
x07 init --package also generates modules/ext/acme_hello_demo/tests.x07.json:
{
"schema_version": "x07.x07ast@0.4.0",
"kind": "module",
"module_id": "ext.acme_hello_demo.tests",
"imports": ["ext.acme_hello_demo", "std.test"],
"decls": [
{ "kind": "export", "names": ["ext.acme_hello_demo.tests.test_hello_v1"] },
{
"kind": "defn",
"name": "ext.acme_hello_demo.tests.test_hello_v1",
"params": [],
"result": "result_i32",
"body": [
"begin",
["let", "name", ["bytes.lit", "x07"]],
["let", "got", ["ext.acme_hello_demo.hello_v1", ["bytes.view", "name"]]],
["let", "expected_prefix", ["bytes.concat", ["bytes.lit", "hello,"], ["bytes1", 32]]],
["let", "expected_tmp", ["bytes.concat", "expected_prefix", "name"]],
["let", "expected", ["bytes.concat", "expected_tmp", ["bytes1", 10]]],
["try", ["std.test.assert_bytes_eq", "got", "expected", ["std.test.code_assert_bytes_eq"]]],
["std.test.pass"]
]
}
]
}
Step 3: package manifest (x07-package.json)
x07 init --package generates a registry-compatible x07-package.json. Publishing to the public registry requires
non-empty description and docs.
{
"schema_version": "x07.package@0.1.0",
"name": "acme-hello-demo",
"version": "0.1.0",
"description": "Starter package generated by `x07 init --package`: ext.acme_hello_demo.hello_v1(name) -> bytes.",
"docs": "Starter package generated by `x07 init --package`.\n\nModules:\n- ext.acme_hello_demo\n- ext.acme_hello_demo.tests\n\nUsage:\n- Add: x07 pkg add acme-hello-demo@0.1.0 --sync\n- Import: ext.acme_hello_demo\n- Call: ext.acme_hello_demo.hello_v1\n\nDev:\n- Test: x07 test --manifest tests/tests.json\n- Pack: x07 pkg pack --package . --out dist/acme-hello-demo-0.1.0.x07pkg\n",
"module_root": "modules",
"modules": ["ext.acme_hello_demo", "ext.acme_hello_demo.tests"],
"meta": {
"determinism_tier": "pure",
"worlds_allowed": ["run-os", "run-os-sandboxed"],
"import_mode": "handwritten",
"visibility": "experimental"
}
}
Step 4: tests manifest (tests/tests.json)
x07 init --package generates a CI-friendly tests/tests.json:
{
"schema_version": "x07.tests_manifest@0.1.0",
"tests": [
{ "id": "hello_v1", "world": "run-os", "entry": "ext.acme_hello_demo.tests.test_hello_v1", "expect": "pass" }
]
}
It also generates a minimal x07.json so x07 test can automatically discover module roots:
{
"schema_version": "x07.project@0.2.0",
"world": "run-os",
"entry": "modules/ext/acme_hello_demo/tests.x07.json",
"module_roots": ["modules"],
"lockfile": "x07.lock.json",
"dependencies": []
}
Run tests:
x07 test --manifest tests/tests.json
Step 5: pack locally (optional sanity check)
mkdir -p dist
x07 pkg pack --package . --out dist/acme-hello-demo-0.1.0.x07pkg
Step 6: publish to the official registry
The official index URL is:
sparse+https://registry.x07.io/index/
6.1 Login
Prefer stdin so tokens don’t end up in shell history:
printf '%s' "$X07_TOKEN" | x07 pkg login --index sparse+https://registry.x07.io/index/ --token-stdin
6.2 Publish
x07 pkg publish --index sparse+https://registry.x07.io/index/ --package .
Step 7: consume the package (end-to-end verification)
In a fresh directory:
mkdir -p /tmp/consume-hello && cd /tmp/consume-hello
x07 init
x07 pkg add acme-hello-demo@0.1.0 --sync
Then import ext.acme_hello_demo and call ext.acme_hello_demo.hello_v1.