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.
curl -fsSL https://raw.githubusercontent.com/ALT-F4-LLC/vorpal/main/script/install.sh | shmacOS (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.
Create a new project and build your first artifact. For a more detailed walkthrough, see the Quickstart tutorial.
mkdir hello-world && cd hello-world
vorpal init hello-worldChoose your language (Go, Rust, or TypeScript) when prompted. Vorpal scaffolds a working project with a Vorpal.toml and sample build config.
vorpal build hello-worldVorpal compiles your config, resolves dependencies, and produces a content-addressed artifact. First builds download toolchains; subsequent builds are cached.
vorpal run hello-worldThat is it. Your artifact is built, cached, and runnable.
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.
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()
}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:
- Development environments: source generated
bin/activateinside the artifact output. - User environments: run
$HOME/.vorpal/bin/vorpal-activate, thensource $HOME/.vorpal/bin/vorpal-activate-shell.
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()
}- Config as code -- Your build config is a real program, not YAML. Write it in Rust, Go, or TypeScript with full IDE support.
- Reproducible by default -- Content-addressed artifacts with hermetic build steps. Same inputs always produce the same output.
- Cross-platform -- Target macOS (Apple Silicon + Intel) and Linux (x86_64 + ARM64) from a single config.
- Built-in caching -- Artifacts are cached by content hash. Unchanged builds resolve instantly.
- Dev environments -- Define project shells with pinned tools and env vars. Like direnv, but versioned and shareable.
- Artifact registry -- Push, pull, and share artifacts with built-in registry support. Run artifacts directly with
vorpal run. - Pluggable executors -- Build steps run in Bash by default. Swap in Docker, Bubblewrap, or any executor.
| 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.
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 |
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