Skip to main content
Version: 1.0.0

Tutorial: create a package and use it in another project

Package availability

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​

Terminal
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:

src/acme/echo.tb
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: check name, version, publisher, license and the skill:acme.echo/Echo export;
  • 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.

Terminal
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​

Terminal
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:

src/client/main.tb
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​

Terminal
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:

Terminal
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.

Terminal
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:

Terminal
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:

Terminal (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​

FindingAction
PackagePublicationMetadataMissingComplete the reported author manifest fields
PackageExportUnknownRef or PackageExportMissingCheck the module, declaration and export, then validate again
PackageDependencyConflictReview the installed version; prepare an explicit upgrade
PackageIntegrityMismatchCompare the copy with approved content; restore a trusted copy instead of rewriting the lock to hide drift
No tests declaredAdd 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.