Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Cli Laravel Package

puli/cli

The command-line interface for Puli, the PHP package discovery and management system. Inspect packages, resolve resource paths, manage repositories, and integrate package discovery into your PHP projects from the terminal.

Deep Wiki
Context7

Getting Started

puli/cli installs the puli binary that manages a puli.json file and the .puli/ repository cache. Puli gives your application a virtual filesystem of paths (e.g. /app/assets/logo.png, /acme/blog/views/index.twig) that resolve to real files wherever Composer put them — this is what the CLI is for.

Minimal setup:

# project-local (recommended)
composer require --dev puli/cli

# the binary lands here
vendor/bin/puli --help

Initialize a project once:

vendor/bin/puli init                 # writes puli.json, asks for package name
vendor/bin/puli map /app/assets public/assets
vendor/bin/puli build                # generates the repository cache in .puli/

Look at these first, in order:

  1. puli.json — the only source of truth; bindings, mappings and config live here.
  2. vendor/bin/puli help and puli help <command> — the command set is small (init, map, bind, publish, build, type, resolve).
  3. .puli/repository.php — the generated cache your runtime code loads.

First real use case: you have assets under public/ (or web/) that live inside vendor/ packages, and you want them addressable by a stable Puli path instead of hard-coded relative filenames. puli map /app/assets public/assets + puli publish /app/assets public/assets gets you there in two commands.

Implementation Patterns

Map, don't hard-code filesystem paths. Every directory or file you want to reach by Puli path needs a map entry. Do this per package:

puli map /acme/blog/views src/Acme/Blog/Resources/views
puli map /acme/blog/public src/Acme/Blog/Resources/public

Bindings are how vendor packages become addressable. A package only appears by its Puli name if it has its own puli.json and is bound:

puli bind acme/blog vendor/acme/blog

Once bound, /acme/blog/... resolves regardless of Composer's install path.

Publishing is a deployment step, not a build step. For web-exposed assets:

puli publish /app/assets public/assets            # copy
puli publish /app/assets public/assets --symlink  # symlink (Linux/macOS)
puli publish --force /app/assets public/assets    # overwrite

Use --symlink in dev so edits are live; use copy in production so the webroot is self-contained. Publish is idempotent enough to run every release.

Rebuild after every config change. puli build regenerates .puli/repository.php. Any script that mutates mappings must end with a build:

puli map /app/docs docs && puli build

Wire it into Composer scripts so the cache never goes stale:

"scripts": {
  "post-install-cmd": ["puli build"],
  "post-update-cmd": ["puli build"],
  "post-autoload-dump": ["puli build"]
}

This also matters because the Composer plugin discovers packages during install — bindings added by a dependency are only visible after a fresh build.

Runtime lookup stays tiny. Application code should only resolve paths, not know about puli.json:

$puli = Puli\Manager\Api\Puli::create();
$repository = $puli->getRepository();
$file = $repository->get('/acme/blog/views/index.twig')->getFilesystemPath();

Custom resource types. If you need to load resources from a non-filesystem backend (database, remote), puli type registers the resource type and the corresponding loader/factory class, keeping the path abstraction consistent across the app. This is the main legitimate extension point of the CLI.

Team workflow: commit puli.json; gitignore .puli/. Let CI run puli build before tests so the cache matches the checked-in config.

Gotchas and Tips

  • Abandoned project. Last release 2016, mid-PHP-7 era. Expect deprecation warnings and possible fatal errors on PHP 8. If you inherit a Puli project, your real job is usually migrating away rather than extending — Symfony's AssetMapper, Composer's files autoload, or plain realpath() calls cover most of what Puli did.
  • Stale cache is the #1 bug. If a path suddenly "does not exist," run puli build before touching anything else. The repository is a serialized snapshot, not a live view of the filesystem.
  • puli.json is per-project. Puli bindings from dependencies are only picked up because puli/composer-plugin runs discovery during composer install/update. Run a plain composer dump-autoload without the plugin and discovery silently does nothing.
  • --symlink breaks on Windows and on filesystems that don't support links. Default to copy in CI, symlink only on dev machines.
  • Publish target directory must be writable and, for real web use, inside the document root. Puli will happily publish to vendor/ and you'll wonder why the browser 404s.
  • Path precedence: when two mappings overlap (e.g. /app/assets and /app/assets/img), the more specific mapping wins for resources under it, but the merge order can surprise you. Keep mappings non-overlapping where possible; puli resolve /app/assets/img/x.png shows the final target and is your debugger.
  • Use puli resolve and -vvv. puli resolve <path> prints the filesystem target; puli -vvv <cmd> explains discovery and build steps. Both beat reading the cache file by hand.
  • Config precedence: project puli.json overrides the global ~/.puli/puli.json. If a binding appears that you never declared, check whether a dependency's puli.json or a global config is supplying it.
  • Permissions on .puli/: the cache is written at build time and read at runtime by the web user. Build as the deploy user (or the same UID that serves requests) or you'll hit unreadable-cache errors only in production.
  • No first-class lockfile semantics. Bindings and mappings are declarative but there's no resolution conflict report; if two packages claim the same Puli name, the CLI won't warn loudly. Naming conventions matter more here than in Composer.
  • Don't build the CLI into runtime code. puli/cli belongs in require-dev; the runtime only needs puli/manager (and the repository cache). Shipping the CLI to production adds a binary and a plugin you'll never invoke.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core