Vorpal

CI Release License npm

Vorpal is a build system that works the way you already write code. Define your build as a program -- not YAML, not a DSL -- using real SDKs in Rust, Go, or TypeScript. Vorpal handles hermetic execution, cross-platform targeting, content-addressed caching, and artifact distribution so you can focus on what you are building.

Contents

Install

curl -fsSL https://raw.githubusercontent.com/ALT-F4-LLC/vorpal/main/script/install.sh | sh

macOS (Apple Silicon, Intel) and Linux (x86_64, ARM64). The installer downloads the latest release, generates TLS keys, and starts background services.

Building from source? See the Contributing section. For detailed installation options, see the Installation Guide.

Quickstart

Create a new project and build your first artifact. For a more detailed walkthrough, see the Quickstart tutorial.

1. Create a project

mkdir hello-world && cd hello-world
vorpal init hello-world

Choose your language (Go, Rust, or TypeScript) when prompted. Vorpal scaffolds a working project with a Vorpal.toml and sample build config.

2. Build it

vorpal build hello-world

Vorpal compiles your config, resolves dependencies, and produces a content-addressed artifact. First builds download toolchains; subsequent builds are cached.

3. Run it

vorpal run hello-world

That is it. Your artifact is built, cached, and runnable.

SDK Examples

Vorpal build configs are real programs. Write them in the language your project already uses. See the full SDK guides for Rust, Go, and TypeScript.

Build an artifact

Define a build artifact targeting multiple platforms with a single config file.

TypeScript
import { ArtifactSystem, ConfigContext, TypeScript, TypeScriptDevelopmentEnvironment } from "@altf4llc/vorpal-sdk";

const SYSTEMS = [
  ArtifactSystem.AARCH64_DARWIN,
  ArtifactSystem.AARCH64_LINUX,
  ArtifactSystem.X8664_DARWIN,
  ArtifactSystem.X8664_LINUX,
];

const context = ConfigContext.create();

// Artifacts

await new TypeScriptDevelopmentEnvironment("example-shell", SYSTEMS)
  .build(context);

await new TypeScript("example", SYSTEMS)
  .withEntrypoint("src/main.ts")
  .withIncludes(["src", "bun.lock", "package.json", "tsconfig.json"])
  .build(context);

await context.run();
Rust
use anyhow::Result;
use vorpal_sdk::{
    api::artifact::ArtifactSystem::{Aarch64Darwin, Aarch64Linux, X8664Darwin, X8664Linux},
    artifact::language::rust::{Rust, RustDevelopmentEnvironment},
    context::get_context,
};

#[tokio::main]
async fn main() -> Result<()> {
    let ctx = &mut get_context().await?;
    let systems = vec![Aarch64Darwin, Aarch64Linux, X8664Darwin, X8664Linux];

    // Artifacts

    RustDevelopmentEnvironment::new("example-shell", systems.clone())
        .build(ctx)
        .await?;

    Rust::new("example", systems)
        .with_bins(vec!["example"])
        .with_includes(vec!["src", "Cargo.lock", "Cargo.toml"])
        .build(ctx)
        .await?;

    ctx.run().await
}
Go
package main

import (
    "log"

    api "github.com/ALT-F4-LLC/vorpal/sdk/go/pkg/api/artifact"
    "github.com/ALT-F4-LLC/vorpal/sdk/go/pkg/artifact/language"
    "github.com/ALT-F4-LLC/vorpal/sdk/go/pkg/config"
)

var systems = []api.ArtifactSystem{
    api.ArtifactSystem_AARCH64_DARWIN,
    api.ArtifactSystem_AARCH64_LINUX,
    api.ArtifactSystem_X8664_DARWIN,
    api.ArtifactSystem_X8664_LINUX,
}

func main() {
    ctx := config.GetContext()

    // Artifacts

	_, err := language.NewGoDevelopmentEnvironment("example-shell", systems).Build(ctx)
	if err != nil {
		log.Fatalf("error building development environment: %v", err)
	}

	_, err = language.NewGo("example", systems).
		WithBuildDirectory("cmd/example").
		WithIncludes([]string{"cmd", "go.mod", "go.sum"}).
		Build(ctx)
	if err != nil {
		log.Fatalf("error building: %v", err)
	}

    ctx.Run()
}

Dev & user environments

Create portable development shells and user-wide tool installations with pinned dependencies.

TypeScript
import {
  ConfigContext,
  ArtifactSystem,
  DevelopmentEnvironment,
  UserEnvironment,
} from "@altf4llc/vorpal-sdk";

const SYSTEMS = [
  ArtifactSystem.AARCH64_DARWIN,
  ArtifactSystem.AARCH64_LINUX,
  ArtifactSystem.X8664_DARWIN,
  ArtifactSystem.X8664_LINUX,
];

async function main() {
  const context = ConfigContext.create();

  await new DevelopmentEnvironment("my-project", SYSTEMS)
    .withEnvironments(["FOO=bar"])
    .build(context);

  await new UserEnvironment("my-home", SYSTEMS)
    .withSymlinks([["/path/to/local/bin/app", "$HOME/.vorpal/bin/app"]])
    .build(context);

  await context.run();
}

main().catch((e) => { console.error(e); process.exit(1); });
Rust
use anyhow::Result;
use vorpal_sdk::{
  api::artifact::ArtifactSystem::{Aarch64Darwin, Aarch64Linux, X8664Darwin, X8664Linux},
  artifact::{DevelopmentEnvironment, UserEnvironment},
  context::get_context,
};

#[tokio::main]
async fn main() -> Result<()> {
  let ctx = &mut get_context().await?;
  let systems = vec![Aarch64Darwin, Aarch64Linux, X8664Darwin, X8664Linux];

  DevelopmentEnvironment::new("my-project", systems.clone())
    .with_environments(vec!["FOO=bar".into()])
    .build(ctx).await?;

  UserEnvironment::new("my-home", systems)
    .with_symlinks(vec![("/path/to/local/bin/app", "$HOME/.vorpal/bin/app")])
    .build(ctx).await?;

  ctx.run().await
}
Go
package main

import (
  api "github.com/ALT-F4-LLC/vorpal/sdk/go/pkg/api/artifact"
  "github.com/ALT-F4-LLC/vorpal/sdk/go/pkg/artifact"
  "github.com/ALT-F4-LLC/vorpal/sdk/go/pkg/config"
)

var systems = []api.ArtifactSystem{
  api.ArtifactSystem_AARCH64_DARWIN,
  api.ArtifactSystem_AARCH64_LINUX,
  api.ArtifactSystem_X8664_DARWIN,
  api.ArtifactSystem_X8664_LINUX,
}

func main() {
  ctx := config.GetContext()

  artifact.NewDevelopmentEnvironment("my-project", systems).
    WithEnvironments([]string{"FOO=bar"}).
    Build(ctx)

  artifact.NewUserEnvironment("my-home", systems).
    WithSymlinks(map[string]string{"/path/to/local/bin/app": "$HOME/.vorpal/bin/app"}).
    Build(ctx)

  ctx.Run()
}

Activate:

Custom executors

Swap the default Bash executor for Docker, Bubblewrap, or any custom binary.

TypeScript
import {
  ConfigContext,
  ArtifactSystem,
  Artifact,
  ArtifactStep,
} from "@altf4llc/vorpal-sdk";

const SYSTEMS = [
  ArtifactSystem.AARCH64_DARWIN,
  ArtifactSystem.AARCH64_LINUX,
  ArtifactSystem.X8664_DARWIN,
  ArtifactSystem.X8664_LINUX,
];

async function main() {
  const context = ConfigContext.create();

  const step = new ArtifactStep("docker")
    .withArguments([
      "run", "--rm", "-v", "$VORPAL_OUTPUT:/out",
      "alpine", "sh", "-lc", "echo hi > /out/hi.txt",
    ])
    .build();

  await new Artifact("example-docker", [step], SYSTEMS)
    .build(context);

  await context.run();
}

main().catch((e) => { console.error(e); process.exit(1); });
Rust
use anyhow::Result;
use vorpal_sdk::{
    api::artifact::ArtifactSystem::{Aarch64Darwin, Aarch64Linux, X8664Darwin, X8664Linux},
    artifact::{Artifact, ArtifactStep},
    context::get_context,
};

#[tokio::main]
async fn main() -> Result<()> {
    let ctx = &mut get_context().await?;
    let systems = vec![Aarch64Darwin, Aarch64Linux, X8664Darwin, X8664Linux];

    let step = ArtifactStep::new("docker")
        .with_arguments(vec![
            "run", "--rm", "-v", "$VORPAL_OUTPUT:/out",
            "alpine", "sh", "-lc", "echo hi > /out/hi.txt",
        ])
        .build();

    Artifact::new("example-docker", vec![step], systems).build(ctx).await?;

    ctx.run().await
}
Go
package main

import (
    "log"

    api "github.com/ALT-F4-LLC/vorpal/sdk/go/pkg/api/artifact"
    "github.com/ALT-F4-LLC/vorpal/sdk/go/pkg/artifact"
    "github.com/ALT-F4-LLC/vorpal/sdk/go/pkg/config"
)

var systems = []api.ArtifactSystem{
    api.ArtifactSystem_AARCH64_DARWIN,
    api.ArtifactSystem_AARCH64_LINUX,
    api.ArtifactSystem_X8664_DARWIN,
    api.ArtifactSystem_X8664_LINUX,
}

func main() {
    ctx := config.GetContext()

    step := artifact.NewArtifactStep("docker").
        WithArguments([]string{
            "run", "--rm", "-v", "$VORPAL_OUTPUT:/out",
            "alpine", "sh", "-lc",
            "echo hi > /out/hi.txt",
        }).
        Build()

    _, err := artifact.NewArtifact("example-docker",
        []*api.ArtifactStep{step}, systems).Build(ctx)
    if err != nil {
        log.Fatalf("error building artifact: %v", err)
    }

    ctx.Run()
}

Features

CLI Reference

Command Description
vorpal init <name> Initialize Vorpal in a directory
vorpal build <name> Build an artifact
vorpal run <alias> Run a built artifact from the store
vorpal config <action> Manage configuration settings (get, set, show)
vorpal login Login to an OAuth2 provider
vorpal inspect <digest> Inspect an artifact by digest
vorpal system keys generate Generate TLS keys
vorpal system services start Start Vorpal services (agent, registry, worker)
vorpal system prune Prune artifacts, sandboxes, and other resources

For full usage details and flags, run vorpal --help or vorpal <command> --help. See the complete CLI reference for more.

Documentation

Full documentation is available at docs.vorpal.build.

Resource Link
Installation guide docs.vorpal.build/getting-started/installation
Quickstart tutorial docs.vorpal.build/getting-started/quickstart
Architecture overview docs.vorpal.build/concepts/architecture
CLI reference docs.vorpal.build/reference/cli
Go SDK guide docs.vorpal.build/guides/go
Rust SDK guide docs.vorpal.build/guides/rust
TypeScript SDK guide docs.vorpal.build/guides/typescript

Contributing

Contributions are welcome. See docs/spec/ for project structure, coding standards, and review workflow.

# Build from source
./script/dev.sh make build

# Before submitting a PR
make format && make lint && make test

License

Apache 2.0