Pumas Library is a shared AI asset library for people and applications that need one dependable place to store model files, track metadata, and manage downloads. It is available both as a desktop application and as a headless Rust library with cross-language bindings.
The core idea is simple: stop treating model storage as app-by-app glue code. Pumas gives you a single library that can be searched, repaired, linked into downstream tools, and embedded into other software without rebuilding the same filesystem, networking, and metadata logic over and over.
- Centralize model weights and metadata instead of duplicating them across tools
- Keep downloads resumable and library state repairable after interruptions
- Search and inspect a large local library with structured metadata and full-text indexing
- Embed the same core behavior into desktop apps, services, and language bindings
- Package a desktop experience and a reusable backend from the same codebase
rust/crates/pumas-core: the core headless libraryrust/crates/pumas-rpc: the Rust sidecar/backend used by the desktop shellrust/crates/pumas-uniffi: UniFFI bindings surfacerust/crates/pumas-rustler: Rustler bindings for Elixir/Erlangfrontend/: the React UIelectron/: the desktop shell and packaging configurationbindings/: generated binding artifacts and packaging outputs
- Shared model library with SQLite-backed metadata and FTS5 search
- Hugging Face search, metadata fetch, and resumable download support
- Model import with hashing and type detection
- Library reconciliation and repair flows for drifted on-disk state
- Link and mapping support so consumer tools can reference a central library
- Cross-process discovery and primary/client coordination over local IPC
- Network resilience with caching, retries, and circuit breaking
- Cross-language access through Rust, Python, C#, Kotlin, Swift, Ruby, and Elixir/Erlang
Supported model families include text, diffusion, embedding, audio, and vision workloads, with metadata and indexing designed for mixed libraries rather than a single runtime.
The Rust API runs in one of two transparent modes:
Primary: owns the local state, runs the IPC server, and manages the library directlyClient: discovers an existing primary instance and proxies requests to it
That design lets multiple processes share one library safely while presenting the same public API either way.
Key implementation pieces:
- SQLite for metadata storage and full-text search
- Local JSON-RPC over TCP for cross-process API access
- A global registry for instance and library discovery
- Best-effort startup behavior so registry or IPC failures do not block initialization
The desktop launcher has one shared CLI contract with thin platform wrappers:
# Linux / macOS
./launcher.sh --install
./launcher.sh --build-release
./launcher.sh --run# Windows PowerShell
./launcher.ps1 --install
./launcher.ps1 --build-release
./launcher.ps1 --runIf PowerShell blocks local scripts on Windows, use:
powershell -ExecutionPolicy Bypass -File .\launcher.ps1 --helpUse the same lifecycle flags on both wrappers:
| Flag | Purpose |
|---|---|
--install |
Install workspace dependencies |
--build |
Build debug artifacts |
--build-release |
Build release artifacts |
--run |
Run the desktop app in development mode |
--run-release |
Run the built desktop runtime |
--test |
Run the canonical launcher-facing verification flow |
--release-smoke |
Launch the release runtime briefly and fail if startup is not healthy |
--help |
Show launcher usage |
Note: --run expects the release backend binary to exist, so build first with
--build-release.
Packaged desktop builds try to reuse an existing launcher root by walking up
from the packaged binary location. If you need to pin a specific existing
library root, set PUMAS_LAUNCHER_ROOT=/path/to/root before launching the app.
Add the core crate:
[dependencies]
pumas-library = { path = "rust/crates/pumas-core" }Minimal example:
use pumas_library::PumasApi;
#[tokio::main]
async fn main() -> pumas_library::Result<()> {
let api = PumasApi::new("/path/to/pumas").await?;
let models = api.list_models().await?;
println!("Found {} models", models.len());
let search = api.search_models("llama", 10, 0).await?;
println!("Search found {} results", search.total_count);
Ok(())
}Alternative initialization styles are also available through PumasApi::builder(...) and PumasApi::discover().
When the filesystem and SQLite metadata drift apart, run the integrity repair example:
cd rust
cargo run --package pumas-library --example repair_library_integrity -- /path/to/shared-resources/modelsThis flow is intended for recovery scenarios such as interrupted downloads, stale index rows, and partial content that needs to be reconciled back into canonical library state.
Two binding paths are supported:
UniFFIfor Python, C#, Kotlin, Swift, and RubyRustlerfor Elixir/Erlang
Generate bindings with:
./scripts/generate-bindings.sh python
./scripts/generate-bindings.sh csharp
./scripts/generate-bindings.sh elixir
./scripts/generate-bindings.sh allUseful binding validation and packaging helpers:
./scripts/check-uniffi-csharp-smoke.sh
./scripts/package-uniffi-csharp-artifacts.shGenerated outputs are written under bindings/.
corepack pnpm install --frozen-lockfile
cd rust
cargo build --release
cd ..
npm run -w frontend build
npm run -w electron buildFrom electron/:
| Command | Output |
|---|---|
npm run package:linux |
AppImage and .deb |
npm run package:win |
Windows installer and portable executable |
npm run package:mac |
DMG |
| Platform | Status | Notes |
|---|---|---|
| Linux (x64) | Full support | Primary packaging target |
| Windows (x64) | Full support | Installer and portable outputs |
| macOS (ARM) | Best-effort | Build support exists, regular testing is lighter |
Before cutting a release, run:
corepack pnpm install --frozen-lockfile
./launcher.sh --test
./launcher.sh --release-smoke
cd rust
cargo test --workspace --exclude pumas_rustler
cargo clippy --workspace --exclude pumas_rustler -- -D warnings
cargo build --workspace --exclude pumas_rustler
cd ..
npm run -w frontend test:run
npm run -w frontend check:types
npm run -w frontend build
npm run -w electron validate
npm run -w electron buildUse the same launcher flags with ./launcher.ps1 on Windows. The underlying
cargo and npm validation commands are the same there.
For pumas_rustler, run its checks on a machine with Erlang/OTP installed.
- Rust, Node, and the workspace package manager are pinned in
rust-toolchain.toml,.node-version, and the rootpackage.json - The desktop app is built from the React frontend plus the Electron shell plus the Rust
pumas-rpcsidecar - The canonical desktop workflow is the shared launcher contract exposed by
launcher.shon Unix andlauncher.ps1on Windows - The repository contains both reusable library code and end-user application packaging
Pumas-Library/
├── rust/
│ └── crates/
│ ├── pumas-core/
│ ├── pumas-rpc/
│ ├── pumas-uniffi/
│ └── pumas-rustler/
├── frontend/
├── electron/
├── bindings/
├── scripts/
└── .github/workflows/
MIT
