Packages and Distribution

Local projects, exact git dependencies, lockfiles, cache restoration, and bundle validation.

Zynx package distribution is deliberately narrow in 0.0.0-dev. Builds use local source, exact git dependencies, and lockfiles. There is no central registry, semver solver, package signing, publishing workflow, mirror selection, or first-class vendor archive format in the current development contract.

Current Contract

Included:

  • local project packages with zynx.json
  • exact git dependencies declared in zynx.json
  • optional manifest-pinned git revisions with rev
  • zynx.lock reuse for deterministic dependency selection
  • new project scaffolding with zynx new <name> and zynx init
  • read-only package validation with zynx package check
  • package-cache restoration with zynx fetch
  • dependency updates with zynx update or zynx update <package>
  • deterministic module identity and duplicate-module rejection
  • static .zxm bundle metadata validation

Excluded:

  • package registries and package indexes
  • semver ranges such as ^1.2.0, ~1.2, or >=1
  • dependency declarations by registry package name alone
  • publishing commands
  • signed package verification
  • mirror selection
  • automatic vendor-cache archives
  • transitive dependency solving beyond the exact locked package graph

Unsupported dependency keys are rejected. Dependency entries may contain only git and optional rev.

Project Scaffolding

Create a new project directory:

./zynx new hello
cd hello
./zynx run

Initialize the current directory instead:

./zynx init
./zynx init --name my_project

zynx new <name> creates a directory containing zynx.json and src/main.zx. zynx init writes those files in the current directory and fails if zynx.json already exists. --name supplies the package name explicitly; when it is omitted, the name is derived from the directory and normalized to package name characters. Dependency-free projects do not get a zynx.lock until one is needed.

Project Manifest

zynx.json describes the local package, build targets, and exact dependencies.

{
  "format": "zynx-project",
  "version": 1,
  "package": {
    "name": "app",
    "version": "0.1.0"
  },
  "targets": {
    "app": {
      "kind": "executable",
      "main": "src/main.zx"
    }
  },
  "default_target": "app",
  "build": {
    "target": "native",
    "profile": "debug"
  },
  "dependencies": {
    "util": {
      "git": "https://github.com/your-org/zynx-util.git",
      "rev": "0123456789abcdef0123456789abcdef01234567"
    }
  }
}

package.version is metadata only. It does not participate in dependency selection.

Lockfile

zynx.lock records the exact dependency graph selected for a build:

{
  "format": "zynx-lock",
  "version": 1,
  "packages": {
    "util": {
      "git": "https://github.com/your-org/zynx-util.git",
      "rev": "0123456789abcdef0123456789abcdef01234567",
      "path": "git/util/0123456789abcdef0123456789abcdef01234567"
    }
  }
}

A normal build reuses a matching lockfile entry for the same dependency name and git URL. If the package cache is missing but the lockfile names a valid git revision, zynx fetch restores the checkout into the cache.

The default package cache is $ZYNX_HOME/packages, or ~/.local/share/zynx/packages when ZYNX_HOME is not set.

Updating Dependencies

Check package state without modifying zynx.lock or fetching dependencies:

./zynx package check

package check validates zynx.json, reads zynx.lock when present, reports missing or stale dependency lock entries, and reports invalid existing package cache checkouts. It does not contact git remotes and does not create or update the lockfile. A clean project reports package check: ok.

Refresh unlocked git dependencies to their remote HEAD with:

./zynx update

Refresh one dependency with:

./zynx update util

Manifest dependencies with rev are pinned to that exact revision. Changing a pinned revision is a source edit to zynx.json, followed by a normal build or fetch.

Reproducible Inputs

To reproduce a build, keep these inputs fixed:

  • project source
  • zynx.json
  • zynx.lock
  • package cache entries named by zynx.lock
  • active SDK and standard library
  • explicit --module-path roots, if any

Fully offline reproduction requires the locked package cache and SDK/stdlib inputs to already be present. Zynx does not define an offline vendor archive format or registry mirror.

Module Identity

Imports use dotted module identities. A package module must provide the same identity that the source imports. Duplicate non-standard module identities across explicit module paths or locked dependency packages are rejected instead of being resolved by path order.

A local source file next to the importer may intentionally shadow package modules. builtin and std.* remain reserved for the active standard library and SDK.

Bundle Validation

Static .zxm bundles may be imported only when their embedded metadata matches the requested module identity, active target, ABI, and supported bundle kind.

Dynamic bundles and runtime loading are not part of normal source. Use ordinary import plus declared package inputs.