Live feel
Watch the wait.
Real-ish timings from Linux CI on laravel-app with require-dev. puck first, then Composer. The pause is the point.
Replay derived from CI cold install timings (run 34124132162). Stylized pacing for the demo, not a wall-clock replay.
Linux CI
The numbers.
Same run for Composer and puck (34124132162). Lead with warm-wipe. Cold is network-heavy. Scripts and flags live in benches/.
laravel-skeleton --no-dev
Linux CI. Warm-wipe is the honest CI number.
- warm wipecomposer1662 mspuck327 ms
- warm keepcomposer908 mspuck24 ms
- coldcomposer4094 mspuck2029 ms
laravel-app with require-dev
Warm-wipe time is dominated by the optimized classmap dump.
- warm wipecomposer2814 mspuck504 ms
- warm keepcomposer1380 mspuck25 ms
- coldcomposer4422 mspuck1778 ms
Warm-wipe: optimized classmap dump scales with require-dev. Cold: downloads still dominate;overlap_ms is summed download+extract work minus wall clock (mostly HTTP concurrency; skeleton cold was 17611 ms).
How it works
One shelf. Every project.
Packages settle into a shared store under ~/.puck/store. Linking them into vendor/ is nearly free. Two apps can share the same bytes on disk.
- laravel/frameworksha...
- nesbot/carbonsha...
- symfony/http-foundationsha...
- illuminate/supportsha...
- laravel/framework → store
- nesbot/carbon → store
- symfony/http-foundation → store
- laravel/framework → store
- nesbot/carbon → store
- pestphp/pest → store
- Land onceEach archive extracts into a content-addressed store. Same bytes never unpack twice.
- Link cheapProjects hardlink or reflink from the store into vendor/. That directory looks normal to PHP, IDEs, and Docker — but those files share inodes with ~/.puck/store, so do not hand-edit vendor/.
- Stay nativeInstall is a Rust binary. Composer stays installed so you can switch back any time.
Before you switch
Run doctor first.
Keep Composer installed. puck reads and writes the same files, and you can switch back at any time.
$ puck doctor
warning: script `Composer\Config::disableProcessTimeout` is a Class::method callback puck skips or runs differently
info: PHP /usr/bin/php (8.4.23) (from PATH)
info: store ~/.puck/store — warm (index non-empty)
info: optimize-autoloader=true
ready to switch| Area | Status |
|---|---|
| composer.json / lock | Supported |
| Composer + path repos | Supported |
| install / require / remove / update | Supported |
| Pest + phpstan Tier 1 adapters | Supported |
| vcs / artifact / package repos | Not in 0.1 |
| Windows | Not in 0.1 |
| Broader plugin host | Not in 0.1 |
| Replace Composer entirely | Not planned |
Install
One binary. Same files.
macOS and Linux. Installs into ~/.puck/bin. Upgrade later with puck upgrade. Manifest truth stays on GitHub Releases.
curl -fsSL https://puck.jimmyverburgt.com/install | bashbrew tap VerburgtJimmy/puck https://github.com/VerburgtJimmy/puck
brew install puck- uses: VerburgtJimmy/puck/.github/actions/setup-puck@v0.1.1
with:
version: latestdocker build \
--build-arg PUCK_VERSION=v0.1.1 \
--build-arg TARGET=x86_64-unknown-linux-musl \
-t puck:0.1.1 .
# then: COPY --from=puck:0.1.1 /puck /usr/local/bin/puck

