Carmel(3)
Carmel(3) π
okay bestie, welcome to the User Contributed Perl Documentation section, because this is Carmel(3) and she is that girl β¨
β¨ NAME β¨
Carmel β your CPAN Artifact Repository Manager π no cap, that's the whole name.
πΈ SYNOPSIS πΈ
here's the vibe, just... all of it, in order, bestie:
# Run with a directory with cpanfile
carmel install
# list all the modules to be loaded
carmel list
# list all the modules in a tree
carmel tree
# show a location where a module is installed
carmel show Plack
# update Plack to the latest
carmel update Plack
# update all the modules in the snapshot
carmel update
# pin modules tp specific versions
carmel update DBI@1.633 Plack@1.0000
# show diffs for cpanfile.snapshot in a nice way
carmel diff
# Runs your perl script with modules from artifacts
carmel exec perl ...
# Requires all your modules in cpanfile in one shot
carmel exec perl -e 'use Carmel::Preload;'
# Roll out the currently selected modules into ./local
carmel rollout
# package modules tarballs and index into ./vendor/cache
carmel package
# use Carmel packages inside a script (without carmel exec)
perl -e 'use Carmel::Setup; ...'
# prints export PATH=... etc for shell scripting
carmel export
# find a module in a repository
carmel find DBI
# find a module matching the version query
carmel find Plack ">= 1.0000, < 1.1000"
(yes, that one comment says tp instead of to β we keep it exactly as it is, we do not touch the sacred text π
)
π DESCRIPTION π
So. Carmel is yet another CPAN module manager. I know, I know, another one. But hear me out π
Here's the thing that makes her different from your traditional CPAN module installer: Carmel keeps the build of all your dependencies in a central repository, and then picks which library paths to include at runtime while you're in development. It's giving β¨organizedβ¨.
And also β and this is the part I'm obsessed with β Carmel lets you rollout all the files into a normal, traditional perl INC directory structure. Which is so useful for production, like in containers π«Ά
π¦ WORKFLOW π¦
π± Development
During development, you run carmel install when you set up a new environment, and honestly also any time you change cpanfile. That updates your build artifacts, and it saves the changes into cpanfile.snapshot. Commit that snapshot file to your version control system so you can reproduce the exact same versions on other machines. fr fr, this is the whole point.
carmel exec makes it easy to run your app using the versions in cpanfile and cpanfile.snapshot, dynamically, no manual path fiddling:
# On your development environment
> cat cpanfile
requires 'Plack', '0.9980';
requires 'Starman', '0.2000';
> carmel install
> echo /.carmel >> .gitignore
> git add cpanfile cpanfile.snapshot .gitignore
> git commit -m "add Plack and Starman"
# On a new setup, or another developer's machine
> git pull
> carmel install
> carmel exec starman -p 8080 myapp.psgi
# Add a new dependency
> echo "requires 'Try::Tiny';" >> cpanfile
> carmel install
> git commit -am 'Add Try::Tiny'
# Update Plack to the latest
> carmel update Plack
look at her go π so clean.
π Production Deployments
Carmel lets you manage all the dependencies the same way across dev environments and production environments. But β and this is a real one β there might be cases where you want to avoid running your app with carmel exec in production. Maybe you want to dodge the overhead of a large number of include paths. Maybe you just don't want to install Carmel on the production hosts at all. Valid. We respect it.
So Carmel gives you two easy ways to avoid depending on Carmel on the deploy target environments:
First: carmel rollout rolls out the build artifacts into a regular perl5 library path in local. Once the rollout is done, you can include that path just like a regular local::lib directory. Iconic.
# Production environment: Roll out to ./local
> carmel rollout
> perl -Ilocal/lib/perl5 local/bin/starman -p 8080 myapp.psgi
You can run carmel rollout in a CI system to create that local directory right next to your application code, for a linux package (like a deb package, bestie) or for Docker containers π³
Second: carmel package (which is similar to carton bundle) creates a directory with tarballs and CPAN-style package index files. You can hand that directory to cpanm on a target machine. This way, all you need is cpanm β which is available as a self-contained single executable β to bootstrap the installation on a host with a stock perl. β¨bootstrappingβ¨
# Vendor all the packages to vendor/cache
> carmel package
> git add vendor/cache
> git commit -m 'Vendor all the tarballs'
# Remote environment (CI etc.)
> git clone https://.../myapp.git && cd myapp
> cpanm -L /path/to/lib --from $PWD/vendor/cache -nq --installdeps .
ate. π
π₯ HOW IT WORKS π₯
Carmel keeps the build directory (aka the artifacts) after a cpanm installation, inside a repository. That repository defaults to $HOME/.carmel/{version}-{archname}/builds, and your directory structure ends up looking like this:
$HOME/.carmel/5.20.1-darwin-2level/builds
Plack-1.0033/
blib/
arch/
lib/
URI-1.64/
blib/
arch/
lib/
URI-1.63/
blib/
arch/
lib/
Carmel scans this directory and builds up the mapping of which version of any given package belongs to which build directory. Lowkey genius.
Given the list of modules and requirements from cpanfile, carmel install computes which versions satisfy the requirements best, and if none of them do, it installs the modules from CPAN and drops them into the artifact repository. The computed mappings are preserved as a snapshot in cpanfile.snapshot.
Once that snapshot exists, every following carmel command uses both cpanfile and cpanfile.snapshot to figure out the best versions to satisfy your requirements. And when you update cpanfile to bump a version or add a new module, carmel installs the new dependencies and updates the snapshot accordingly. She's self-maintaining, we love a main character. π
The carmel exec command β just like the install command β lists the build directories and .pm files you need from the repository, and then prepends the mappings of those files in the @INC hook. Handy way to run a perl program using the dependencies pinned by Carmel, without changing any include path. No cap.
The carmel update command lets you selectively update a dependency while preserving all the other dependencies in the snapshot. carmel update Plack, for example, pulls the latest version of Plack from CPAN (plus its dependencies, if it needs a newer version than the one pinned in the snapshot), and updates the snapshot properly. Running carmel update with no arguments at all updates all the modules in cpanfile, including their dependencies.
On a production environment, you might want to use the carmel rollout command, which saves all the files included in cpanfile β pinned with cpanfile.snapshot β into the local directory. That directory can be included like a regular perl library path, with PERL5LIB=/path/to/local/lib/perl5, or with use lib, and then you don't need to use the carmel command in production at all. π
πΈ SNAPSHOT SUPPORT
As of v0.1.29, Carmel supports saving and loading the snapshot file in cpanfile.snapshot, in a format that's compatible with Carton. Versions saved in the snapshot file get preserved across multiple runs of Carmel across machines β so versions frozen in one environment can be committed to a source code repository, and reproduced on another box. The one condition, bestie: so long as the perl version and architecture is the same. π
π CAVEATS / KNOWN ISSUES π
- If you run multiple instances of
carmel, or if you hit Ctrl-C to interrupt the cpanm install session, Carmel might get into a state where some modules have been installed properly while some modules in the dependency chain are missing. So: make sure you don't run multiple instances ofcarmelat the same time, and let it finish the installation so you get the full builds properly. π - There're certain dependencies that get missed during the initial
carmel install, and you'll see the error messageCan't find an artifact for Foo.
Please report it to the issue tracker if you can reliably reproduce this type of errors.
Usually you run carmel install again and the error will be gone. β¨ (not me gaslighting you, it's just how it is)
- In some situations, you might encounter conflicts in version resolutions β between what's pinned in the snapshot and a new version that's needed when you introduce a new module.
For example, suppose you have:
# cpanfile
requires 'Foo';
requires 'Bar'; # which requires Foo >= 1.001
Without the snapshot, Carmel has no trouble resolving the correct versions for this combination. But if you have:
# cpanfile.snapshot
Foo-1.000
Then the first time you run carmel install, Carmel will try to install Foo-1.000, because that's the version pinned in the snapshot β while also trying to pull in the module Bar, which would conflict with that version of Foo. π
This can happen 50% of the time, because if cpanm (which Carmel calls internally) installs Bar first, then the resolution is done correctly, the version in the snapshot gets skipped, and the snapshot gets updated accordingly. This is due to perl's hash randomization after Perl 5.18. (perl said "let's randomize" and Carmel said "bet") π
To avoid this, you're recommended to run carmel install before making any changes to cpanfile. That puts the build caches in place to satisfy what's in cpanfile and the snapshot. After that, adding a new dependency will likely reuse what's in the build cache, while adding a new dependency can update the transient dependency (for Foo) without having conflicts.
If you do encounter conflicts like this, you can work around it by:
- Running
carmel update Footo pull the latest version of Foo from CPAN, ignoring what's in the snapshot. - Updating
cpanfileto explicitly update the version requirement forFoo.
okay bestie we're not done yet β this page has more coming π
π¦ COMPARISONS WITH SIMILAR TOOLS π¦
okay bestie, let's do the side-by-side thing, because you've probably used one of these before and you deserve to know exactly how Carmel differs π
π Carton
Carmel shares the same goal with Carton, where you can manage your dependencies by declaring them in cpanfile, and pinning them in cpanfile.snapshot. Most of the commands work the same way, so Carmel can most effectively be a drop-in replacement for Carton, if you're currently using it. π
Here's a few key differences between Carmel and Carton:
- Carton does not manage what's currently being installed in
localdirectory. It just runscpanmcommand with-L local, with a hope that nothing has changed the directory except Carton, and whatever is in the directory won't conflict with the snapshot file. This can easily conflict whencpanfile.snapshotis updated by multiple developers or when you continuously update the dependencies across multiple machines. π
Carmel manages all the dependencies for your project in the Carmel repository under $HOME/.carmel, and nothing is installed under your project directory on development. The local directory is only created when you request it via carmel rollout command, and it's safe to run multiple times. Running carmel install after pulling the changes to the snapshot file will always install the correct dependencies from the snapshot file, as compared to Carton, which doesn't honor the snapshot on a regular install command, if whatever version in local already satisfies the version in cpanfile. β¨
- Carton has no easy way to undo a change once you update a version of a module in
local, because which version is actually selected is only preserved as a file inside the directory, that's not managed by Carton. To undo a change you have to remove the entirelocaldirectory to start over. π
Carmel preserves this information to the cpanfile.snapshot file, and every invocation of Carmel resolves the dependencies declared in cpanfile and pinned in cpanfile.snapshot dynamically, to create a stable dependency tree, without relying on anything in a directory under your project other than the snapshot file. Undoing the change in cpanfile.snapshot file immediately reverts the change. π
π cpm
App::cpm is an excellent standalone CPAN installer. no notes, we love them π«Ά
- Like Carton, cpm installs the dependencies declared in
cpanfiletolocal. Carmel installs them into a build cache, and doesn't uselocaldirectory for state management. You can runcarmel rolloutto copy the dependencies tolocaldirectory. π - cpm installs the modules in parallel, which makes the installation very fast. Like Carmel, cpm also manages its build artifacts cache, so a module that has previously been installed would be very fast to install, since there's no build process. β‘
- Unlike Carton and Carmel, cpm doesn't have the ability to manage
cpanfile.snapshotfile on its own. It can read the snapshot however, so it's possible to use Carmel in a development environment, and then usecpm installinstead ofcarmel installandcarmel rollout, if all you need is to build out a perl5 library path out ofcpanfileandcpanfile.snapshotin the source code repository. π
πΈ COMMUNITY πΈ
https://github.com/miyagawa/Carmelβ Code repository, Wiki and Issue Tracker πβ¨
π AUTHOR π
Tatsuhiko Miyagawa <miyagawa@bulknews.net> β the icon, the legend π
β COPYRIGHT β
Copyright 2015- Tatsuhiko Miyagawa
π LICENSE π
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. slay, that's the whole vibe π
π SEE ALSO π
App::cpanminusCarton
iykyk π
and that's the whole page bestie!! π this was Carmel(3) from perl v5.42.0, dated 2025-07-25 β go forth and pin your dependencies, you're gonna eat πβ¨π¦πΈπ
π¦ where this page comes from
- fedora 43: perl-Carmel 0.1.56-23.fc43 Β· GPL-1.0-or-later OR Artistic-1.0-Perl
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms