Flox Package Publishing Guide
Core Commands
flox publish # Publish all packages flox publish my_package # Publish single package flox publish -o myorg package # Publish to organization flox publish -o myuser package # Publish to personal namespace flox auth login # Authenticate before publishing
Publishing Workflow: Development to Runtime
Publishing packages enables a clear separation between development and runtime/consumption:
The Complete Workflow
Phase 1: Development Environment
# .flox/env/manifest.toml (in git with source code) [install] gcc.pkg-path = "gcc13" make.pkg-path = "make" python.pkg-path = "python311Full" [build.myapp] command = ''' python setup.py build mkdir -p $out/bin cp build/myapp $out/bin/ ''' version = "1.0.0"
Developers work in this environment, commit .flox/ to git alongside source code.
Phase 2: Build and Publish
# Build the package flox build myapp # Publish to catalog flox publish -o myorg myapp
The published package contains BINARIES/ARTIFACTS (what's in $out/), NOT source code.
Phase 3: Runtime Environment
# Separate environment (can be pushed to FloxHub) [install] myapp.pkg-path = "myorg/myapp" # The published package
Consumers create runtime environments and install the published package. No build tools needed, no source code exposed.
Key insight: You don't install the published package back into the development environment - that would be circular. Published packages are installed into OTHER environments (different projects, production, etc.).
Publishing to Flox Catalog
Prerequisites
Before publishing:
- •Package defined in
[build]section or.flox/pkgs/ - •Environment in Git repo with configured remote
- •Clean working tree (no uncommitted changes)
- •Current commit pushed to remote
- •All build files tracked by Git
- •At least one package installed in
[install]
Authentication
Run authentication before first publish:
flox auth login
Publishing Commands
# Publish single package flox publish my_package # Publish all packages flox publish # Publish to organization flox publish -o myorg my_package # Publish to personal namespace (for testing) flox publish -o mypersonalhandle my_package
Catalog Types
Personal catalogs: Only visible to you (good for testing)
- •Published to your personal namespace
- •Example: User "alice" publishes "hello" → available as
alice/hello - •Useful for testing before publishing to organization
Organization catalogs: Shared with team members (paid feature)
- •Published to organization namespace
- •Example: Org "acme" publishes "tool" → available as
acme/tool - •All organization members can install
Build Validation
Flox clones your repo to a temp location and performs a clean build to ensure reproducibility. Only packages that build successfully in this clean environment can be published.
This validation ensures:
- •All dependencies are declared
- •Build is reproducible
- •No reliance on local machine state
- •Git repository is clean and up-to-date
After Publishing
- •Package available in
flox search,flox show,flox install - •Metadata sent to Flox servers
- •Package binaries uploaded to Catalog Store
- •Install with:
flox install <catalog>/<package>
Users can then:
# Search for your package flox search my_package # See package details flox show myorg/my_package # Install the package flox install myorg/my_package
What Gets Published
Published packages contain:
- •Binaries and compiled artifacts (everything in
$out/) - •Runtime dependencies specified in
runtime-packages - •Package metadata (version, description)
Published packages do NOT contain:
- •Source code (unless explicitly copied to
$out/) - •Build tools or build-time dependencies
- •Development environment configuration
- •The
.flox/directory itself
This separation allows you to share built artifacts without exposing source code.
Real-world Publishing Workflows
Application Development Workflow
Developer workflow:
- •
Create development environment with build tools:
bashmkdir myapp && cd myapp flox init flox install gcc make python311Full
- •
Add source code and build definition to
.flox/env/manifest.toml:toml[build.myapp] command = '''make && cp myapp $out/bin/''' version = "1.0.0"
- •
Commit to git (environment definition + source code):
bashgit add .flox/ src/ git commit -m "Add development environment and source" git push origin main
- •
Build and publish package (binaries/artifacts):
bashflox build myapp flox publish -o myorg myapp
Other developers:
- •Clone repo:
git clone <repo> && cd myapp && flox activate - •Get the same development environment with build tools
Consumers:
- •Create new runtime environment:
flox init && flox install myorg/myapp - •OR install into existing environment:
flox install myorg/myapp - •Get the BUILT package (binaries), not source code
- •Can push runtime environment to FloxHub without exposing source
Fork-based Development Pattern
- •Fork upstream repo (e.g.,
user/projectfromupstream/project) - •Add
.flox/to fork with build definitions - •Commit and push:
git push origin main - •Publish package:
flox publish -o username package-name - •Others can install:
flox install username/package-name
Versioning Strategies
Semantic Versioning
[build.mytool] version = "1.2.3" # Major.Minor.Patch description = "My awesome tool"
Git-based Versioning
[build.mytool] version.command = "git describe --tags" description = "My awesome tool"
File-based Versioning
[build.mytool] version.file = "VERSION.txt" description = "My awesome tool"
Dynamic Versioning from Source
[build.rustapp] version.command = "cargo metadata --no-deps --format-version 1 | jq -r '.packages[0].version'"
Publishing Multiple Variants
You can publish multiple variants of the same project:
[build.myapp] command = ''' cargo build --release mkdir -p $out/bin cp target/release/myapp $out/bin/ ''' version = "1.0.0" description = "Production build" sandbox = "pure" [build.myapp-debug] command = ''' cargo build mkdir -p $out/bin cp target/debug/myapp $out/bin/myapp-debug ''' version = "1.0.0" description = "Debug build with symbols" sandbox = "off"
Both can be published and users can choose which to install.
Testing Before Publishing
Local Testing
- •Build the package:
flox build myapp
- •Test the built artifact:
./result-myapp/bin/myapp --version
- •Install locally to test:
flox install ./result-myapp
Personal Catalog Testing
Publish to your personal namespace first:
flox publish -o myusername myapp
Then test installation:
flox install myusername/myapp
Once validated, republish to organization:
flox publish -o myorg myapp
Common Gotchas
Branch names
Many repos use master not main - check with git branch
Auth required
Run flox auth login before first publish
Clean git state
Commit and push ALL changes before flox publish:
git status # Check for uncommitted changes git add .flox/ git commit -m "Add flox build configuration" git push origin master
runtime-packages
List only what package needs at runtime, not build deps:
[install] gcc.pkg-path = "gcc" make.pkg-path = "make" [build.myapp] command = '''make && cp myapp $out/bin/''' runtime-packages = [] # No runtime deps needed
Git-tracked files only
All files referenced in build must be tracked:
git add .flox/pkgs/* git add src/ git commit -m "Add build files"
Publishing Nix Expression Builds
For Nix expression builds in .flox/pkgs/:
- •Create the Nix expression:
mkdir -p .flox/pkgs
cat > .flox/pkgs/hello.nix << 'EOF'
{ hello }:
hello.overrideAttrs (oldAttrs: {
patches = (oldAttrs.patches or []) ++ [ ./my.patch ];
})
EOF
- •Track with Git:
git add .flox/pkgs/* git commit -m "Add hello package" git push
- •Publish:
flox publish hello
Publishing Configuration and Assets
You can publish non-code artifacts:
Configuration templates
[build.nginx-config] command = ''' mkdir -p $out/etc cp nginx.conf $out/etc/ cp -r conf.d $out/etc/ ''' version = "1.0.0" description = "Organization Nginx configuration"
Protocol buffers
[build.api-proto] command = ''' mkdir -p $out/share/proto cp proto/**/*.proto $out/share/proto/ ''' version = "2.1.0" description = "API protocol definitions"
Teams install and reference via $FLOX_ENV/etc/ or $FLOX_ENV/share/.
Continuous Integration Publishing
GitHub Actions Example
name: Publish to Flox
on:
push:
tags:
- 'v*'
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Flox
run: |
curl -fsSL https://downloads.flox.dev/by-env/stable/install | bash
- name: Authenticate
env:
FLOX_AUTH_TOKEN: ${{ secrets.FLOX_AUTH_TOKEN }}
run: flox auth login --token "$FLOX_AUTH_TOKEN"
- name: Publish package
run: flox publish -o myorg mypackage
GitLab CI Example
publish:
stage: deploy
only:
- tags
script:
- curl -fsSL https://downloads.flox.dev/by-env/stable/install | bash
- flox auth login --token "$FLOX_AUTH_TOKEN"
- flox publish -o myorg mypackage
Package Metadata Best Practices
Good Descriptions
[build.cli] description = "High-performance log shipper with filtering" # Good: specific, descriptive # Avoid: # description = "My tool" # Too vague # description = "CLI" # Not descriptive enough
Proper Versioning
- •Use semantic versioning: MAJOR.MINOR.PATCH
- •Increment MAJOR for breaking changes
- •Increment MINOR for new features
- •Increment PATCH for bug fixes
Runtime Dependencies
Only include what's actually needed at runtime:
[install] # Build-time only gcc.pkg-path = "gcc" make.pkg-path = "make" # Runtime dependency libssl.pkg-path = "openssl" [build.myapp] runtime-packages = ["libssl"] # Only runtime deps
Related Skills
- •flox-builds - Building packages before publishing, dual-environment workflow
- •flox-environments - Setting up development and runtime environments
- •flox-sharing - Sharing environment definitions (via git or FloxHub) vs publishing packages (binaries/artifacts)