What is flyp?
flyp is the official package manager for Fly. It handles everything outside the compiler itself: creating projects, declaring and fetching dependencies, locking versions for reproducible builds, and invoking the fly compiler with the right flags and include paths.
flyp ships alongside the fly compiler as a separate binary in the same installation archive. If you have Fly installed, you have flyp.
$ flyp --version
flyp 0.1.0
Project structure
A Fly project managed by flyp has this layout:
my-project/
├── fly.toml # manifest — project metadata and dependencies
├── fly.lock # lockfile — exact resolved versions (commit to VCS)
└── src/
└── main.fly # entry point (auto-detected)
fly.toml is written by hand. fly.lock is generated by flyp and must never be edited manually.
fly.toml reference
fly.toml is the project manifest. It uses TOML syntax.
[package]
Required section that describes the project itself.
[package]
name = "my-app"
version = "0.1.0"
description = "A brief description of what this project does"
license = "Apache-2.0"
fly-version = "0.1.0"
homepage = "https://example.com" # optional
repository = "https://github.com/you/my-app" # optional
authors = ["Your Name <[email protected]>"] # optional
| Field | Required | Description |
|---|---|---|
name | yes | Package name. Must match [a-z0-9_-]+ |
version | yes | Semantic version in MAJOR.MINOR.PATCH format |
description | yes | Short description |
license | yes | SPDX license identifier |
fly-version | yes | Minimum Fly compiler version required |
homepage | no | Project website |
repository | no | Source repository URL |
authors | no | List of author strings |
[[bin]]
Declares an executable target. If omitted, flyp auto-detects src/main.fly.
[[bin]]
name = "my-app"
path = "src/main.fly"
[[bin]]
name = "cli-tool"
path = "src/cli.fly"
[[lib]]
Declares a library target. If omitted, flyp auto-detects src/lib.fly.
[[lib]]
name = "my-lib"
path = "src/lib.fly"
type = "static" # "static" (default) or "shared"
[[test]]
Declares a test suite target.
[[test]]
name = "unit"
path = "test/unit.fly"
[[test]]
name = "integration"
path = "test/integration.fly"
[dependencies]
Runtime dependencies fetched from Git repositories.
[dependencies]
mylib = { git = "https://github.com/example/mylib.git", tag = "v1.2.0" }
core = { git = "https://github.com/example/core.git", branch = "main" }
patched = { git = "https://github.com/example/utils.git", rev = "a3f1c29d" }
Each dependency must specify exactly one of:
| Key | Description |
|---|---|
tag | A Git tag — recommended for released versions |
branch | A Git branch — always fetches the latest commit on that branch |
rev | A full 40-character commit hash — the most reproducible option |
[dev-dependencies]
Dependencies used only for tests and development tools. Not fetched in release builds and not propagated to packages that depend on yours.
[dev-dependencies]
test-utils = { git = "https://github.com/example/test-utils.git", tag = "v0.3.0" }
[profile.debug] and [profile.release]
Build profiles control how the Fly compiler optimises and instruments the output.
[profile.debug]
opt-level = 0 # 0–3
debug-info = true # emit DWARF debug information
assertions = true # enable runtime assertions
[profile.release]
opt-level = 3
debug-info = false
lto = false # link-time optimisation
strip = false # strip symbols from output binary
assertions = false
Creating a project
$ flyp init
Creates fly.toml and src/main.fly in the current directory, using the directory name as the package name.
$ flyp init --name my-app
Creates a new subdirectory my-app/ with the same layout.
$ flyp init --name my-app --version 0.2.0
Specifies an initial version other than the default 0.1.0.
After flyp init:
my-app/
├── fly.toml
└── src/
└── main.fly
Managing dependencies
Adding a dependency
$ flyp add mylib --git https://github.com/example/mylib.git --tag v1.2.0
flyp adds the entry to fly.toml, then immediately resolves and fetches all dependencies, writing a fresh fly.lock.
$ flyp add core --git https://github.com/example/core.git --branch main
$ flyp add patched --git https://github.com/example/utils.git --rev a3f1c29d8e2b...
Add a development-only dependency with --dev:
$ flyp add test-utils --git https://github.com/example/test-utils.git --tag v0.3.0 --dev
Removing a dependency
$ flyp remove mylib
Removes the entry from fly.toml (both [dependencies] and [dev-dependencies]) and regenerates fly.lock.
Updating dependencies
Update a single package to the latest commit on its configured branch or tag:
$ flyp update mylib
Update all dependencies at once:
$ flyp update
flyp update clears the affected cache entries and re-runs resolution, so it will pick up new commits on tracked branches or newer tags if you change fly.toml manually.
The lockfile
fly.lock records the exact commit hash, checksum, and dependency tree for every package in the build. A minimal lockfile looks like this:
# fly.lock — generated automatically by flyp.
# Do not edit manually.
# Commit alongside fly.toml for reproducible builds.
version = 1
flyp = "0.1.0"
checksum = "sha256:e3b0c44298fc1c149afbf4c8996fb924..."
[[package]]
name = "mylib"
version = "1.2.0"
source = "git+https://github.com/example/mylib.git"
rev = "a3f1c29d8e2b4f1a7c3d5e6b8f9a0b1c2d3e4f5a"
tag = "v1.2.0"
checksum = "sha256:9f86d081884c7d659a2feaa0c55ad015..."
dependencies = []
Always commit fly.lock to version control. It guarantees that every developer and every CI run compiles the exact same code.
The lockfile is automatically regenerated whenever fly.toml changes. flyp detects staleness by storing a SHA-256 checksum of fly.toml inside the lockfile itself.
Version resolution (MVS)
flyp uses Minimum Version Selection (MVS), the same algorithm used by Go Modules. The rules are simple:
- Collect all version constraints from the root manifest and all transitive dependencies via breadth-first traversal.
- For each package, select the highest version among all constraints — this is the minimum version that satisfies everyone.
- If two constraints refer to the same package name but different Git URLs, resolution fails with error E001.
Example
root → mylib v1.0.0
root → framework v2.0.0
framework → mylib v1.5.0 ← higher constraint
MVS selects mylib v1.5.0. No SAT solver, no backtracking — deterministic and fast.
Why the highest version?
Because it is the minimum version that satisfies the most demanding constraint. Lower versions would break framework, and picking an arbitrary higher version would be non-deterministic.
Building
Compile all targets in debug mode:
$ flyp build
Compile with the release profile (optimised, no debug info):
$ flyp build --release
Build a specific target by name:
$ flyp build --target my-app
Output goes to target/debug/ or target/release/ in the project root.
If fly.lock is stale when you run flyp build, flyp automatically re-locks before building.
Running
Build and immediately run the default binary:
$ flyp run
Pass arguments to the binary after --:
$ flyp run -- --port 8080 --verbose
Choose which binary to run in a multi-binary project:
$ flyp run --bin cli-tool
$ flyp run --release --bin server
Testing
Build and run all test suites:
$ flyp test
Run only one suite by name:
$ flyp test unit
Run tests with release optimisations:
$ flyp test --release
Each test target is compiled and executed as a standalone binary. flyp reports pass/fail per suite.
Understanding the dependency graph
flyp why <package> explains why a package is included and which constraint caused it to be selected.
$ flyp why mylib
Example output:
mylib v1.5.0 is included because:
root v0.1.0 (requires mylib tag v1.0.0)
framework v2.0.0 (requires mylib tag v1.5.0)
resolved: mylib 1.5.0 satisfies all 2 constraint(s)
This makes it easy to understand diamond dependencies and trace unexpected version selections.
Resolving the lockfile manually
Run resolution explicitly without building:
$ flyp lock
Useful in CI pipelines to separate the "resolve" step from the "build" step, or to pre-populate the cache.
Cache management
flyp stores fetched packages in a local cache so they are not re-downloaded on every build.
| Path (default) | Description |
|---|---|
~/.flyp/cache/<host>/<owner>/<repo>/<rev>/ | Cached source tree |
Override the cache location with the environment variable $FLYP_HOME:
export FLYP_HOME=/opt/flyp
Inspect the cache
$ flyp cache stats
Cache: /home/user/.flyp/cache
142 files, 3891 KB
Clear the cache
$ flyp cache clean
Cache cleared: /home/user/.flyp/cache
Error reference
flyp reports structured errors with a code, context, and a hint.
E001 — Dependency conflict
Two packages require the same dependency from different Git URLs. flyp cannot reconcile this automatically.
error[E001]: dependency conflict — cannot resolve
conflict chain:
root → mylib (git=https://github.com/example/mylib.git tag=v1.0.0)
fork-lib → mylib (git=https://github.com/fork/mylib.git tag=v1.0.0)
hint: run `flyp why mylib` to see all constraints
Resolution: ensure all packages in your dependency tree reference the same Git URL for a given package name, or fork one of the conflicting packages under a different name.
E002 — Package not found
The specified tag, branch, or commit hash does not exist in the remote repository.
error[E002]: package not found
package: mylib
source: https://github.com/example/mylib.git
tag "v3.0.0" not found in repository
available: v1.0.0, v1.2.0, v2.0.0
hint: did you mean tag = "v2.0.0"?
Resolution: check the tag or branch name in fly.toml. Use flyp update after correcting it.
CLI reference
| Command | Description |
|---|---|
flyp init [--name NAME] [--version VER] | Create a new Fly project |
flyp build [--release] [--target NAME] | Build all or one target |
flyp run [--release] [--bin NAME] [-- ARGS] | Build and run a binary |
flyp test [--release] [SUITE] | Build and run test suites |
flyp add NAME --git URL (--tag|--branch|--rev) [--dev] | Add a dependency |
flyp remove NAME | Remove a dependency |
flyp update [NAME] | Update one or all dependencies |
flyp lock | Resolve and write fly.lock |
flyp why NAME | Explain why a package is included |
flyp cache stats | Show cache size |
flyp cache clean | Remove all cached packages |
flyp version | Print flyp version |
flyp search QUERY | Search the package registry (coming soon) |
flyp publish | Publish to the package registry (coming soon) |