MANUAL

RakuPM Manual

A comprehensive, authoritative reference for raku-pm โ€” from first install to advanced contributor workflows.

Version 0.77.0 | Quick start | Architecture deep dive | Commands wiki | ไธญๆ–‡็‰ˆ

Table of Contents

1. Overview

RakuPM is a teaching package manager for the Raku programming language. It is a fully functional MVP (~3,700 lines of Raku, 40 library modules + 1 CLI entry point) modelled on the layered, pluggable architecture of zef.

RakuPM can:

  • Discover, resolve, download, build, test, and install Raku packages from ecosystem indexes (zef, REA, CPAN) and local directories

  • Install directly from git URLs with full recursive dependency resolution

  • Manage multiple repository indexes with priority ordering and offline caching

  • Perform atomic installs with transaction rollback (generations)

  • Detect system native libraries (:from<native>) across Windows, macOS, and Linux

  • Author and publish packages via a complete producer-side workflow

  • Self-upgrade via a two-stage bootstrap mechanism

Key Design Principles

PrincipleDescription
Layered, pluggable architectureModeled on zef; each module has a single, well-defined responsibility
zef compatibilitySame META6.json format, spec string syntax, CUR::Installation target, upload protocol
Multi-version coexistenceMultiple versions of the same package live side-by-side; use :ver<> selects the right one
Atomic installsAll-or-nothing: if any package in the tree fails, the target is restored to its prior state
Content-addressed storePackages are stored with MD5 digests for tamper detection
Zero external dependencies (beyond 4)MD5 is pure-Raku; UI is pure-Raku; no build system beyond META6.json

2. Prerequisites

RequirementVersionNotes
Rakudo6.d or laterThe Raku compiler
Gitany recentRequired for git installs, self-upgrade

Runtime dependencies (auto-installed by zef)

PackagePurpose
JSON::FastJSON parsing/generation
HTTP::TinyishHTTP client (system curl backend)
URIURI parsing

MD5 is implemented in pure Raku (RakuPM::MD5), so no ecosystem dependency is needed for content digests.

3. Installation

Option A: Run from source (recommended)

This is the most robust method โ€” it avoids version mismatches when you have multiple Rakudo installs.

git clone https://gitee.com/skyter10086/raku-pm.git
cd raku-pm
raku bin/raku-pm.raku --help    # prints help => environment is OK

Every invocation uses raku bin/raku-pm.raku [command] (or raku -Ilib bin/raku-pm.raku [command] if the lib directory is not auto-detected).

Optionally, create a shell wrapper for convenience:

# bash / zsh
cat > ~/.local/bin/raku-pm <<'EOF'
#!/usr/bin/env bash
exec raku "$HOME/raku-pm/bin/raku-pm.raku" "$@"
EOF
chmod +x ~/.local/bin/raku-pm

Option B: Install as a global command via zef

git clone https://gitee.com/skyter10086/raku-pm.git
cd raku-pm
zef install .

This gives you a raku-pm command on PATH. On Windows, zef generates raku-pm.exe under site/bin.

Gotcha: a legacy zef wrapper swallows raku-pm --help (its *% named-parameter signature takes --help for itself); the wrapper raku-pm generates itself does not (see the section at the end of ยง17). Prefer raku-pm help. The default output is a compact command index (one screen); raku-pm help <command> shows one command, raku-pm help <group> shows a whole group (e.g. raku-pm help author for the publishing commands), and raku-pm help all the full manual.

Set environment variables

export RAKUPM_REPO=repo              # local repo root
export RAKUPM_TARGET=$HOME/.raku-pm  # install root (store/ + site/ + lockfile)

Both directories are created automatically on first run.

After installing a package, put inst#<target>/site on the module search path:

export RAKULIB="inst#$HOME/.raku-pm/site"
raku -e 'use File::Temp; say tempfile'

Run raku-pm env to print the exact export lines for your current prefix.

4. Configuration

4.1 Environment Variables

Environment variables control runtime behavior. They are listed in full in Section 19. The most commonly used:

VariablePurposeDefault
RAKUPM_TARGETInstall prefix (store / site / lockfile / git-cache)~/.raku-pm
RAKUPM_REPOLocal repository root. (cwd)
RAKUPM_ECOSYSTEMEcosystem index URL(s), comma/semicolon-separated(none; when unset, built-in default is zef+cpan+rea+local; setting it overrides the built-in indexes)
RAKULIBModule search path (must include inst#<target>/site)(none)
RAKUPM_OFFLINEOffline mode (1/true/yes/on)(off)
RAKUPM_NO_COLORDisable color output(off)
NO_COLORDisable color (industry standard)(off)

4.2 Config Files

FileLocationPurpose
repositories.json<target>/repositories.jsonPersisted repository configuration
installed.json<target>/installed.jsonLedger of installed packages
raku-pm.lock$CWD/raku-pm.lock (default)Lockfile for reproducible installs
credentials.json<target>/credentials.jsonAPI key storage for ecosystem upload
META6.jsonDistribution rootPackage identity (name, version, provides, depends)

4.3 Global Options

Every command recognizes these options:

OptionDescription
--target=<dir>Override $RAKUPM_TARGET for this invocation
--no-lockSkip the cross-process file lock (dangerous if another process writes)
--promote-bin / --no-promote-binWhether to place the bin wrapper on the global PATH
--offlineAlias for RAKUPM_OFFLINE=1; no network requests

5. Core Concepts

5.1 The Target Directory Layout

$RAKUPM_TARGET/                   default ~/.raku-pm
โ”œโ”€โ”€ cache/                        ecosystem indexes + downloaded tarballs & unpack dirs
โ”‚   โ”œโ”€โ”€ index-360.zef.pm.json
โ”‚   โ””โ”€โ”€ dist/<dist>/<version>/
โ”œโ”€โ”€ store/                        source snapshots: multiple versions coexist, only grows
โ”‚   โ””โ”€โ”€ <dist>/<version>/
โ”‚       โ”œโ”€โ”€ META.json             raku-pm's normalised metadata
โ”‚       โ”œโ”€โ”€ META6.json            Raku standard metadata (what CUR reads)
โ”‚       โ”œโ”€โ”€ lib/                  sources
โ”‚       โ”œโ”€โ”€ resources/            resources (native .so/.dll build output lives here)
โ”‚       โ”œโ”€โ”€ build.json            build-trace sidecar
โ”‚       โ””โ”€โ”€ .digest               content digest (MD5, tamper detection)
โ”œโ”€โ”€ site/                         โ˜… the live CompUnit::Repository::Installation
โ”‚   โ”œโ”€โ”€ precomp/                  precompilation, managed by Rakudo
โ”‚   โ””โ”€โ”€ dist/                     per-distribution metadata (multiple versions coexist)
โ”œโ”€โ”€ installed.json                raku-pm's installed ledger
โ”œโ”€โ”€ raku-pm.lock                  lockfile (in the target by default; also $CWD)
โ”œโ”€โ”€ generations/                  generation snapshots (for rollback)
โ”œโ”€โ”€ git-cache/                    git clone cache
โ””โ”€โ”€ log/<dist>/<version>/         test output logs

Key distinction: store/ vs site/

  • store/ is the source cache โ€” one download can be deployed repeatedly; reinstalling after an uninstall never re-downloads from the network.

  • site/ is the runtime โ€” the CompUnit::Repository::Installation that Rakudo's use resolves from.

5.2 Multiple Version Coexistence

Raku's use Foo (without a version constraint) always loads the highest installed version. raku-pm's design embraces this:

  • install adds each version to site/ without removing older ones.

  • installed.json records all installed versions.

  • To use a specific version, write use Foo:ver<1.2.3> in your code, or use --only to remove higher versions.

Downgrade caveat: Installing an older version does not switch use over by default. It just adds another version alongside. To make the old version active, either upgrade Foo --version=X --only or use :ver<> in code.

5.3 The Ledger (installed.json)

The ledger is the single source of truth for "what is installed." Every entry carries:

  • name, version, auth, api โ€” identity

  • provides โ€” which modules this distribution provides

  • digest โ€” content hash for tamper detection

  • source-dir โ€” the source directory in the store (for reinstalls)

  • reason โ€” explicit (user requested) or dependency (pulled in as a dependency)

The reason field powers autoremove: only dependency-reasoned packages are reclaimed when nothing depends on them anymore. Packages you explicitly installed are never reclaimed.

6. Command Reference

6.1 Package Operations

install

Install a package and all its dependencies.

raku-pm install <module|url|path> [options]

Targets:

  • Module name: install File::Temp

  • Spec string: install 'Foo:ver<1.2.3>:auth<zef:x>'

  • Git URL: install https://github.com/user/repo.git

  • Local directory: install . or install /path/to/dist

Options:

FlagDescription
--version=XPin an exact version
--lockedStrict lockfile mode; abort if lock disagrees
--no-testSkip the test phase
--no-buildSkip the build phase
--no-test-depsDo not install test dependencies
--no-native-checkSkip native library detection
--forceRe-run everything, even if already installed
--allow-test-failureInstall even if tests fail (use with caution)
--test-timeout=SPer-test timeout in seconds (default: 300)
--dryResolve only; do not install
--lock-file=<path>Use a specific lockfile
--pin=Mod@ver[,โ€ฆ]Pin specific dependency versions

Spec string precedence: --version > :ver<> in the spec > the positional constraint.

Examples:

raku-pm install File::Temp                           # latest from ecosystem
raku-pm install 'Concurrent::Stack:ver<1.1>'         # exact version
raku-pm install 'Concurrent::[email protected]'              # @ shorthand (same thing)
raku-pm install Concurrent::Stack --version=1.1      # flag form
raku-pm install https://github.com/user/repo.git     # from git
raku-pm install .                                    # current directory
raku-pm install Web::App --dry                       # resolve only
raku-pm install File::Temp --no-test                 # skip tests

upgrade

Upgrade installed packages to a newer version.

raku-pm upgrade                # upgrade ALL installed packages
raku-pm upgrade <module>       # upgrade one to latest
raku-pm upgrade <module> --version=X  # upgrade/downgrade to specific version
raku-pm upgrade --only         # after upgrade, remove all other versions
raku-pm upgrade --dry          # preview only

upgrade without a package name follows the apt upgrade / zef upgrade convention.

uninstall

Remove installed packages.

raku-pm uninstall <module>                    # remove ALL versions
raku-pm uninstall <module> --version=X        # remove only that version
raku-pm uninstall <module> --keep-store       # keep source snapshot in store
raku-pm uninstall <module> --recursive        # also remove reverse dependencies
raku-pm uninstall <module> --force            # ignore reverse dependency checks

Behavior:

  • Without --version: removes all versions from site/, the ledger, and the lockfile; deletes associated store/ snapshots.

  • With --version=X: X is either an exact version (removes only that one) or a semver constraint string โ€” removing every matching version at once: ranges like <1.0 / >=1.0, <2.0, the wildcard *, at-least 0.2+, and the npm-style sugar ^1.0 (compatible) / ~1.2 (approximately). Snapshots of the removed versions are deleted too (add --keep-store to keep them for instant reinstalls).

  • Reverse dependency check: by default, refuses if other packages depend on it. Use --recursive to remove dependents, or --force to break dependencies.

  • Exit code (since 0.87.3): returns 0 only when something was actually removed. All four cases below return 1 with the reason on stderr, so scripts can tell (raku-pm uninstall X && โ€ฆ / set -e): package not installed, requested version doesn't exist, range matched no installed version, refused because of reverse dependencies. Before the fix all four printed "uninstalled X" and returned 0 โ€” a false success is worse than no message at all.

Sugar upper bounds follow npm semantics (one bound was computed too loosely and fixed in 0.87.2): ^1.2.3 โ†’ <2.0.0, ^0.2.3 โ†’ <0.3.0, ^0.0.3 โ†’ <0.0.4; ~1.2 and ~1.2.3 โ†’ <1.3.0, ~1 โ†’ <2.0.0. The authoritative list is the sugar matrix in t/version.t (both bounds asserted).

Pre-release ordering (0.87.3) follows semver 2.0.0 ยง11: 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-beta < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0. When in doubt, installed <module> shows the resulting order.

reinstall

Remove and re-install the same version.

raku-pm reinstall <module> [--version=X] [--force] [--dry]

If the package was never installed, this behaves like a normal install. Options mirror install.

fetch

Download the source without installing.

raku-pm fetch <module> [--to=dir] [--version=X]

Useful for populating a local directory repository: fetch to ./my-dists, then repos add ./my-dists.

test

Run tests only (no install).

raku-pm test [path]              # defaults to current directory

build

Run the build phase only (no install).

raku-pm build [path]             # defaults to current directory

6.2 Query Commands

All query commands are read-only and modify nothing on disk.

CommandSyntaxDescription
listraku-pm listList all installable packages across all repos
searchraku-pm search <keyword>Search packages (fuzzy match + relevance ranking)
installedraku-pm installed [module]List installed packages and versions
storeraku-pm store [module]View the package source store
versionraku-pm version [module]Show raku-pm's version, or a module's installed version
whichraku-pm which [module]Without args: cross-repo conflict overview; with module: where it loads from
inforaku-pm info <package>Detailed package metadata
browseraku-pm browse <package>Open homepage in browser
locateraku-pm locate <module>Find the on-disk file path of a module
whyraku-pm why <module>Dependency resolution diagnostics
dependsraku-pm depends <module>Forward dependency tree
rdependsraku-pm rdepends <package>Reverse dependencies (who depends on this)
outdatedraku-pm outdatedList packages with available upgrades
lockraku-pm lockDisplay lockfile contents
verifyraku-pm verify [--content] [--fix]Verify content integrity + install consistency
nativeraku-pm native <lib> [--paths]Check if a system native library is present

verify's content check: native MD5 + a manifest cache (0.86.0). Per-file MD5 used to dominate it (pure-Raku MD5 runs at ~0.16 MB/s โ€” 296 files take 10.9s; parallelism and multiple processes were both measured and do not help). There are now two levels of speed-up: โ‘  NativeCall calls the system libcrypto MD5() directly (pure Raku is the fallback on machines without the library); โ‘ก each store entry keeps a .files.json manifest so files whose size and mtime are unchanged reuse last time's MD5. Measured: forced full hashing 11.7s โ†’ 2.9s, ~1.9s when the manifest hits. The trade-off, stated plainly: a modification that also restores the original size and mtime is not detected โ€” for suspected tampering set RAKUPM_VERIFY_NOCACHE=1 (and RAKUPM_MD5=raku to compare against the pure-Raku implementation). No OpenSSL installation is required: the native path uses the system libcrypto (bundled on macOS, present on most Linux distros via the curl/git dependency chain, hit-or-miss on Windows โ€” where it additionally tries the copy shipped with Git for Windows, libcrypto-3-x64.dll) and silently falls back to pure Raku otherwise โ€” same digests, just slower. --content means "content check only, skip install-consistency".

Spec string support: search, installed, store, version, and fetch all accept spec strings for version/author filtering:

raku-pm search 'JSON::Fast:ver<1.0+>'
raku-pm installed 'Foo:ver<1.0>'
raku-pm installed 'Foo:auth<zef:x>'
raku-pm store '[email protected]'

Matching rules:

  • search: fuzzy match + relevance ranking (name exact > prefix > substring > module)

  • store / installed: exact match (exact dist name or module name)

  • install: indexed exact module-name lookup

6.3 Repository Management

raku-pm repos                         # list configured repos
raku-pm repos add <alias|url|path>    # add a repository
raku-pm repos add <name> --name=X     # add with custom alias
raku-pm repos remove <name|url>       # remove a repository
raku-pm repos update [name]           # force-refresh index cache(es)
raku-pm update [name]                 # alias for repos update

Built-in aliases: zef, rea, cpan, p6c.

See Section 10 for detailed repository system documentation.

6.4 Version & Release Management

bump

Increment the version in META6.json and prepend a Changes entry.

raku-pm bump                      # default: --patch (0.1.0 โ†’ 0.1.1)
raku-pm bump --minor              # 0.1.0 โ†’ 0.2.0
raku-pm bump --major              # 0.1.0 โ†’ 1.0.0
raku-pm bump 2.5.0                # exact version
raku-pm bump --to=2.5.0           # same, explicit
raku-pm bump --date=2026-09-15    # set the heading date
raku-pm bump --dry                # preview only

generations

List install generations (atomic install snapshots).

raku-pm generations

rollback

Roll back to a previous generation.

raku-pm rollback                   # go back one generation
raku-pm rollback <generation-id>   # go back to a specific generation

See Section 13 for how generations work.

6.5 Maintenance & Cleanup

clean / gc

Reclaim cache and unreferenced store entries.

raku-pm clean                      # dry run (default)
raku-pm clean --yes                # actually delete
raku-pm clean --all --yes          # also reclaim index + git caches
raku-pm clean --name=Foo           # only Foo-related entries
raku-pm clean --older-than=30      # only entries untouched for 30 days

Safety boundary: Only versions referenced by none of these are deleted:

  1. The installed.json ledger

  2. The live site/ directory

  3. The lockfile

  4. Generation manifests

clean never deletes any "still installed" version โ€” including old ones you want gone. Use uninstall --version=X to remove old versions (which also cleans their store snapshots).

flush

Wipe the entire prefix (start over).

raku-pm flush                      # dry run
raku-pm flush --yes                # delete everything raku-pm installed in this prefix

Unlike clean, flush has no protection โ€” it removes everything. After a flush, there is no raku-pm command left; reinstall via zef install . or run from source.

autoremove

Reclaim packages that are no longer needed.

raku-pm autoremove --dry           # preview
raku-pm autoremove                 # remove orphaned dependencies

autoremove loops until convergence: removing a package can orphan its own dependencies, which are then also reclaimed. Packages you explicitly installed are never reclaimed.

6.6 Self Management

self-upgrade

Upgrade raku-pm itself.

raku-pm self-upgrade                   # upgrade if a newer version exists
raku-pm self-upgrade --force           # reinstall even if already up to date
raku-pm self-upgrade --from=<git-url>  # pull from a specific remote
raku-pm self-upgrade --dry             # preview only

Source priority (two paths):

  1. --from-dir <dir> โ€” install straight from a local source directory (no clone; also the entry point of the bootstrap's second stage)

  2. git remote โ€” --from <url>, or the default upstream https://gitee.com/skyter10086/raku-pm.git

After upgrading, old versions are automatically pruned from site/, store/, and the ledger (only the newest version is kept).

self-upgrade without --force skips pruning when the version is already current. Use --force to force a reinstall + prune.

self-remove

Uninstall raku-pm itself.

raku-pm self-remove --dry        # preview
raku-pm self-remove              # remove raku-pm entirely

Does more than uninstall RakuPM: also removes store/, bin wrappers, and ledger entries.

6.7 Utility Commands

CommandDescription
envPrint RAKULIB / PATH setup instructions for the current prefix
shellPrint an eval-able shell environment export line
doctorRun a comprehensive health check (RAKULIB, PATH, residual staging, consistency, version)
completions <shell>Generate shell completions for bash, zsh, fish, or pwsh
preflightPre-commit gate check (same as CI)
smoke [packages...]Fetch source and run tests; without args, smoke all installed distributions

6.8 Author / Producer Commands

These commands operate on a distribution directory you are developing.

raku-pm new <module> [--into=dir] [--auth=] [--version=] [--with-readme] [--bin=<x>] [--force] [--dry]
raku-pm refresh [path] [--dry]
raku-pm check [path] [--remote]
raku-pm dist [path] [--to=dir] [--no-build] [--dry]
raku-pm bump [path] [--to=X.Y.Z|--major|--minor|--date] [--dry]
raku-pm publish [path] [--remote] [--from=tar.gz] [--to=repo-dir] [--no-build] [--force] [--quiet] [--dry]
raku-pm login [--username=] [--password=] [--api-key=] [--quiet]
raku-pm logout

See Section 17 for the full authoring workflow.

6.9 Command Aliases

Short forms for convenience:

AliasFull CommandAliasFull Command
iinstallun / rmuninstall
upupgradeupdupdate
rireinstalllslist
liinstalledinfinfo
depdependsrdep / rdepsrdepends
ssearchttest
bbuildffetch
docdoctoroutoutdated
gen / gensgenerationsrbrollback
arautoremovenatnative
vfyverifyststore
wwhicheenv
shshellloclocate
brbrowsewhwhy
suself-upgradesrself-remove
reporeposlklock
smsmoke

7. The Install Pipeline

Every install follows this seven-phase pipeline:

resolve โ†’ fetch โ†’ build โ†’ store โ†’ test โ†’ install (activate) โ†’ lock
PhaseWhat happensCan skip with
resolveLook up which distributions provide the target module; pick the highest matching version; expand dependencies recursively; topological sort into bottom-up orderโ€”
fetchDownload the tarball (ecosystem) or point at a directory (local/git); unpack into cache/dist/โ€”
buildIf Build.pm or META6 builder exists, run it in a subprocess--no-build
storeAdmit sources into the content-addressed store with MD5 digestโ€”
testRun t/*.t and t/*.rakutest against the source directory--no-test
activateHand the distribution to CompUnit::Repository::Installation to write into site/; update the ledgerโ€”
lockWrite exact versions + digests into the lockfileโ€”

What is atomic: phases 3โ€“7 (store through lock) are wrapped in a single transaction. If any package fails, the target is restored to its pre-run state. Only when everything succeeds is a generation recorded.

Git installs follow the same pipeline. The target package's sources come from the clone directory instead of a repository, but all other phases are identical.

Local directory installs (install .) also follow the same pipeline. The directory is appended to the end of the dependency chain.

8. Dependency Resolution

The resolver (RakuPM::Resolver) is the heart of the package manager. It performs:

  1. Recursive DFS over the dependency graph starting from the target module.

  2. Per-version provides checking โ€” handles the "provides drift" problem where a module moves between distributions across versions (e.g., NativeLibs in DBIish before 0.6.2, standalone after).

  3. Conflict detection โ€” when the same module is required with incompatible constraints, the error message shows the full chain of requesters.

  4. Cycle detection โ€” mutual dependencies are noted and warned about, but not fatal. The topological sort places unresolvable cycles at the end.

  5. Topological sort (Kahn's algorithm) โ€” dependencies are installed before their dependents.

Ranking candidates

When multiple distributions provide the same module:

  1. A distribution whose name matches the module name wins (e.g., NativeLibs module โ†’ NativeLibs distribution).

  2. Then higher version (real semver, not string comparison).

  3. Then name, lexicographically (for stable, reproducible results).

Constraint syntax

SpellingMeaning
Foo:ver<1.2.3>Exactly 1.2.3
[email protected]@ shorthand, same as above
Foo --version=1.2.3The flag form
Foo:ver<1.2+>At least 1.2 (zef's + suffix)
Foo:ver<>=1.0>Greater than or equal to 1.0
Foo:ver<>1.0>Greater than 1.0
Foo:ver<<=1.0>Less than or equal to 1.0
Foo:ver<<1.0>Less than 1.0
Foo:ver<>=1.0, <2.0>Range: 1.0 โ‰ค x < 2.0
Foo:ver<*> / Foo:ver<>Any version
Foo:ver<1.2.3>:auth<zef:x>Version + author filter

:auth<> actually filters โ€” it is not parsed and ignored. A mismatched auth is a hard error.

Diagnostic: why

raku-pm why <module>

Outputs which distributions were considered, why they were rejected, and what constraint led to the final choice. Uses Resolver.explain-all() for non-fatal diagnostics.

9. Version Management

Multiple versions

raku-pm installs into CompUnit::Repository::Installation, which natively supports multiple coexisting versions. Installing version 2.0.0 does not remove version 1.0.0.

$ raku-pm installed Foo
  ยท Foo 1.0.0
  * Foo 2.0.0      โ† use Foo picks this (highest)

The * marker indicates the "active" version โ€” what use Foo loads.

Pinning

raku-pm install Foo --version=1.0.0    # install a specific version
raku-pm install Foo [email protected]      # pin a dependency version

Downgrading

Raku's use Foo always picks the highest version. Installing an older version adds it alongside but does not make it active. To actually switch:

raku-pm upgrade Foo --version=1.0.0 --only   # remove higher versions
# or use version constraint in code: use Foo:ver<1.0.0>

Lockfile

raku-pm lock                           # display lockfile contents
raku-pm install Foo --locked           # strict mode: abort if lock disagrees

The lockfile is written to $CWD/raku-pm.lock by default (Cargo.lock style), so it can be committed for reproducible installs.

10. Repository System

How repositories work

raku-pm queries an ordered list of repositories for package metadata. When resolving a dependency, it asks every repository and merges the results by the ranking rules in Section 8.

Repository types

TypeBackendDescription
EcosystemRepository::EcosystemRemote JSON index (zef, REA, CPAN, p6c)
LocalRepository::LocalLocal directory containing distribution subdirectories

Built-in repository aliases

AliasIndex URLRecordsNotes
zefhttps://360.zef.pm~8kCurrent versions
reaโ€ฆ/Raku/REA/main/META.json~15kArchive, includes old versions
cpanโ€ฆ/ugexe/Perl6-ecosystems/master/cpan1.json~2kPerl6 modules on CPAN
p6cโ€ฆ/ugexe/Perl6-ecosystems/master/p6c1.jsonโ€”Legacy archive

922 distributions exist only in REA and not in zef โ€” a single index cannot install everything.

Configuration precedence (high โ†’ low)

  1. $RAKUPM_TARGET/repositories.json โ€” maintained by repos add/remove

  2. RAKUPM_ECOSYSTEM env var โ€” comma/semicolon separated, each entry an URL or alias

  3. Default: the zef index + the local $RAKUPM_REPO directory

Adding local directory repos

A local directory repo holds one subdirectory per distribution, each with META6.json + lib/:

raku-pm repos add ~/my-dists                  # add local directory
raku-pm fetch HTTP::Client --to=~/my-dists    # populate it

Resilient index fetching

If a repository index cannot be fetched:

SituationBehavior
Fetch failed, old cache existsReuse cache, warn "may be stale"
Fetch failed, never cachedTreat as empty index, warn "results may be incomplete"

A warning never silently hides a missing module โ€” it says the module may exist but is currently unreachable.

Index caching

Indexes are cached locally with conditional GET (ETag / If-None-Match). The TTL is controlled by RAKUPM_INDEX_TTL. Once expired, raku-pm asks the server once (and very likely gets a 304 Not Modified).

11. Lockfile & Reproducibility

The lockfile (raku-pm.lock) records exact versions and content digests:

{
  "version": 1,
  "entries": [
    { "name": "JSON", "version": "2.0.0", "auth": "demo:raku",
      "digest": "d47078e2...", "depends": [] }
  ]
}

Committable lockfile workflow

cd my-project
raku-pm install JSON               # pins exact versions into ./raku-pm.lock
git add -f raku-pm.lock            # commit it (-f bypasses .gitignore)
# teammate, after cloning:
raku-pm install --locked           # strictly reuses locked versions
  • --lock-file=<path> relocates the lockfile (useful in CI).

  • install / reinstall / self-upgrade / lock all accept --lock-file.

  • The lockfile is independent of --target: even with a separate prefix, the lock stays in the project root.

12. Native Library Detection

raku-pm does not ship system libraries. Before installing, it checks whether the required native libraries are present on the system.

What is checked

  • :from<native> dependencies in META6.json

  • Runtime is native('...') calls scanned from lib/ and bin/ source files

  • :from<bin> and :from<Perl5> external dependencies (reported but never block install)

Per-OS file name mapping

Logical nameWindowsmacOSLinux
sqlite3sqlite3.dlllibsqlite3.dyliblibsqlite3.so
ssllibssl-3-x64.dlllibssl.dyliblibssl.so
libffilibffi-8.dlllibffi.dyliblibffi.so
zlibzlib1.dlllibz.dyliblibz.so
unknown foofoo.dlllibfoo.dyliblibfoo.so

Per-OS search paths

OSSearch paths
WindowsPATH โ†’ System32/SysWOW64 โ†’ vcpkg installed/*/bin
macOSDYLD_LIBRARY_PATH โ†’ /opt/homebrew/lib (Apple Silicon) โ†’ /usr/local/lib (Intel) โ†’ /opt/local/lib (MacPorts) โ†’ /usr/lib
LinuxLD_LIBRARY_PATH โ†’ /usr/local/lib, /usr/lib โ†’ Debian multiarch dirs โ†’ versioned .so.N

Per-distro install commands

When a library is missing, raku-pm suggests the install command for your Linux distribution:

Distro familyPackage managerExample
Debian/Ubuntuaptapt install libsqlite3-dev
Fedora/RHELdnfdnf install sqlite-devel
Archpacmanpacman -S sqlite
Alpineapkapk add sqlite-dev
openSUSEzypperzypper install libsqlite3-devel

Querying native libraries

raku-pm native sqlite3                              # check if present
raku-pm native ssl curl --paths                     # multiple at once, show search paths
raku-pm native --installed                          # scan lockfile for declared libs
raku-pm native sqlite3 --os=linux --distro=ubuntu   # simulate another platform

Platform-conditional dependencies

META6.json can use by-distro.name to declare platform-specific dependencies:

{
  "depends": [{
    "name": {
      "by-distro.name": {
        "": "",
        "mswin32": "Win32::Registry"
      }
    }
  }]
}

Only the branch matching $*DISTRO.name (or the "" fallback) is resolved. On Linux, Win32::Registry is not fetched.

13. Atomic Install & Generations

How atomic install works

  1. All packages are staged into a shared temporary CUR (target/stage/pending).

  2. Tests run against the staging CUR.

  3. If everything passes, packages are promoted to the real site/ + ledger + bin wrappers.

  4. If anything fails, the staging area is discarded โ€” the real CUR is never touched.

raku-pm install A       # A depends on B โ†’ order [B, A]
  B installed into staging CUR โœ“
  A's tests fail โœ—
  โ†’ rollback: staging discarded; B removed; target is back to its prior state

Generations

After a successful atomic install, a generation is recorded in target/generations/:

target/generations/
โ”œโ”€โ”€ current                  current generation id
โ”œโ”€โ”€ 000001/
โ”‚   โ”œโ”€โ”€ before.json          ledger snapshot before the transaction
โ”‚   โ”œโ”€โ”€ manifest.json        ledger after commit
โ”‚   โ””โ”€โ”€ meta.json            timestamp, what was installed
โ””โ”€โ”€ 000002/...

The 10 most recent generations are kept. Generations are cheap โ€” they are a few KB of JSON, not a copy of the entire site/.

Rolling back

raku-pm generations                  # list available generations
raku-pm rollback                     # go back one generation
raku-pm rollback 000003              # go back to a specific generation

Rollback removes the versions installed by the targeted generation from the CUR and restores the ledger. Older versions that were never removed remain intact.

Limitation: Rolling back to a generation whose sources have been removed from the store by clean warns and skips. Don't gc aggressively if you might need to roll back.

14. Caching & Cleanup

What gets cached

CategoryLocationSize impact
Store snapshotsstore/<dist>/<version>/Grows over time (every upgrade leaves a snapshot)
Download cachecache/dist/Tarballs + unpacked trees
Index cachecache/index-*.json~10 MB per index
Git clone cachegit-cache/Per-repo clones
Precompiled artifacts.precomp inside store entriesRebuilt on demand
Test logslog/<dist>/<version>/Per-test-file output

Cleanup with clean

clean is protective GC โ€” it only deletes versions that are not referenced by any of: the ledger, site/, the lockfile, or generation manifests.

raku-pm clean                       # dry run: see what would be reclaimed
raku-pm clean --yes                 # actually delete
raku-pm clean --all --yes           # also reclaim index + git caches
raku-pm clean --name=Foo            # only Foo-related entries
raku-pm clean --older-than=30       # only entries untouched for 30 days

Nuclear option: flush

flush wipes everything raku-pm installed in the current prefix with no protection. Use only when starting over from scratch.

Reclaiming orphaned dependencies

raku-pm autoremove                  # remove packages no longer depended on
raku-pm autoremove --dry            # preview

Loops until convergence: removing a package can orphan its own dependencies.

15. Concurrency & File Locking

Multiple raku-pm processes running simultaneously can corrupt the store and lockfile. To prevent this, every write command acquires a cross-process file lock:

$ raku-pm install Foo          # while another terminal installs something else
โณ Another raku-pm is writing to /home/user/.raku-pm, waiting...

Lock details

AspectBehavior
Mechanismflock (OS-reclaims on process death; no stale locks)
Lock filetarget/.raku-pm.run.lock (holds no state)
Timeout600s default (RAKUPM_LOCK_TIMEOUT)
Re-entrantReference-counted within one process; nested calls don't self-deadlock
Child-process tokenRandom token passed to child processes; they skip the lock
Escape hatch--no-lock or RAKUPM_NO_LOCK=1 (dangerous; use only when sure nothing else is running)

Tests run serially during install

As of 0.80.0, tests run serially (each test file in its own subprocess โ€” process- isolated, but not sandboxed). Tests used to run concurrently by default, but keeping concurrency from harming installs required two extra safety nets (a serial precomp warm-up plus a serial re-verify of failed cases) โ€” complexity that does not pay off for a single-machine teaching tool, so the whole concurrency mechanism has been removed (and the --test-jobs flag with it).

PhaseConcurrent?
Resolve / download / build / store / stage / promote to siteSerial (one distribution at a time, bottom-up)
Running test filesSerial (file by file, process-isolated)
Cross-process (two raku-pm runs at once)Serial โ€” via the file lock above

The only automatic retry: serial re-verify of failures

A case that failed the first run is re-run serially once, and only counts as a real failure if it fails again. This is the one concession to flaky upstream tests โ€” e.g. Concurrent::Stack 1.3's stress case fails 3 runs out of 10 (an upstream race). That is an upstream bug, but a user should not be unable to install a package over a probabilistic failure. The re-verify log is written to <name>.flake.log and does not overwrite the first-run failure log.

Residual risks (stated honestly)

RiskWhat it means
Re-verify also fails โ†’ judged a real failure โ†’ whole chain rolls backDependencies already built in this run are discarded too (store versions remain)
The upstream test is itself flakye.g. Concurrent::Stack 1.3's stress case; fails serially too โ€” the re-verify absorbs one attempt
A single test file is slowSerial means slow cases add up wall-clock time, possibly hitting --test-timeout (300s default)

Knobs

raku-pm install Foo --test-timeout=900    # relax the per-file timeout
raku-pm install Foo --allow-test-failure  # install even if tests fail (soft pass)
raku-pm install Foo --no-test             # skip tests entirely

Env vars: RAKUPM_TEST_TIMEOUT.

Two further soft-pass paths: explicit --allow-test-failure, and failures recognised as a known Windows upstream bug (a deliberately narrow match: specific dist + specific test file + failure signature) โ€” the latter does not hide real bugs.

16. HTTP Layer

All network traffic goes through the RakuPM::HTTP facade, which delegates to the single backend:

BackendUnder the hoodNotes
RakuPM::HTTP::TinyishHTTP::Tinyish (system curl)the only backend; best TLS/proxy support

As of 0.82.0 there is a single backend: the pure-Raku HTTP::Tiny fallback and the RAKUPM_HTTP_BACKEND / register-backend pluggable machinery have been removed.

Features

  • Retry with exponential backoff + jitter on transient failures

  • Proxy support via HTTPS_PROXY / HTTP_PROXY environment variables

  • Conditional GET with ETag / If-None-Match (304 reuses cache)

  • Debug observability via RAKUPM_HTTP_DEBUG

  • Multipart upload for ecosystem publishing

17. Authoring & Publishing

The producer-side workflow follows this sequence:

new โ†’ refresh โ†’ check โ†’ dist โ†’ publish

1. Scaffold a new distribution

raku-pm new Foo::Bar                                    # create Foo-Bar/
raku-pm new Foo::Bar --into=MyProj                      # custom directory name
raku-pm new Foo::Bar --with-readme --bin=foo --auth=github:me --version=0.2.0
raku-pm new Foo::Bar --dry                              # preview only

Creates: META6.json, lib/Foo/Bar.rakumod, t/01-basic.rakutest, Changes, .gitignore, optionally README.md and bin/<x>.raku.

2. Rebuild provides from disk

raku-pm refresh              # rebuild provides for the current directory
raku-pm refresh ./some-dist  # target a specific directory
raku-pm refresh --dry        # preview only

After adding/renaming modules under lib/, the provides in META6.json may no longer match. refresh scans lib/ and rebuilds provides automatically. It only touches provides โ€” everything else is preserved verbatim.

3. Pre-flight check

raku-pm check                 # local-only, instant, offline
raku-pm check ./some-dist     # target a specific directory
raku-pm check --remote        # also check if the version is already published online

Checks: META6.json valid, name present, version โ‰  *, auth matches RAKUPM_AUTHOR_AUTH, provides matches disk, bin scripts exist, dependencies parseable.

Any hard error ([โœ—]) exits non-zero, so this drops directly into a CI publish gate.

4. Package the sdist

raku-pm dist                  # package current directory
raku-pm dist ./some-dist      # target a specific directory
raku-pm dist --no-build       # skip the build phase
raku-pm dist --to=../out      # place the tarball under ../out
raku-pm dist --dry            # preview only

Runs the check gate first (any hard error is rejected). If a Build.pm exists, it is executed inline (native extension compilations land in the tarball). The output is a source distribution tarball (no precompiled bytecode).

5. Deploy

Local directory repo:

raku-pm publish --to=../my-dists                       # deploy to local repo
raku-pm publish --from=../out/Foo-1.0.0.tar.gz --to=../my-dists  # reuse existing package
raku-pm publish --dry                                   # preview only

Remote ecosystem:

raku-pm login --api-key=<key>          # store the API key
raku-pm login --username=me --password=secret  # online login to 42.zef.pm
raku-pm publish --remote --dry         # preview the upload request
raku-pm publish --remote               # actually upload

After publishing, another machine can raku-pm repos add <repo> and raku-pm install <name>.

18. Troubleshooting

Module not found

ๅœจๆ‰€ๆœ‰ๅทฒ้…็ฝฎ็š„ไป“ๅบ“้‡Œ้ƒฝๆ‰พไธๅˆฐๆจกๅ— 'Foo'

Possible causes:

  • The module isn't in the default zef index. Try raku-pm repos add rea for broader coverage.

  • A repository index couldn't be fetched. Check for โš  warning lines above the error.

  • Typo in the module name. Try raku-pm search <partial-name>.

"Another raku-pm is writing" timeout

A previous raku-pm process may be hanging. The lock is auto-released when the process exits (or is killed). If the lock file is stale:

rm $RAKUPM_TARGET/.raku-pm.run.lock

Or wait up to 600s for the lock to time out.

Native library not found

โœ— sqlite3  ๆœชๆ‰พๅˆฐ โ€” ๆœฌ็ณป็ปŸ้œ€่ฆ libsqlite3.so / libsqlite3.so.0
  ๅฎ‰่ฃ…๏ผšapt install libsqlite3-dev

Install the system library using the suggested command, or use --no-native-check to skip the check (the library will still fail to load at runtime).

RAKULIB shadowing

If RAKULIB is exported globally (from your shell profile), plain raku will load raku-pm's own copy of RakuPM from site/. If that copy is old, tests may appear to fail on the current code.

Safe habits:

  • Run tests via raku tools/run-suite.raku (it passes -I<worktree>/lib and self-checks).

  • Run a single file as raku -Ilib t/<x>.t (-I comes before RAKULIB).

  • Check which copy loads: raku-pm which RakuPM::Version

use Foo:ver<1.2.3> loads the wrong version

The inst# prefix is mandatory in RAKULIB. Without it, Rakudo treats site/ as an ordinary filesystem repository and ignores version metadata:

export RAKULIB="inst#$HOME/.raku-pm/site"   # correct
# NOT: export RAKULIB="$HOME/.raku-pm/site"  # wrong

raku-pm --help may be swallowed under PowerShell

Bottom line first: --help works with the wrapper raku-pm generates itself โ€” measured, raku-pm --help and raku-pm -h both print help and exit 0 (the local wrapper is site/bin/raku-pm.ps1, which forwards @args verbatim to the entry). Only a legacy zef wrapper (raku-pm.exe, whose *% named-parameter signature claims --help for itself) swallows it โ€” that .exe is renamed to <name>.zef-old at install/upgrade time, see the next section.

Prefer raku-pm help: it works under every wrapper flavour and supports the levels (raku-pm help <command> / raku-pm help <group> / raku-pm help all).

raku-pm version shows the old version after upgrade

The zef-era raku-pm.exe (.EXE outranks .BAT in PATHEXT) may shadow the new wrapper. The entry check at install/upgrade renames it to <name>.zef-old. If the issue persists, run raku-pm env to see which entry point actually executes.

Debug mode

RAKUPM_DEBUG=1 raku-pm <command>    # full backtrace on failure
RAKUPM_HTTP_DEBUG=1 raku-pm <command>  # HTTP request/response details

19. Environment Variables Reference

VariablePurposeDefault
RAKUPM_TARGETInstall prefix (store/site/lockfile)~/.raku-pm
RAKUPM_REPOLocal repository root. (cwd)
RAKUPM_ECOSYSTEMEcosystem index URL(s), comma/semicolon-separated(none; when unset, built-in default is zef+cpan+rea+local; setting it overrides the built-in indexes)
RAKULIBModule search path(none)
RAKUPM_OFFLINEOffline mode (1/true/yes/on)(off)
RAKUPM_NO_COLORDisable color output(off)
NO_COLORDisable color (industry standard)(off)
RAKUPM_HTTP_DEBUGHTTP debug logging(off)
RAKUPM_INDEX_TTLIndex cache TTL(configurable)
RAKUPM_LOCK_TIMEOUTCross-process lock timeout (seconds)600
RAKUPM_NO_LOCKSkip write lock (1)(off)
RAKUPM_LOCK_TOKENInternal: child-process lock token(auto)
RAKUPM_TEST_TIMEOUTPer-test timeout (seconds)300
RAKUPM_TEST_LOG_DIRTest log root directory<target>
RAKUPM_TEST_PROGRESSTest progress display (0=off, 1=on)auto (TTY detection)
RAKUPM_PUBLISH_REPODefault publish target directory(none)
RAKUPM_API_KEYEcosystem upload API key(none)
RAKUPM_AUTHOR_AUTHAuthor identity for publishingzef:skyter10086
RAKUPM_CURLOverride curl binary pathsystem curl
RAKUPM_DEBUGFull backtrace on failure(off)
RAKUPM_CI_XTCI: set to 0 to skip extended tests(on)
HTTPS_PROXY / HTTP_PROXYProxy settings for HTTP requests(none)
DYLD_LIBRARY_PATHmacOS library search path(none)
LD_LIBRARY_PATHLinux library search path(none)

20. Config Files Reference

repositories.json

Located at $RAKUPM_TARGET/repositories.json. Maintained by repos add/remove. Structure:

[
  { "name": "zef", "url": "https://360.zef.pm", "type": "ecosystem" },
  { "name": "local", "url": "/path/to/local-repo", "type": "local" }
]

installed.json

Located at $RAKUPM_TARGET/installed.json. The ledger of all installed packages. Each entry includes identity, provides, digest, source directory, and install reason.

raku-pm.lock

Located at $CWD/raku-pm.lock (default). Records exact versions and content digests for reproducible installs. Committable to version control.

credentials.json

Located at $RAKUPM_TARGET/credentials.json. Stores API keys for ecosystem upload. Created by raku-pm login.

META6.json

The distribution manifest. Key fields:

{
  "name": "My-Dist",
  "version": "1.0.0",
  "auth": "github:me",
  "api": "1",
  "description": "A brief description",
  "license": "Artistic-2.0",
  "provides": { "My::Dist": "lib/My/Dist.rakumod" },
  "depends": [ "JSON::Fast" ],
  "test-depends": [ "Test" ],
  "build-depends": [],
  "bin": { "my-tool": "bin/my-tool.raku" },
  "source-url": "https://github.com/me/my-dist"
}

21. Contributing

Running tests

# Full test suite (same code path as CI):
raku tools/run-suite.raku

# Without extended tests (no network/heavy tests):
raku tools/run-suite.raku --no-xt

# Docs-only check:
raku tools/run-suite.raku --docs-only

# Filter by name:
raku tools/run-suite.raku --filter=native

# Do not print per-test timings / slowest list (for clean CI logs):
raku tools/run-suite.raku --no-timings

# Single test file:
raku -Ilib t/version.t

Do NOT use prove6 for test verdicts โ€” it false-flags harmless warnings. The only reliable signal is raku tools/run-suite.raku.

To find out "why the gate is slow", run the full suite and read the timing summary at the end: by default the script prints each test's wall clock, the 15 slowest, the actual t/ xt/ wall clock, the parallel speedup, and the raku -e '' startup baseline with its share of the total. Read it from both ends: a high startup share means the bottleneck is process count (merging test files helps); a low share means the bottleneck is the heavy tests themselves and how they are scheduled โ€” look at the top of the slowest list. Measured on this machine (8 jobs, 135 tests): the 0.22s startup baseline is just 2% of the total while the average test takes 14.2s, so this project falls in the latter case. Also, a speedup well below the --jobs value usually means "long tests sitting at the tail of a batch while only one or two still run", not that parallelism failed.

How the suite is scheduled: t/ and xt/ sit in a single pool and are dispatched by descending historical wall clock (LPT) โ€” the longest test starts first and short tests fill the gaps it leaves; the pool is then split across lanes that run independently (there is no "wait for the whole layer" barrier โ€” whoever runs dry first picks up the next test). As a result tests appear interleaved in the log (a per-directory summary is printed at the end). The old "per-directory batches by filename" scheme let long tests land at the tail of a batch while only one or two were still running: measured 2.83x with 8 jobs. Timings are cached at ~/.raku-pm/suite-timings.json and only affect dispatch order.

Pre-commit hook

raku tools/install-hooks.raku    # install the git pre-commit hook

The hook runs tools/run-suite.raku --no-xt (same gate as CI).

CI pipeline

The Gitee Go pipeline (.workflow/master-pipeline.yml) triggers on push to master, runs on a self-hosted agent, and executes raku tools/run-suite.raku.

Code structure

bin/raku-pm.raku           CLI entry point (argument parsing, command dispatch)
lib/RakuPM/Client.rakumod  Orchestrator (coordinates all other modules)
lib/RakuPM/Resolver.rakumod Dependency resolver
lib/RakuPM/Installer.rakumod Store โ†’ CUR activation
lib/RakuPM/Repository/     Pluggable repository backends
lib/RakuPM/HTTP/           Dual-backend HTTP layer
lib/RakuPM/UI.rakumod      Terminal display (colors, tables, CJK alignment)
lib/RakuPM/Version.rakumod Semver parsing and comparison
lib/RakuPM/Spec.rakumod    Install spec string parser
lib/RakuPM/Author.rakumod  Producer-side commands

Architecture overview

bin/raku-pm.raku (CLI)
  โ†’ RakuPM::Client (Orchestrator)
    โ†’ RakuPM::Resolver (Dependency Resolution)
      โ†’ RakuPM::Repository (role, pluggable backends)
        โ†’ Repository::Local
        โ†’ Repository::Ecosystem
    โ†’ RakuPM::Store (Content-Addressed Storage)
    โ†’ RakuPM::Installer (Activation into CUR::Installation)
    โ†’ RakuPM::Builder (Build Phase)
    โ†’ RakuPM::Lock (Lockfile)

See architecture.en.md for the full deep dive.

22. FAQ

Q: How is raku-pm different from zef?

raku-pm is modelled on zef's architecture but implemented from scratch as a teaching tool. Key differences: raku-pm is ~3,700 lines (zef is much larger), has atomic installs with generation rollback, includes a native library detector with per-OS probing, and implements the full authoring workflow. zef is the production-grade package manager; raku-pm is designed to teach how one works.

Q: Can raku-pm and zef coexist?

Yes. They install into separate locations (~/.raku for zef vs $RAKUPM_TARGET/site for raku-pm). Raku's multi-version design means two versions of the same module can live side by side.

Q: What happens if I install a package that zef already installed?

They coexist. If both install the same version, use picks the one on RAKULIB first (raku-pm's site). raku-pm which shows which copy actually loads.

Q: Why are there two copies in store/ and site/?

store/ is a download cache (one download, many deployments; reinstalling never re-downloads). site/ is the runtime (what use resolves from). This mirrors Cargo's registry/cache + src design.

Q: Can I use a spec string with query commands?

Yes. search, installed, store, version, and fetch all accept spec strings like Foo:ver<1.2+> or [email protected] for version/author filtering.

Q: What does --only do on upgrade?

It removes all versions higher than the target after upgrading. This is how you make a downgrade actually take effect (Raku's use always picks the highest version).

Q: How do I contribute?

See Section 21: Contributing. The project uses Gitee for hosting; contributions follow standard fork โ†’ branch โ†’ PR workflow. All PRs must pass raku tools/run-suite.raku.

A. Appendix: Exit Codes

CodeMeaning
0Success
1Business failure (test failed, native lib missing, usage error, etc.)

Business failures print a clean user-facing message and exit 1 without printing internal stack traces. Set RAKUPM_DEBUG=1 to see full backtraces.

B. Appendix: Spec String Syntax

Spec strings are the zef-compatible way to specify a module with version and/or author constraints. They are accepted by install, search, installed, store, version, and fetch.

Supported forms

FormExampleMeaning
Module onlyFooAny version
With :ver<>Foo:ver<1.2.3>Exactly 1.2.3
With :ver<> + +Foo:ver<1.2+>At least 1.2
With @ shorthand[email protected]Exactly 1.2.3
With :auth<>Foo:auth<zef:x>Specific author
CombinedFoo:ver<1.2.3>:auth<zef:x>:api<1>Version + author + API

Shell quoting

The <> in :ver<> is a shell redirection operator. Quote the entire string:

  • bash/zsh: search 'Foo:ver<1.2+>'

  • Windows cmd: Use the @ shorthand instead: search [email protected]+

  • PowerShell: Same as bash โ€” quote the string

Fallback

If the ver part is not a valid constraint (e.g., search Foo@bar), the whole input falls back to a plain keyword search.

C. Appendix: Platform Behavior Matrix

FeatureWindowsmacOSLinux
Native lib suffix.dll.dylib.so
Native lib prefix(none)liblib
Shell wrapper.bat + .ps1bashbash
Default search pathsPATH, System32, vcpkgDYLD_LIBRARY_PATH, Homebrew, MacPortsLD_LIBRARY_PATH, multiarch dirs
sort -V supportN/A (uses bash)No (fallback to lexicographic)Yes
site/bin promotion.exe โ†’ .bat rename checkDirect copyDirect copy
File lockingLockFileEx (mandatory)flockflock
PATHEXT.EXE outranks .BATN/AN/A

This manual covers raku-pm version 0.77.0. For the latest changes, see Changes. For questions and issues: https://gitee.com/skyter10086/raku-pm/issues

RakuPM v1.0.3

ไธ€ไธชๆ•™ๅญฆ็”จ็š„ Raku ๅŒ…็ฎก็†ๅ™จ๏ผšๅคš็ดขๅผ•ไป“ๅบ“ใ€ไพ่ต–่งฃๆžใ€่ทจ็ณป็ปŸๆœฌๅœฐๅบ“(:from<native>)ๆŽขๆต‹ใ€ๅ†…ๅฎนๅฏปๅ€ๅญ˜ๅ‚จใ€้”ๆ–‡ไปถใ€ๅ•็‰ˆๆœฌๆฟ€ๆดปใ€ๅ•ๅŽ็ซฏ HTTP ๅฎขๆˆท็ซฏ๏ผˆcurl๏ผ‰ใ€็ดขๅผ• TTL ไธŽ็ฝ‘็ปœ้‡่ฏ•

Authors

  • skyter10086

License

Apache-2.0

Dependencies

Test Dependencies

Provides

  • RakuPM::Author
  • RakuPM::Builder
  • RakuPM::CLI
  • RakuPM::Cleaner
  • RakuPM::CliCheck
  • RakuPM::CliSpec
  • RakuPM::Client
  • RakuPM::Client::Flusher
  • RakuPM::Client::Git
  • RakuPM::Client::Query
  • RakuPM::Client::SelfManager
  • RakuPM::Client::Tester
  • RakuPM::Distribution
  • RakuPM::FileLock
  • RakuPM::Fs
  • RakuPM::HTTP
  • RakuPM::HTTP::Backend
  • RakuPM::HTTP::Tinyish
  • RakuPM::Help
  • RakuPM::InstallOptions
  • RakuPM::Installer
  • RakuPM::Installer::Generations
  • RakuPM::Installer::ShellTemplates
  • RakuPM::Ledger
  • RakuPM::Lock
  • RakuPM::MD5
  • RakuPM::Message
  • RakuPM::NativeLib
  • RakuPM::Net
  • RakuPM::Platform
  • RakuPM::Prefix
  • RakuPM::Repositories
  • RakuPM::Repository
  • RakuPM::Repository::Ecosystem
  • RakuPM::Repository::Local
  • RakuPM::Repository::Matching
  • RakuPM::Resolver
  • RakuPM::Spec
  • RakuPM::Store
  • RakuPM::UI
  • RakuPM::Version

The Camelia image is copyright 2009 by Larry Wall. "Raku" is a trademark of the Yet Another Society. All rights reserved.

Built with Podlite โ€” the markup and publishing tools behind this site.