Stone Package System

Stone includes a comprehensive package management system for sharing and reusing code.

File Extensions

ExtensionPurpose
.stnStone code (functions, logic, imports)
.sonStone Object Notation (data/config only)

Package Manifest (package.son)

Every package has a package.son file at its root:

// package.son
name = "my-physics-lib"
version = "1.0.0"
entry = "main.stn"              // optional, defaults to main.stn
description = "Physics simulation library"
author = "Jane Doe"
license = "MIT"

dependencies = {
  "stoneslabs.io" = {
    linalg = "^2.0.0"
    ode    = "~1.4.2"
  }
  "basinrepo.com" = {
    "amir/private-tool" = "^1.0.0"
    "amir/clay"         = { version = "^1.0", as = "amir-clay" }
  }
}

Dependencies are organised by origin URL (the domain that hosts them). The first slash splits the origin from the package path. Inside each origin block:

  • Bare version string: clay = "^1.0" for the simple case
  • Object form: { version, as, registry, git, path, ... } for renames or alternative sources

Required Fields

  • name - Package identifier (letters, numbers, underscores, hyphens)
  • version - Semantic version (e.g., "1.0.0")

Optional Fields

  • entry - Entry point file (default: "main.stn")
  • description - Package description
  • author - Package author
  • license - License identifier (e.g., "MIT", "Apache-2.0")
  • keywords - Array of keywords
  • dependencies - Origin-grouped map of dependencies (see above)

Version Ranges

Stone uses semantic versioning (semver):

SyntaxNameMeaning
1.2.3ExactExactly version 1.2.3
^1.2.3Compatible>=1.2.3 <2.0.0
~1.2.3Patch-level>=1.2.3 <1.3.0
>=1.0.0Greater/equal1.0.0 or higher
<2.0.0Less thanBelow 2.0.0
1.xWildcardAny 1.x version
*AnyAny version

Understanding ^ and ~

Version: 1.2.3
         │ │ └── PATCH (bug fixes)
         │ └──── MINOR (new features)
         └────── MAJOR (breaking changes)

^1.2.3  →  "Keep MAJOR fixed, allow MINOR+PATCH updates"
~1.2.3  →  "Keep MAJOR+MINOR fixed, allow only PATCH updates"

Project Structure

my-project/
├── package.son              # Project manifest
├── package.lock.son         # Locked versions (generated)
├── stone_modules/           # Installed packages
│     utils/
│       package.son
│       main.stn
│     physics/
│       package.son
│       main.stn
├── main.stn                 # Your code
└── lib/
      helpers.stn

Module Resolution

When you write import foo from bar:

  1. Built-in? Check primitives (print, len, sqrt, etc.)
  2. Standard library? Check bundled modules (math, array, stats, etc.)
  3. Project root? Walk up to find package.son
  4. Local stone_modules/ Check stone_modules/bar at project root
  5. Global stone_modules/ Check ~/.stone/stone_modules/bar
  6. Error if not found

Relative vs Absolute Imports

// Relative imports - bypass package resolution
import helper from ./utils/helper
import shared from ../common/shared

// Absolute imports - use package resolution
import math from math           // standard library
import physics from physics     // from stone_modules

CLI Commands

Initialize a Project

stone init

Creates package.son in the current directory.

Install Dependencies

# Install all dependencies from package.son
stone install

# Install a specific package from URL
stone install physics --source https://example.com/packages

# Install a specific package from local directory
stone install mylib --source ./path/to/mylib
stone install mylib --source /absolute/path/to/mylib
stone install mylib --source C:\path\to\mylib    # Windows

# Install globally
stone install -g utils --source https://example.com/packages

Remove a Package

stone remove physics

# Remove from global
stone remove -g utils

Update Dependencies

# Update all
stone update

# Update specific package
stone update physics

List Packages

# List project packages
stone list

# List global packages
stone list -g

Lock File (package.lock.son)

The lock file ensures reproducible builds:

// package.lock.son
lockVersion = 1

packages = {
  utils = {
    version = "1.2.3",
    source = "https://example.com/packages/utils",
    integrity = "sha256-abc123..."
  },
  physics = {
    version = "2.1.0",
    source = "https://github.com/user/physics/releases",
    integrity = "sha256-def456..."
  }
}

Package Sources

Packages can be fetched from HTTP URLs or copied from local directories. No central registry is required.

URL Sources

dependencies = {
  utils = {
    version = "^1.0.0",
    source = "https://example.com/packages/utils"
  }
}

Expected URL Structure

https://example.com/packages/utils/
├── versions.son            # Optional: lists available versions
├── 1.0.0/
│     package.son
│     main.stn
│     ...
├── 1.0.1/
│     ...
└── 1.1.0/
      ...

Local Path Sources

You can also install packages from local directories, useful for development and testing:

dependencies = {
  mylib = {
    version = "^1.0.0",
    source = "./packages/mylib"           // Relative path
  },
  shared = {
    version = "*",
    source = "/home/user/libs/shared"     // Absolute path
  }
}

Local paths are resolved relative to the current working directory when using the CLI.

The package directory should contain:

mylib/
├── package.son    # Package manifest (optional but recommended)
├── main.stn       # Entry point
└── ...            # Other source files

Global Packages

Global packages are installed to ~/.stone/:

~/.stone/
├── package.son              # Global dependencies
├── stone_modules/           # Global packages
      utils/
      math-ext/

Set STONE_HOME environment variable to use a different location.

Web/Browser Support

In web environments (Riva):

  1. Packages are fetched on demand when a script runs
  2. Cached in browser storage (IndexedDB)
  3. Cache clears on logout
  4. Global packages are stored in the user's account

Stone Object Notation (.son)

SON is a subset of Stone syntax for data files:

// Comments are supported

// Simple values
name = "my-package"
version = "1.0.0"
count = 42
enabled = true
nothing = none

// Arrays
keywords = ["math", "science", "simulation"]

// Objects
config = {
  debug = true,
  level = 3
}

// Nested structures
dependencies = {
  utils = {
    version = "^1.0.0",
    source = "https://example.com"
  }
}

Not allowed in SON:

  • Functions
  • Control flow (if, for, while)
  • Imports
  • Expressions (only literal values)

Standard Documentation Files

Packages support three optional documentation files at the project root:

FilePurposeWhen to include
GUIDE.mdAI agent + human reference — setup, API, usage patterns, conventionsRecommended for all packages
DEMO.mdRunnable examples — interactive Stone code blocksRecommended for all packages
ABOUT.mdBasin landing page — design rationale, comparisons, project story (not loaded by Delta)Optional — only when your package has a story to tell

You don't need to write a README.md — one is auto-generated at publish time from your package.son metadata, linking to whichever standard files are present.

Example Project with Docs

my-slab/
├── package.son
├── main.stn
├── GUIDE.md            # Setup, API reference, usage patterns
├── DEMO.md             # Runnable usage examples
├── ABOUT.md            # Optional — narrative, rationale, comparisons
└── lib/
      helpers.stn

GUIDE.md

The primary documentation file. When a user installs a package that includes a GUIDE.md, it is automatically registered as a workspace guide in Riva. The Delta agent loads it into context to understand your package's API, conventions, and intended usage.

Include everything an agent or developer needs to use the package correctly:

  • Setup — build steps, extern dependencies, environment variables, system requirements
  • API reference — function signatures, parameter tables, return types
  • Conventions — usage patterns, gotchas, common pitfalls
  • Prerequisites — domain knowledge or companion packages needed

Don't repeat the package description — Delta prepends it automatically from package.son.

DEMO.md

Runnable Stone examples that show your package in action. Both humans and the AI agent use these — users browse them to learn, Delta suggests them when asked "show me how."

Use Stone code blocks:

## Basic Usage

```stone
import transform from my-slab

data = [1, 2, 3, 4, 5]
result = transform(data)
print(result)
```

ABOUT.md

The Basin landing page for your package. This file is not loaded by Delta — it doesn't consume agent context or credits. Write freely for a human audience.

Most packages don't need one — package.son metadata and the auto-generated README cover simple cases. Include one when your package has context that isn't reference material:

  • Design rationale — why this approach, how it differs from alternatives
  • Project story — motivation, intended audience, architectural decisions
  • Comparisons — how it relates to similar packages or tools

If Basin finds an ABOUT.md, it renders it as the package landing page. Otherwise, the auto-generated README from package.son is used.

Skip it for simple packages. A stats slab doesn't need a landing page explaining why statistics exist.

Doc Comments (///)

Stone uses triple-slash comments (///) for documentation. These are distinct from regular comments (//) and are used to generate API documentation automatically.

/// Bisection root-finding on [a, b].
/// f(a) and f(b) must have opposite signs.
export fn bisect(f, a, b, tol = 1e-12) {
    ...
}

Rules

  • /// directly above an export = doc comment for that export
  • // = regular comment — ignored by documentation tools
  • First /// line = brief description (used in API tables, search results)
  • Subsequent /// lines = extended description (return types, gotchas, details)
  • A blank line or regular // comment between /// and the export breaks the association

What to document

The function signature already shows parameter names and defaults — don't repeat them. Focus on:

  • What it does (the brief — first line)
  • What it returns (especially for record returns)
  • Gotchas or constraints (e.g. "inputs must have opposite signs")
// ============================================
// ROOT FINDING                          ← regular comment, ignored
// ============================================

// Internal helper                       ← regular comment, ignored
fn _check_bracket(fa, fb) { ... }

/// Bisection root-finding on [a, b].
/// f(a) and f(b) must have opposite signs.
/// Returns {x, fval, converged, iterations}
export fn bisect(f, a, b, tol = 1e-12) {
    ...
}

/// Newton's method for root-finding.
/// Requires derivative function fprime.
/// Returns {x, fval, converged, iterations}
export fn newton(f, fprime, x0, tol = 1e-12, max_iter = 100) {
    ...
}

/// Gravitational constant (m³ kg⁻¹ s⁻²)
export G = 6.674e-11

Generated output

The generate-api-tree.js script parses /// comments and produces API reference tables:

FunctionDescription
bisect(f, a, b, tol = 1e-12)Bisection root-finding on [a, b].
newton(f, fprime, x0, tol = 1e-12, max_iter = 100)Newton's method for root-finding.

The brief (first /// line) appears in the table. Extended lines are available for detailed documentation views.

Extern Modules (Native C/C++ Libraries)

Stone packages can include native C/C++ code as an extern kernel, letting you wrap existing libraries and call them from Stone. See Extern Modules for the full guide covering setup, the Stone Record ABI, dependency resolution, and mixing C and C++.

Best Practices

  1. Lock your dependencies - Commit package.lock.son to version control
  2. Use version ranges - ^1.0.0 allows compatible updates
  3. Pin critical deps - Use exact versions for critical packages
  4. Document your package - Include GUIDE.md and DEMO.md; add ABOUT.md only if setup or context is needed
  5. Keep dependencies minimal - Only add what you need