A pacman-style package manager for Minecraft server resources. Download, cache,
verify, and deploy server jars, mods, plugins, and resource packs — all driven
by a declarative pacraft.toml and a human-readable pacraft.lock.md.
cargo install --path .Requires Rust 1.85+ (edition 2024).
# Install a server jar
pacraft -S paper -g 1.21.4
# Install a mod from Modrinth
pacraft -S lithium -g 1.21.4 -l fabric
# Install a plugin from Modrinth
pacraft -S luckperms -g 1.21.4 -l paper
# Update everything
pacraft -Syu
# See what changed
pacraft diffPackages land in ./pacraft_cache/. To deploy them to an actual server
directory, add a [target] section to pacraft.toml (see below).
pacraft.toml API (Modrinth, PaperMC, Mojang, …)
│ config │ metadata
▼ ▼
resolve ──► ResolvedPackage ──► download ──► pacraft_cache/
│
pacraft.lock.md ◄── lock entry ◄─────────────────┘
│
▼
deploy ──► ./server/mods/ ./server/plugins/ ./server/
- Resolve — query the appropriate API for version metadata and download URLs
- Download — fetch files into
pacraft_cache/with hash verification and mirror fallback - Lock — record resolved versions, hashes, and file paths in
pacraft.lock.md(Markdown with embedded JSON — git-diff friendly) - Deploy — copy cached files into your server directories
[settings]
download_concurrency = 4
[target]
root = "./server"
server = "." # where server jars go
mods = "mods"
plugins = "plugins"
proxy_plugins = "plugins"
resourcepacks = "resourcepacks"
[repos]
# Optional: override built-in repo types or add custom mirrors
[dependencies]
vanilla = { version = "1.21.4", repo = "mojang" }
paper = { version = "latest", repo = "bmcl" }
lithium = { version = "latest", repo = "modrinth", game_version = "1.21.4", loader = "fabric" }Four repos are always available without explicit configuration:
| Repo | Type | Purpose |
|---|---|---|
mojang |
original |
Direct Mojang/PaperMC/Purpur APIs |
bmcl |
bmclapi |
BMCLAPI mirror (faster in mainland China) |
gh-proxy |
github-proxy |
GitHub proxy mirror |
modrinth |
modrinth |
Modrinth platform API |
You can add custom repos with pacraft repo add <name> --kind <type>.
| Field | Required | Description |
|---|---|---|
version |
yes | "latest", a specific version, or "1.21.4@123" build |
repo |
yes | Which repo section to use for resolution |
game_version |
no | Minecraft version (Modrinth deps only) |
loader |
no | Mod loader: fabric, forge, paper, velocity, etc. |
build |
no | Specific build number (Paper/Purpur/Folia) |
pin |
no | Skip during -Su upgrades |
pacraft -S <name> # install a package
pacraft -S <repo>/<name> # install from a specific repo
pacraft -S paper -g 1.21.4 # with game version and loader hints
pacraft -S lithium -g 1.21.4 -l fabric
pacraft -S <name> --deploy # install then deploy immediately
pacraft -S <name> --force # re-download even if lock matches
pacraft -Su # upgrade all non-pinned deps
pacraft -Syu # refresh PUR registry + upgrade
pacraft -Sy # refresh PUR registry onlypacraft -Q # list repos, configured deps, lock entries
pacraft -Qu # check which dependencies are outdated
pacraft -Qk # verify all cached files against lock hashes
pacraft -Qm # show missing lock/cache/deploy state
pacraft -Ql # list cache and deploy paths for each package
pacraft -Qd # compare deploy target against cache (file-level status)pacraft -Dk # run doctor: config/lock/cache consistency checks
pacraft -Sc # clean orphaned cache files
pacraft -Sc --dry-run # preview what would be cleanedpacraft doctor # same as -Dk
pacraft verify # same as -Qk
pacraft clean # same as -Sc
pacraft clean --dry-run
pacraft deploy # copy cache → target dirs
pacraft deploy --dry-run
pacraft deploy --to ./server # override target root
pacraft deploy <name> # deploy a specific package only
pacraft status # config/lock/cache/deploy overview
pacraft diff # compare cache vs deployed files
pacraft diff --to ./server
pacraft repair # fill in missing deploy files (conservative)
pacraft repair --dry-run
pacraft repo list # list configured repos
pacraft repo add custom --kind bmclapi
pacraft repo remove custompacraft -s <name> # search server versions or Modrinth projects
pacraft -s modrinth:<query> # search Modrinth directly
pacraft -R <name> # remove a dependency
pacraft --pin <name> # pin a dependency to its current version
pacraft --unpin <name> # unpin a dependency
pacraft -G <name> # print a package manifest to stdoutgame_version and version are different concepts:
game_versionis the exact Minecraft environment version filter, such as1.21.4.versionis the package/project version request. For Modrinth packages it may be a SemVer constraint.
Examples:
lithium = { version = "latest", repo = "modrinth", game_version = "1.21.4", loader = "fabric" }
modmenu = { version = "^11.0", repo = "modrinth", game_version = "1.21.4", loader = "fabric" }
luckperms = { version = ">=5.4, <6", repo = "modrinth", game_version = "1.21.4", loader = "paper" }
specific = { version = "id:abcdef123456", repo = "modrinth", game_version = "1.21.4", loader = "fabric" }SemVer support is best-effort: only Modrinth version_number values that parse as SemVer participate in range matching. Non-SemVer labels still work with exact matching or latest. Server jar versions keep exact/latest semantics.
pacraft can resolve and download these server cores directly (no Modrinth
needed):
| Server | API source |
|---|---|
| Vanilla | Mojang piston-meta |
| Paper | PaperMC Fill API v3 |
| Folia | PaperMC Fill API v3 |
| Velocity | PaperMC Fill API v3 |
| Waterfall | PaperMC Fill API v3 |
| Purpur | Purpur API v2 |
| Forge | Forge Maven metadata |
| Mohist | MohistMC API v2 |
| Youer | MohistMC API v2 |
| Spigot | ServerJars API |
| Bukkit | ServerJars API |
| Tuinity | ServerJars API |
| CatServer | GitHub Releases |
| authlib-injector | authlib-injector API |
PUR (Package Universal Registry) manifests support multiple source backends:
| Source | Status |
|---|---|
| Built-in servers | implemented |
| Modrinth | implemented (with transitive deps) |
| URL | implemented |
| GitHub Release | implemented |
| Hangar | parsed, API not implemented |
| CurseForge | parsed, API not implemented |
Deploy copies cached files from pacraft_cache/ to your server directories
based on each package's install_kind:
| Install kind | Target directory |
|---|---|
server |
[target].server |
mod |
[target].mods |
plugin |
[target].plugins |
proxy-plugin |
[target].proxy_plugins |
resource-pack |
[target].resourcepacks |
Typical workflow:
pacraft -S lithium --deploy --target ./server
# or in separate steps:
pacraft deploy
pacraft diff
pacraft repair --dry-run
pacraft repairDownloads automatically try mirrors for faster access in mainland China:
BMCLAPI → GitHub proxy → original URL
Mirror rules in mirror.rs rewrite Mojang, Forge, Fabric, and GitHub URLs.
Metadata APIs also respect repo type selection (bmcl uses BMCLAPI endpoints).
deploycopies files; it never moves or deletes cache filesrepaironly copies cache files to missing deploy paths — it never overwrites existing deployed filescleanonly removes orphaned files insidepacraft_cache/and never touches deploy directoriesstatus,diff,repair,-Qm,-Ql, and-Qdare offline (no network)- All deploy paths are validated: no absolute subdirectories, no
..traversal, no path separators in filenames
- Hangar API not yet implemented
- CurseForge API not yet implemented
- SemVer constraints are implemented for Modrinth package versions (best effort)
- No automatic config version bump on upgrade
GPL-3.0-only