Package reference
Local packages are available now. The public package server is undergoing validation and testing and will be available soon.
Touba 1.0.0 supports creating, installing and sharing packages locally. Start with the practical guide. In a consuming project, install the shared directory or archive:
touba package add ./acme.echo-1.0.0.tar.gz
touba package check
Follow the server launch on the roadmap.
Shared host modules
A package can distribute an attestation or decision adapter in hosts.
Each entry has a unique id, a kind and a path:
human_approval or decision_provider, with a JS or Python file.
A host-only package may declare exports: {}.
{
"hosts": [
{ "id": "approval", "kind": "human_approval", "path": "host/approval.mjs" },
{ "id": "decision", "kind": "decision_provider", "path": "host/decision.py" }
],
"files": ["host"]
}
The project enables a module through pkg:organization.package/identifier
in --human-approval-host or --agent-decision-provider.
Touba verifies every installed package's inventory before loading the module.
Include helper files in files; install JS or Python dependencies explicitly
in the application environment. Host modules are trusted application code.
Restart the host after replacing a package that has already been loaded.
Proposed Python handlers use the consuming project's .venv interpreter
when present. Touba prevents bytecode writes during their execution.
For separately launched Python tests, use python -B.
A cache added under packages/ remains an undeclared file: check its origin
and reinstall a validated copy, keeping the approved lock unchanged.
Grants control admission of Touba operations. Configure host-process confinement separately through the sandbox policy.
The single author manifest is touba.package.json, using
touba-package-v1. Contextual procedures and reusable agents share the same
distribution format. Source imports remain typed.
Commands
| Command | Effect |
|---|---|
touba package new | Questionnaire with confirmation before creation |
touba package new "Invoice tools" --org "North Company" --yes | Creates invoice-tools/, identity north-company.invoice-tools |
touba package publish [directory] --registry <directory> | Publish a local static draft, without overwriting or executing package code |
touba package check [directory] | Real validation, no tests executed; --publishing requires sharing metadata |
touba package test [directory] | Explicit declared Node tests; pass extra variables with --env NAME |
touba package version patch | Strictly higher version; also accepts minor, major or an exact version |
touba package pack [directory] | dist/<name>-<version>.tar.gz; optional --output, no overwriting |
touba package add <name|directory|archive> | Locked installation; a bare name selects a manual drop under packages/ |
touba package add org.name@1.0.0 --registry <source> | Exact version from a chosen registry |
touba package list | List and validate registered dependencies |
touba package remove org.name | Remove a dependency not required by another package |
All accept --json and --root. Commands find the root from subdirectories;
for new, --root is the parent of the new directory. With no target, check
validates the author package or an application's registered dependencies.
Exit codes: 0 success, 1 failed/missing tests or cancelled creation, 2
contract/argument error. Check/add/pack never execute third-party tests.
A local organization name proves neither availability nor public ownership.
Manifest fields
| Field | Requirement |
|---|---|
package_schema_version | touba-package-v1 |
name | Qualified lowercase identifier, such as acme.billing |
version | Exact SemVer, such as 1.2.0 |
touba.air_profile | touba-air-json-canonical-v1 |
touba.runtime_compatibility | A checked SemVer range |
exports | Object with optional types, defines, functions, tools, skills, agents, strategies, memories lists |
contexts | Optional contextual procedures |
dependencies | Optional map of package names to exact versions |
files | Included relative files/directories; defaults to src for code |
handlers | Supplied implementations, not effective bindings or grants |
engines | Optional node range and platforms list |
description, publisher, license | Required to prepare the archive with pack |
readme | README included in the archive; required for direct CLI publication. A publication service can accept a separately supplied overview. |
contract_tests | Node .test.mjs, .test.cjs, .test.js files; run only by package test |
root | Optional; must be . |
provenance | Unsigned kind, source, revision metadata |
At least one export or context is required. Every exported reference must
exist. For example, skill:acme.billing/PrepareInvoice is declared in
src/acme/billing.tb. Constants in exports.defines use constant:.
Context
{
"id": "review",
"description": "Review supplied material against explicit criteria.",
"procedure": "SKILL.md",
"activation": { "model_invocable": true, "user_invocable": true },
"resources": [
{ "name": "checklist", "path": "resources/checklist.md", "kind": "reference",
"description": "Acceptance checklist", "loadable_as_context": true }
],
"execution_links": []
}
The Markdown procedure must be nonempty. Resources have unique names, paths,
kinds and descriptions. Kinds: procedure, reference, example,
template, sample, script, fixture. Scripts cannot be loaded or run
as context. Execution links contain label, target_ref and
description; referring to a tool or skill does not authorize it.
Selection: --skill-pack packages/acme.review#review.
Activation: --activate-skill-pack skill_pack:acme.review/review.
Touba derives the internal touba-skill-pack-v1 protocol; authors do not
maintain a second manifest.
Supplied handler
{
"tool": "tool:acme.billing/ReadInvoice",
"path": "handlers/read_invoice.mjs",
"protocol": "touba-tool-handler-v1",
"documentation": "README.md"
}
The tool must be declared. Optional configuration points to a file describing
configuration. The CLI checks its inclusion, not business-service availability.
The consuming project chooses the process binding, grants, secrets, effect
contract and limits.
Validation and diagnostics
touba package check --json preserves source errors as objects in
diagnostics: code, message, severity, source_path and source_ref
when available. Its top-level code is PackageSourceInvalid. Source line
and column indices are zero-based in JSON; terminal locations start at one.
A failed source compilation is reported before export checks, so one source
error does not generate a cascade of missing exports.
Paths are confined and relative. Archive links, special files, traversal and
collisions are refused. Common secret files and node_modules cannot be
distributed. Limits: 4,096 files/entries, 16 MiB per file, 64 MiB of content,
1 MiB per manifest, depth 32, and at most 128 packages per dependency closure.
Installation executes no command supplied by a package.
| Diagnostic | Action |
|---|---|
PackageDependencyMissing | Supply the exact dependency |
PackageDependencyConflict | Resolve conflicting versions or contents |
PackageDependencyCycle | Remove the cycle |
PackageIntegrityMismatch | Compare against the approved package and lock; do not blindly accept changes |
PackageNotInstalled | Validate and register with package add |
PackageRequirementMissing | Supply the declared host environment |
PackageExportUnknownRef | Fix the export or declaration |
PackageAuthorityFieldForbidden | Configure authority in the consuming project |
PackageInstallationIncomplete | Inspect the interrupted transaction before recovery |
The installation lock does not replace execution supply-chain checks. See the author and consumer guide.
Explicit handler selection
A package may propose a handler but never grants authority. In host decisions,
select it with bindings[toolRef].package_handler = "organization.name".
Keep the required grants, secrets, limits and effect contract explicit.
Preparation uses the declared package entrypoint and avoids generating an
unused local stub. Unknown or unrelated proposals are refused.
PackageExportMissing covers an unexported import, a declared module missing
from the package inventory, or a package with no export or context.
PackageExportUnknownRef covers an export whose declaration does not exist.
A copied package is not implicitly activated: run touba package add organization.name.
Private drafts
| Command | Result |
|---|---|
touba package submit [directory] --registry <URL> | Checked archive submitted as a private draft |
touba package checkout <id> --registry <URL> [--root <parent>] | New author folder named after the package |
touba package submit [directory] [--draft <id>] | Resubmission to the linked or explicitly selected draft |
touba package submit [directory] --ci <authorization> --registry <URL> | New draft from an authorized GitHub Actions job |
Interactive commands accept --no-browser and --json. Each operation uses browser
authentication; the service requires strong authentication for these CLI
operations. Checkout checks private access and integrity before extraction.
Submission runs the service’s validation and isolated tests.
Publication remains an explicit action.
The --ci mode uses GitHub OIDC with id-token: write. Its authorization
binds the repository, workflow, branch and environment. It prepares a new draft,
without a local link or automatic replacement. Final publication requires an
authorized person and strong authentication in the service. The --draft and
--no-browser options are incompatible with --ci.
The local .touba/package-draft.json link stays outside the archive. It stores
registry, identity/version, ID, revision and digest, without a token.
Resubmission keeps remote overview edits. A changed archive or concurrent
revision stops replacement.
| Diagnostic | Action |
|---|---|
PackageAlreadyExists | Choose a parent without a folder named after the package |
PackageDraftConflict | Review the remote draft before resubmitting |
PackageDraftTargetMismatch | Check the target registry, identity and version |
PackageDraftIntegrityMismatch | Ask the operator to verify the archive |
PackageDraftBusy | Inspect the active operation before recovering the lock |
PackageOperationCancelled | Check the draft before retrying |
PackageDraftRefused | Check your session, permissions and the service diagnostic |
Signed remote registry
Publishing to a compatible service opens browser authentication:
touba package publish --registry https://registry.example.org/registry
The service checks your identity, namespace permissions, archive and isolated
contract tests. --no-browser displays the link to open manually.
Credentials remain in memory during the operation.
For installation, obtain approved keys from the operator:
touba package add acme.review@1.0.0 \
--registry https://registry.example.org/registry \
--trust registry-trust.json
For a private registry, the command opens the browser to authorize catalog
reads. --no-browser displays the link to open manually. The read token stays
in memory during installation; revocation is requested when the operation
ends. Publishing uses a separate authorization.
The CLI verifies the signature, index validity, digests and version status. Installation preserves the consuming project's explicit execution permissions. These commands work with JavaScript and Python handlers.
The CLI keeps the last accepted revision and known keys in
registry-trust.json.sqlite, beside the selected trust file. Keep both files
together. An older revision, different content at the same revision or a revoked
key stops the command. For rotation, the operator first supplies a trust file
with both active keys, then removes or revokes the old one. An observed revocation
remains effective if an older trust file is restored.
Moving the trust file without its SQLite state starts a new trust bootstrap. The first read relies on the verified key and signature validity; backing up the state then preserves rollback protection.
touba package check archive.tar.gz --publishing checks an archive directly,
without installing it or executing its tests.
Read errors as JSON
package ... --json returns errors on stdout with status: "error",
diagnostics[].code, message, and a nonzero exit code.
A file at the reserved packages/ path produces PackageDirectoryRequired;
a symlink produces PackageSymlinkForbidden. A missing resource produces
PackageFileMissing with its relative path.
PackageExportMissing covers a non-exported import, an exported module
missing from the inventory, or a package with neither exports nor context.
PackageExportUnknownRef identifies an export pointing to an absent declaration.