App::C...d::run(3pm)
πΈ App::Cme::Command::run
okay so bestie, this is the App::C...d::run(3pm) manual page π β yeah the title got chopped by your terminal, it's giving "my window is this small" energy π. The real name is App::Cme::Command::run, and we are about to run some cme scripts together. Grab a boba π§, sit criss-cross, let's go.
π NAME
App::Cme::Command::run - Run a cme script
β¨ VERSION
version 1.049
π¦ SYNOPSIS
okay so first, a little main-character demo of what a cme script even is. Watch this:
$ cat ~/.cme/scripts/remove-mia
doc: remove mia from Uploaders. Require mia parameter
# declare app to configure
app: dpkg
# specify one or more instructions
load: ! control source Uploaders:-~/$mia$/
# commit the modifications with a message (git only)
commit: remove MIA dev $mia
$ cme run remove-mia -arg mia=longgone@d3bian.org
# cme run can also use environment variables
$ cat ~/.cme/scripts/add-me-to-uploaders
app: dpkg-control
load: source Uploaders:.push("$DEBFULLNAME <$DEBEMAIL>")
$ cme run add-me-to-uploaders
Reading package lists... Done
Building dependency tree
Reading state information... Done
Changes applied to dpkg-control configuration:
- source Uploaders:3: '<undef>' -> 'Dominique Dumont <dod@debian.org>'
# show the script documentation
$ cme run remove-mia -doc
remove mia from Uploaders. require mia parameter
# list scripts
$ cme run -list
Available scripts:
- update-copyright
- add-me-to-uploaders
# mass modification
$ cme run add-me-to-uploaders --foreach "raku-log raku-zef"
# similar result
$ echo "raku-*" | cme run add-me-to-uploaders --foreach -
ate, no crumbs π₯.
π DESCRIPTION
It runs a script written for cme. That's it. That's the vibe.
So, if you hand it a script by name, cme goes hunting through ~/.cme/scripts, /etc/cme/scripts or /usr/share/perl5/Config/Model/scripts π. Like, say you type cme run foo β then cme loads whichever of these it finds first: ~/.cme/scripts/foo, /etc/cme/scripts/foo or /usr/share/perl5/Config/Model/scripts/foo.
But the second you pass an actual path, the searching stops. No search, no scavenger hunt. E.g. cme run ./foo β it just uses what you gave it, periodt.
cme run is super open-minded and accepts scripts written in a bunch of different syntaxes:
π§ cme DSL
For simple scripts! This DSL text specifies the target app, the doc, optional variables and a load string used by Config::Model::Loader or Perl code.
π YAML
Exactly like the text above, but using Yaml syntax. Same energy, different font.
π Perl data structure
Writing Perl code in a text file or in a YAML field can be painful π β because Perl syntax doesn't get highlighted. Rude. So with a Perl data structure, a cme script specifies the target app, the doc, optional variables, and a perl subroutine (more on that below, bestie π).
β plain Perl script
cme run can also run a plain Perl script. It's basically syntactic sugar so you don't go polluting the global namespace β i.e. there's no need to store a script using cme function in /usr/local/bin/. But heads up: the script must begin with the usual shebang line (#!) and be executable. Non-negotiable, that's the law π
.
And to help management with cme run, here's the deal:
- comment lines beginning with
##are shown as doc (withcme run xxx --doc) - comment line beginning with
# app:indicates the app shown bycme run --listcommand
So when run, this script:
- opens the configuration file of
app - applies the modifications specified with
loadinstructions or the Perl code. - save the configuration files
- commits the result if
commitis specified (either in script or on command line).
See App::Cme::Command::run for details.
π Syntax of text format
The script accepts instructions in the form:
key: value
The key line can be repeated when needed. Yes queen, repeat yourself π .
Multi line values can also be:
--- key
multi line value
---
The script accepts the following instructions:
π app
Specify the target application. Must be one of the application listed by cme list command. Mandatory. Only one app instruction is allowed. One app only, we don't do polyamory here π.
π default
Specify default values that can be used in load or var sections.
For instance:
default: name=foobar
πΈ var
Use Perl code to specify variables usable in this script. The Perl code must store data in %var hash. For instance:
var: my @l = localtime; $var{year} = $l[5]+1900;
The hash %args contains the variables passed with the -arg option. Reading a value from %args which is not set by user triggers a missing option error π¨. Use exists if you need to test if a argument was set by user:
var: $var{foo} = exists $args{bar} ? $args{bar} : 'default' # good
var: $var{foo} = $args{bar} || 'default' # triggers a "missing arg" error
See that second one? That's the villain origin story. Don't do it π.
π¦ load
Specify the modifications to apply using a string as specified in Config::Model::Loader. This string can contain variable (e.g. $foo) which are replaced by command argument (e.g. -arg foo=bar) or by a variable set in var: line (e.g. $var{foo} as set above) or by an environment variable (e.g. $ENV{foo}).
π code
Specify Perl code to run. See "code section" for details.
π₯ commit
Specify that the change must be committed with the passed commit message. When this option is used, cme stashes and restores all modifications if used on a non-clean workspace. This option works only with git. (git girlies rise π«Ά)
Strings like {{ load path }} are substituted with a value extracted from configuration tree with the specified load path. See Config::Model::Loader for a valid load path.
For example, this specification:
load: source Standards-Version="4.7.0"
commit: declare compliance with policy {{source Standards-Version}}
yields this commit message:
declare compliance with policy 4.7.0
String like $some_value are with substituted with a value coming from an environment variable, a script argument or a value defined as a var line.
For example, this specification:
var: $var{close_str} = defined $args{closes} ? " (Closes: #$args{closes})" : ""
commit: set $DEBEMAIL as Maintainer$close_str
invoked with argument -arg closes=1234, yields this commit message:
set dod@example.com as Maintainer (Closes: #1234)
Iconic. No notes. β¨
All instructions can use variables like $stuff whose value can be specified with -arg options, with a Perl variable (from var: section explained above) or with an environment variable:
For instance:
cme run -arg var1=foo -arg var2=bar
transforms the instruction:
load: ! a=$var1 b=$var2
in
load: ! a=foo b=bar
Like, it literally just does the swap. So satisfying π.
π Example
Here's an example from libconfig-model-dpkg-perl scripts (https://salsa.debian.org/perl-team/modules/packages/libconfig-model-dpkg-perl/-/blob/master/lib/Config/Model/scripts/add-me-to-uploaders):
doc: add myself to Uploaders
app: dpkg-control
load: source Uploaders:.insort("$DEBFULLNAME <$DEBEMAIL>")
commit: add $DEBEMAIL to Uploaders
You can find other examples on script directory of libconfig-model-dpkg-perl (https://salsa.debian.org/perl-team/modules/packages/libconfig-model-dpkg-perl/-/blob/master/lib/Config/Model/scripts/)
π§ Code section
The code section can contain variable (e.g. $foo) which are replaced by command argument (e.g. -arg foo=bar) or by a variable set in var: line (e.g. $var{foo} as set above).
When evaluated the following variables are also set:
$rootβ Root node of the configuration (SeeConfig::Model::Node)$instβ Configuration instance (SeeConfig::Model::Instance)$commit_msgβ Message used to commit the modification.
Since the code is run in an eval, other variables are available (like $self) to shoot yourself in the foot. π yeah, foot-shooting privileges included, no extra charge.
For example:
app: popcon
---code
$root->fetch_element('MY_HOSTID')->store($to_store);
---
π Syntax of YAML format
This format is intented for people not wanting to user the text format above. It supports the same parameters as the text format. (Yes, "intented" and "user" β that's how it's written, I don't make the rules π.)
When using ! and $ characters in a string, using YAML block scalar is probably easier.
For instance:
# Format: YAML
---
app: popcon
default:
defname: foobar
var: |-
$var{name} = $args{defname}
load: |-
! MY_HOSTID=$name
β Syntax of Perl format
This format is intended for more complex script where using load instructions is not enough.
This script must then begin with # Format: perl and specifies a hash. For instance:
# Format: perl
{
app => 'popcon', # mandatory
doc => "Use --arg to_store=a_value to store a_value in MY_HOSTID',
commit => "control: update Vcs-Browser and Vcs-Git"
sub => sub ($root, $arg) { $root->fetch_element('MY_HOSTID')->store($arg->{to_store}); }
}
$root is the root if the configuration tree (See Config::Model::Node). $arg is a hash containing the arguments passed to cme run with -arg options.
The sub parameter value must be a sub ref. Its parameters are $root (a Config::Model::Node object containing the root of the configuration tree) and $arg (a hash ref containing the keys and values passed to cme run with --arg options).
Note that this format does not support var, default and load parameters as you can easily achieve the same result with Perl code. π
π Options
π list
List available scripts and exits.
π arg
Arguments for the cme scripts which are used to substitute variables.
πΈ doc
Show the script documentation. (Note that --help options show the documentation of cme run command)
π¦ cat
Pop the hood and show the content of the script. π
π₯ commit
Like the commit instruction in script. Specify that the change must be committed with the passed commit message.
π no-commit
Don't commit to git (even if the above option is set). Boundaries, bestie. β
β foreach
Apply the script in specific directories. This option is available only when dealing with application (See the list returned by cme list).
For instance, if your directory contains several Debian packages and you want to apply the same modification to all packages, you can run something like:
cme run add-me-to-uploaders --foreach "raku-log raku-zef"
or use STDIN to send the package directories:
ls "raku-*" | cme run add-me-to-uploaders --foreach -
Mass modification, but make it a serve π.
π verbose
Show effect of the modify instructions.
π Common options
See "Global Options" in cme.
π update copyright years in debian/copyright π
okay so imagine you're a Debian maintainer and it's January and the copyright years are stale β bestie, this is the script that fixes that. Look:
$ cme run update-copyright -cat
app: dpkg-copyright
load: Files:~ Copyright=~"s/2016,?\s+$name/2017, $name/g"
commit: updated copyright year of $name
the -cat there is just showing you what the script says, she's not doing anything yet π
and then you actually run it and pass your name in like this:
$ cme run update-copyright -arg "name=Dominique Dumont"
cme: using Dpkg::Copyright model
Changes applied to dpkg-copyright configuration:
- Files:"*" Copyright: '2005-2016, Dominique Dumont <dod@debian.org>' -> '2005-2017, Dominique Dumont <dod@debian.org>'
- Files:"lib/Dpkg/Copyright/Scanner.pm" Copyright:
@@ -1,2 +1,2 @@
-2014-2016, Dominique Dumont <dod@debian.org>
+2014-2017, Dominique Dumont <dod@debian.org>
2005-2012, Jonas Smedegaard <dr@jones.dk>
[master ac2e6410] updated copyright year of Dominique Dumont
1 file changed, 2 insertions(+), 2 deletions(-)
see how it literally shows you the diff before committing?? that's the vibe check passing β and then boom, a real commit at the bottom. iconic.
πΈ update VcsGit in debian/control πΈ
next up, the "please stop hand-editing the Vcs- fields" script:
$ cme run set-vcs-git -cat
doc: update control Vcs-Browser and Vcs-git from git remote value
doc: parameters: remote (default is origin)
doc:
doc: example:
doc: cme run set-vcs-git
doc: cme run set-vcs-git -arg remote=debian
app: dpkg-control
default: remote: origin
var: chomp ( $var{url} = `git remote get-url $args{remote}` ) ;
var: $var{url} =~ s!^git@!https://!;
var: $var{url} =~ s!(https?://[\w.]+):!$1/!;
var: $var{browser} = $var{url};
var: $var{browser} =~ s/.git$//;
load: ! source Vcs-Browser="$browser" Vcs-Git="$url"
commit: control: update Vcs-Browser and Vcs-Git
like. she reads your git remote, cleans it up, turns it into a browsable URL, and writes it into debian/control. no cap, that's the whole job π«Ά
and the same script can be written with multi line instructions instead β look at this glow-up:
$ cme run set-vcs-git -cat
--- doc
update control Vcs-Browser and Vcs-git from git remote value
parameters: remote (default is origin)
example:
cme run set-vcs-git
cme run set-vcs-git -arg remote=debian
---
app: dpkg-control
default: remote: origin
--- var
chomp ( $var{url} = `git remote get-url $args{remote}` ) ;
$var{url} =~ s!^git@!https://!;
$var{url} =~ s!(https?://[\w.]+):!$1/!;
$var{browser} = $var{url};
$var{browser} =~ s/.git$//;
---
load: ! source Vcs-Browser="$browser" Vcs-Git="$url"
commit: control: update Vcs-Browser and Vcs-Git
same energy, way better formatting, she ate π
π personal scripts π
and NOW the best part β you can write your own scripts and drop them in ~/.cme/scripts. here's a whole example, literally the entire file:
$ cat ~/.cme/scripts/set-any-arch
app: dpkg-control
load: binary:~".*" Architecture=any
tiny. adorable. devastating. that's a script that sets every binary package's Architecture to any. main character energy fr fr π
π SEE ALSO
cme
(yeah that's it, she's self-referential, she contains multitudes)
βοΈ AUTHOR
Dominique Dumont
π COPYRIGHT AND LICENSE
This software is Copyright (c) 2014-2022 by Dominique Dumont <ddumont@cpan.org>.
This is free software, licensed under:
The GNU Lesser General Public License, Version 2.1, February 1999
and that's a wrap bestie πβ¨ you made it to the end of part 2, I'm so proud of you ππ this page is perl v5.40.1 flavored, dated 2026-06-29, and it's the App::C...d::run(3pm) page β go forth and cme run something slay today π
π¦πΈ
π¦ where this page comes from
- ubuntu stonking: cme 1.049-1 Β· LGPL-2.1-only
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms