Tutorial: create a package and use it in another project
Local packages are available now. The public package server is undergoing validation and testing and will be available soon.
This walkthrough uses the real compiler and runtime, without a model or network.
Create acme.echo, test its contract, share an archive, import it into an
application, then upgrade that application. The final alternatives cover a
local registry and manual registration.
Before you start
Install Touba, open a terminal and check touba version, then touba doctor.
This pure package needs no SDK or external service. Commands below use
macOS/Linux or a POSIX shell on Windows; in PowerShell, create the same folders
and adapt shell syntax, not the Touba files. Use a fresh directory and keep
the same terminal to follow the cd commands.
Author sources remain in package-demo/echo/; the application is in
package-demo/consumer/. Its packages/acme.echo/ directory is a checked
copy, not the place to develop the package.
1. Create the author package
mkdir package-demo
cd package-demo
touba package new echo --org acme --license MIT --yes
cd echo
touba package check
touba package test
The generated skill is:
module acme.echo
skill Echo
description "Return the supplied text unchanged."
takes value as Text
gives Text
do
give value
The generated touba.package.json contains acme.echo, version 0.1.0,
the publisher from --org, the license and the declared test. Choose a license
you are entitled to use. The test compiles and runs Echo; an incorrect assertion
makes touba package test fail.
Before sharing, open the generated files:
touba.package.json: checkname,version,publisher,licenseand theskill:acme.echo/Echoexport;src/acme/echo.tb: the exported business declaration;tests/echo.test.mjs: the test that prepares and runs Echo, then checks the result;README.md: complete the input/output contract and import example.
Keep Echo unchanged during this tutorial to obtain the same results. For your own package, update source, exports and assertions together, following the author guide.
touba package check --publishing
touba package pack
The publication check should succeed and produce
dist/acme.echo-0.1.0.tar.gz. pack reports its digest, without running tests
for you or sending the package to a server. Keep the archive and digest;
a second pack command targeting the same file is refused.
2. Install in another project
cd ..
mkdir consumer
cd consumer
touba init
touba package add ../echo/dist/acme.echo-0.1.0.tar.gz
touba package list
mkdir -p src/client
package list should show acme.echo at 0.1.0. Touba creates
touba.packages.lock.json and records the dependency in
touba.project.json. Installation does not modify the author package.
Create this file:
module client.main
import skill Echo from acme.echo
strategy Run
takes request as Text
gives Text
uses Echo
do
Echo
with value as request
into reply
give reply
3. Prepare and run
touba prepare --mode write --entry strategy:client.main/Run
touba run --project . --inputs-json '{"request":"Package import works"}' --output json
The result is Package import works. No network permission, handler or model
key is needed.
In the output JSON, check status: "success" and
result: "Package import works". The qualified name after from identifies
the module; uses Echo declares the capability used by the strategy.
The dependency's physical path does not appear in the Touba code.
4. Check the boundary
In a test copy, edit packages/acme.echo/src/acme/echo.tb, then run
touba prepare: PackageIntegrityMismatch refuses preparation.
A version string alone does not guarantee file content.
Try importing a declaration that is not exported: preparation refuses the import. Installation makes public declarations available, not every symbol inside a package.
Keep the original archive and restore your test copy from it rather than recomputing a lock to hide an unexpected change.
5. Create a new local version
Return to the author project, not the installed copy:
cd ../echo/src
touba package version patch
touba package check --publishing
touba package test
touba package pack
Commands find the root from src/. The archive is now
echo/dist/acme.echo-0.1.1.tar.gz; the first archive remains unchanged.
Nothing is sent remotely. The consumer keeps 0.1.0 until an explicit upgrade.
The acme.echo identity stays stable; metadata and the documented contract
can evolve in the new version.
6. Upgrade the consumer
From echo/src/, return to the consumer. For this demonstration project with
no other dependency, explicitly remove the installed copy and add the next
archive. In a real project, use a working branch or copy and preserve the
previous lock for review.
cd ../../consumer
touba package remove acme.echo
touba package add ../echo/dist/acme.echo-0.1.1.tar.gz
touba package list
touba package check
touba prepare --mode write --entry strategy:client.main/Run
touba run --project . --inputs-json '{"request":"Package import works"}' --output json
The list shows 0.1.1 and the result is unchanged. Imports stay the same because
the identity and contract are stable. Commit the project manifest and lock
together. Here 0.1.0 and 0.1.1 belong to your package, not to the
Touba language distribution.
Install from a private registry
After publication, obtain the operator's trust file and verify its fingerprint through your trusted channel. In a new project:
touba package add acme.echo@0.1.1 \
--registry https://registry.example.org/registry \
--trust registry-trust.json
touba package list
Check the code displayed by the terminal, then authorize reads in the browser. Touba verifies the signature and digests, installs the package and releases its temporary access. Use the same typed import as in this tutorial. Replace the example URL with your registry's address.
7. Alternative: publish and install through a local registry
Still starting from consumer/, publish the author version to a sibling directory:
cd ../echo
touba package test
touba package publish --registry ../registry
touba registry check --registry ../registry --source-root ../registry
cd ../consumer
touba package remove acme.echo
touba package add acme.echo@0.1.1 --registry ../registry --allow-draft
touba package list
touba prepare --mode write --entry strategy:client.main/Run
touba run --project . --inputs-json '{"request":"Package import works"}' --output json
registry/ contains the index, metadata and archive. Local publication starts
as draft: --allow-draft accepts your own reviewed code here, not an unknown
third-party package. Without that choice, the draft is refused. A second
publication of the same identity/version is refused; no archive is overwritten.
This command neither reserves a name with a public service nor uploads files.
HTTPS hosting is a separate step.
8. Alternative: register a manually copied directory
Run touba init in a new test project. Open the archive you just produced
with your archive manager. Copy the contents of its package/ directory into
packages/acme.echo/. The manifest must be directly at
packages/acme.echo/touba.package.json, without another package/ level.
Do not copy the entire author directory with its builds.
From this new project:
touba package add acme.echo
touba package list
touba package check
The name is enough because Touba searches packages/. Copying alone does not
replace add, which checks and records the content. Reuse
src/client/main.tb and the commands from step 3 to use it.
For third-party archives, prefer touba package add <archive>: Touba checks
archive paths before extraction.
9. Understand a refusal and continue
| Finding | Action |
|---|---|
PackagePublicationMetadataMissing | Complete the reported author manifest fields |
PackageExportUnknownRef or PackageExportMissing | Check the module, declaration and export, then validate again |
PackageDependencyConflict | Review the installed version; prepare an explicit upgrade |
PackageIntegrityMismatch | Compare the copy with approved content; restore a trusted copy instead of rewriting the lock to hide drift |
| No tests declared | Add real tests; no_tests does not validate business behavior |
10. Submit a draft for review
With a compatible publication service and maintainer access to an acme
namespace, return to the echo author folder:
touba package submit --registry https://registry.example.org/registry
Replace this example address with your service URL. Confirm the terminal code in your browser. After verification, open the returned link: the README is the default overview. Keep it, upload another README or write sections in the service. Preview the page, then publish this version.
To continue the draft on another machine, use its ID from an available parent directory:
touba package checkout 11111111-1111-4111-8111-111111111111 --registry https://registry.example.org/registry
cd echo
touba package check
touba package test
touba package submit
Replace the example ID with the one returned by your submission.
Touba creates echo/ and records its draft link; later submissions reuse it.
The service keeps the saved overview and images. After publication, change
the version before submitting new code. The workflow is identical for both SDKs.
You now have a testable package, a reusable archive and an application that actually imports it. Continue with the full guide, manifest reference, package context and governed tool, and JavaScript or Python handlers.
GitHub Actions variant
With a submission authorization created by your space owner, the same package can become a draft from its CI job:
touba package submit --ci 11111111-1111-4111-8111-111111111111 --registry https://registry.example.org/registry
The job needs id-token: write and the authorized environment. Replace the
example values with those of your service. Open the returned link, review the
overview and publish the version through the interface. The
guide
explains the authorization scope.