Version: 2.0.1
Author: Magal Hezi / Pixel Solutions
Original Author: Robert Campbell (calguy1000)
License: GPLv2
Requires: CMSMS 2.2.14+, PHP 7.4+
A standalone CLI tool for managing CMS Made Simple installations from the command line. Designed for automation, scripting, and cron jobs. Distributed as a self-contained .phar file.
# Copy cmscli.phar to your CMSMS root and run from there
cp cmscli.phar /var/www/mysite/
cd /var/www/mysite
php cmscli.phar site-info
# Or install system-wide
cp cmscli.phar ~/bin/cmscli
chmod +x ~/bin/cmscli
cmscli --dir /var/www/mysite site-info| Option | Short | Description |
|---|---|---|
--dir <path> |
-d |
CMSMS installation directory (default: current working directory) |
--help |
-h |
Display help or command list |
--nopermcheck |
-n |
Skip file ownership/permission checks |
--usestderr |
Send error messages to stderr instead of stdout | |
--version |
-V |
Display cmscli version |
Display site name, CMSMS version, and schema version.
cmscli site-infoSet maintenance mode.
cmscli site-down # Standard maintenance page
cmscli site-down -c # Complete shutdown (no output at all)Remove maintenance mode.
cmscli site-upGenerate a checksum file for integrity verification.
cmscli site-checksum-generate # All files
cmscli site-checksum-generate --core # Core files only
cmscli site-checksum-generate --noindexesVerify installation integrity against a previously generated checksum file.
cmscli site-checksum-verifyClear the server cache.
cmscli cache-clearGet a CMSMS config.php variable value.
cmscli config-get db_prefix # Output: cms_
cmscli config-get root_url # Output: https://www.mysite.comSet a CMSMS config.php variable.
cmscli config-set db_prefix cms_
cmscli config-set root_url https://www.mysite.comList content pages with optional filters.
cmscli content-list # Full tabular list
cmscli content-list -b # Brief: aliases only
cmscli content-list -p home # Children of 'home' page
cmscli content-list -p 42 # Children of page ID 42
cmscli content-list -t content # Filter by type (content, pagelink, separator)
cmscli content-list -T "My Template" # Filter by template name
cmscli content-list -D "My Design" # Filter by design name
cmscli content-list -a # Active pages only
cmscli content-list -i # Inactive pages only
cmscli content-list -H 00002 # Filter by hierarchy prefix
cmscli content-list -m # Pages marked "show in menu" onlyOutput columns: ID, Alias, Name, Type, Template, Hierarchy, Active
Retrieve a page property (content block) value.
cmscli content-get home # Default: outputs content_en
cmscli content-get home content_en # Explicit property name
cmscli content-get home extra1 # Custom content block
cmscli content-get 42 content_en # By numeric ID
cmscli content-get home -l # List available properties
cmscli content-get home -s # Process through Smarty first
cmscli content-get home -f output.html # Write to fileCreate a new content page. Only the title is required; all other fields have sensible defaults.
cmscli content-create "My New Page"
cmscli content-create "My New Page" -p home # Under 'home' parent
cmscli content-create "My New Page" -a my-alias # Custom alias
cmscli content-create "My New Page" -T "Page Template" # Specific template
cmscli content-create "My New Page" -t pagelink # Content type
cmscli content-create "My New Page" -c "<p>Hello</p>" # Inline content
cmscli content-create "My New Page" -f content.html # Content from file
cmscli content-create "My New Page" -m "Menu Text" # Custom menu text
cmscli content-create "My New Page" -I # Create inactive
cmscli content-create "My New Page" -M # Hide from menuDefaults when not specified:
- alias - auto-generated from title (e.g. "My New Page" becomes
my-new-page) - parent - root level (-1)
- template - site's default page template
- type -
content - menu text - same as title
- active - yes
- show in menu - yes
- owner - admin user (ID 1)
Options:
| Option | Short | Description |
|---|---|---|
--parent <alias|id> |
-p |
Parent page (default: root) |
--alias <alias> |
-a |
Page alias (auto-generated from title if omitted) |
--template <name> |
-T |
Template name (default: site default page template) |
--type <type> |
-t |
Content type: content, pagelink, separator (default: content) |
--content <html> |
-c |
Page content (content_en block) |
--file <path> |
-f |
Read content from file |
--menutext <text> |
-m |
Menu text (defaults to title) |
--inactive |
-I |
Create page as inactive |
--hide-from-menu |
-M |
Hide page from navigation menu |
Edit properties of an existing page.
cmscli content-edit my-page --title "New Title"
cmscli content-edit my-page -a new-alias
cmscli content-edit my-page -T "Other Template"
cmscli content-edit my-page -p other-parent
cmscli content-edit my-page -m "New Menu Text"
cmscli content-edit my-page --active 1
cmscli content-edit my-page --showinmenu 0
cmscli content-edit my-page -c "<p>New content</p>"
cmscli content-edit my-page -f updated.html
cmscli content-edit my-page -P extra1="Custom value"
cmscli content-edit 42 --active 0 # By IDOptions:
| Option | Short | Description |
|---|---|---|
--title <text> |
Page title | |
--alias <alias> |
-a |
Page alias |
--template <name> |
-T |
Template name |
--parent <alias|id> |
-p |
Parent page |
--menutext <text> |
-m |
Menu text |
--active <0|1> |
Active state | |
--showinmenu <0|1> |
Show in menu | |
--content <html> |
-c |
Set content_en |
--file <path> |
-f |
Read content from file |
--prop <name=value> |
-P |
Set a custom property |
Delete a page by alias or ID.
cmscli content-delete my-page
cmscli content-delete 42
cmscli content-delete my-page -f # Force: delete even with childrenProtections: refuses to delete the default page. Refuses to delete pages with children unless --force is used.
List all templates with optional filters.
cmscli template-list # Full tabular list
cmscli template-list -b # Brief: names only
cmscli template-list -D "My Design" # Filter by design
cmscli template-list -t __CORE__::page # Filter by type (originator::name)Export a template's content to stdout or file.
cmscli template-export "My Template"
cmscli template-export "My Template" -f output.tplImport template content from file or stdin.
cmscli template-import "My Template" -f input.tpl # Update existing
cmscli template-import "New Template" -f input.tpl -c # Create new
cat template.tpl | cmscli template-import "My Template" # From stdin| Option | Short | Description |
|---|---|---|
--file <path> |
-f |
Read from file (default: stdin) |
--create |
-c |
Create template if it doesn't exist |
Export template(s) to file-based editing in assets/templates/. When a template has a file on disk, the admin UI disables in-browser editing for that template, allowing you to edit with your IDE.
cmscli template-file-export "My Template" # Single template
cmscli template-file-export --all # All templates
cmscli template-file-export -t __CORE__::page # All page templates
cmscli template-file-export -t News::summary # Single module type
cmscli template-file-export -m News # All News module templates
cmscli template-file-export -m Navigator # All Navigator templates
cmscli template-file-export -D "My Design" # All in a designFiles are written to assets/templates/{munged-name}.{id}.tpl. Templates that already have files on disk are skipped.
| Option | Short | Description |
|---|---|---|
--all |
-a |
Export all templates |
--type <orig::name> |
-t |
Export all templates of this type |
--module <name> |
-m |
Export all templates for a module (all types) |
--design <name> |
-D |
Export all templates in this design |
Import template(s) from assets/templates/ back into the database.
cmscli template-file-import "My Template" # Single template
cmscli template-file-import --all # All templates with files
cmscli template-file-import "My Template" -k # Keep file after importBy default, the file is deleted after import. Use --keep to preserve it.
| Option | Short | Description |
|---|---|---|
--all |
-a |
Import all templates that have files on disk |
--keep |
-k |
Keep the file on disk after import (default: delete) |
List all stylesheets.
cmscli stylesheet-list
cmscli stylesheet-list -b # Brief: names only
cmscli stylesheet-list -D "My Design" # Filter by designExport a stylesheet to stdout or file.
cmscli stylesheet-export "My Stylesheet"
cmscli stylesheet-export "My Stylesheet" -f output.cssImport stylesheet content from file or stdin.
cmscli stylesheet-import "My Stylesheet" -f styles.css
cmscli stylesheet-import "New Sheet" -f styles.css -c # Create newList all designs.
cmscli design-list
cmscli design-list -b # Brief: names onlyExport a design as XML (includes templates, stylesheets, resources).
cmscli design-export "My Design" # To stdout
cmscli design-export "My Design" -f design.xml # To fileImport a design from XML file.
cmscli design-import design.xmlList all User Defined Tags.
cmscli udt-list
cmscli udt-list -b # Brief: names onlyOutput columns: ID, Name, Description, Modified
Export UDT code to stdout or file.
cmscli udt-export my_tag
cmscli udt-export my_tag -f my_tag.phpImport/update UDT code from file or stdin.
cmscli udt-import my_tag -f my_tag.php # Update existing
cmscli udt-import new_tag -f code.php --create # Create new
cmscli udt-import new_tag -f code.php -c -D "My helper" # Create with description
cat code.php | cmscli udt-import my_tag # From stdin| Option | Short | Description |
|---|---|---|
--file <path> |
-f |
Read code from file (default: stdin) |
--create |
-c |
Create the UDT if it doesn't exist |
--description <text> |
-D |
Set description (used with --create) |
In CMSMS 2.2, Global Content Blocks are templates of type Core::generic in the DesignManager.
List all Global Content Blocks.
cmscli gcb-list
cmscli gcb-list -b # Brief: names onlyOutput columns: ID, Name, Description, Modified
Get the content of a GCB.
cmscli gcb-get footer
cmscli gcb-get footer -f footer.tpl # Write to fileSet/update GCB content from file or stdin.
cmscli gcb-set footer -f footer.tpl # Update existing
cmscli gcb-set "new block" -f block.tpl --create # Create new
echo "<p>Hello</p>" | cmscli gcb-set footer # From stdin| Option | Short | Description |
|---|---|---|
--file <path> |
-f |
Read content from file (default: stdin) |
--create |
-c |
Create the GCB if it doesn't exist |
List system and module events with handler counts.
cmscli event-list # All events
cmscli event-list -b # Brief: Originator::EventName only
cmscli event-list -o Core # Filter by originator
cmscli event-list -o News # Module events onlyOutput columns: ID, Originator, Event, Handlers
Trigger (send) an event from the command line.
cmscli event-send Core::ContentPostRender
cmscli event-send Core::ContentEditPost -p content_id=42
cmscli event-send MyModule::MyEvent -p key1=value1 -p key2=value2| Option | Short | Description |
|---|---|---|
--param <key=value> |
-p |
Event parameter (repeatable) |
Event format: Originator::EventName
List custom (pretty URL) routes registered by modules.
cmscli route-list # All routes
cmscli route-list -b # Brief: patterns only
cmscli route-list -m News # Filter by moduleOutput columns: Route Pattern, Module, Key2, Created
Add a static route.
cmscli route-add '/products/(?P<slug>[a-z0-9-]+)$' StoreFront
cmscli route-add '/api/callback' MyModule --absolute # Exact string, not regex
cmscli route-add '/webhook' MyModule --key2 handler # With optional key2| Option | Description |
|---|---|
--absolute |
Treat pattern as exact string match (not regex) |
--key2 <value> |
Optional key2 value |
--key3 <value> |
Optional key3 value |
Validates that the module exists and the route is not a duplicate.
Delete a static route.
cmscli route-delete '/products/(?P<slug>[a-z0-9-]+)$'
cmscli route-delete '/test' -m News # Specify module if ambiguous| Option | Short | Description |
|---|---|---|
--module <name> |
-m |
Specify module when multiple routes share the same pattern |
Read site preferences from the cms_siteprefs table.
cmscli pref-get sitename # Get single preference value
cmscli pref-get --list # List all preference names
cmscli pref-get --search sitename # Search by pattern (LIKE %pattern%)| Option | Short | Description |
|---|---|---|
--list |
-l |
List all preference names |
--search <pattern> |
-s |
Search preferences by name pattern |
Set or create a site preference.
cmscli pref-set sitename "My Site"
cmscli pref-set custom_setting value123If the preference doesn't exist, it is created.
Read module preferences via the module's GetPreference() method.
cmscli module-pref-get StoreFrontPayPal paypal_testmode # Get single value
cmscli module-pref-get StoreFrontPayPal --list # List all prefs for module
cmscli module-pref-get StoreFrontPayPal --search sandbox # Search by pattern| Option | Short | Description |
|---|---|---|
--list |
-l |
List all preference names for the module |
--search <pattern> |
-s |
Search preferences by name pattern |
Preference names are shown without the internal prefix (e.g. paypal_testmode not StoreFrontPayPal_mapi_pref_paypal_testmode).
Set a module preference via the module's SetPreference() method.
cmscli module-pref-set StoreFrontPayPal paypal_testmode 0
cmscli module-pref-set MeetSimple min_notice_hours 24List background jobs in the CmsJobManager queue.
cmscli jobs-list # Full table
cmscli jobs-list -b # Brief: names onlyOutput columns: ID, Name, Module, Errors, Status (READY/WAITING), Next Run
Also shows the timestamp of the last job processing run.
Process pending background jobs directly from CLI. This bypasses the HTTP-based async trigger that normally fires during page requests.
cmscli jobs-run # Process if throttle allows
cmscli jobs-run --force # Ignore frequency throttle
cmscli jobs-run --force --verbose # Show per-job progress| Option | Short | Description |
|---|---|---|
--force |
-f |
Ignore the async frequency throttle |
--verbose |
-v |
Show details for each processed job |
Cron usage (recommended for low-traffic sites):
*/3 * * * * cd /var/www/mysite && php cmscli.phar jobs-run --forceThis ensures background tasks (version checks, log cleanup, module tasks) run reliably even without incoming web traffic.
List admin log entries.
cmscli log-list # Last 50 entries
cmscli log-list --limit 10 # Last 10 entries
cmscli log-list --source Core # Filter by source (item_name)
cmscli log-list -m MeetSimple # Short form
cmscli log-list --user 1 # Filter by user_id
cmscli log-list --search "password" # Search action text
cmscli log-list -b # Brief: timestamp + action only| Option | Short | Description |
|---|---|---|
--limit <n> |
Number of entries to show (default: 50) | |
--source <name> |
-m |
Filter by source/item_name (e.g. Core, Module, MeetSimple) |
--user <id> |
-u |
Filter by user_id |
--search <text> |
-s |
Search action text (LIKE %pattern%) |
--brief |
-b |
Brief output: timestamp and action only |
Output columns: Timestamp, User, Source, Action
Add an entry to the admin log via the audit() function.
cmscli log-add MyModule "Deployed new version"
cmscli log-add cmscli "Ran backup script" --item-id 42
cmscli log-add Core "Manual cache clear" --user-id 3| Option | Short | Description |
|---|---|---|
--item-id <n> |
-i |
Item ID (default: -1) |
--user-id <n> |
-u |
User ID (default: 1) |
Clear admin log entries. Requires at least one filter to prevent accidental deletion.
cmscli log-clear --older-than 30 # Delete entries older than 30 days
cmscli log-clear --module Core # Delete all entries from source
cmscli log-clear --older-than 7 --module News # Combined filters
cmscli log-clear --all # Delete ALL entries| Option | Short | Description |
|---|---|---|
--older-than <days> |
Delete entries older than N days | |
--module <name> |
-m |
Delete entries for this source/module |
--all |
Delete ALL log entries |
Generate a mysqldump of CMSMS tables.
cmscli db-dump # Dump to stdout
cmscli db-dump -F dump.sql # Dump to file
cmscli db-dump -f # Full database (not just CMSMS tables)Import an SQL file into the CMSMS database.
cmscli db-import < dump.sql # From stdinDrop all CMSMS tables from the database. Destructive operation.
cmscli db-resetList installed modules.
cmscli module-list
cmscli module-list -b # Brief: names onlymodule-list-hidden
List modules hidden from the admin panel.
cmscli module-list-hiddenInstall a module.
cmscli module-install ModuleName # Install from modules/ directory
cmscli module-install ModuleName --forge # Download from Forge and install
cmscli module-install ModuleName --with-deps # Download with all dependencies| Option | Description |
|---|---|
--forge |
Download the latest version from the CMSMS Forge |
--with-deps |
Resolve and install all dependencies (implies --forge) |
Uninstall a module (keeps files on disk).
cmscli module-uninstall ModuleName
cmscli module-uninstall ModuleName -f # Force (skip safety checks)Uninstall a module AND delete its files from disk. Destructive.
cmscli module-purge ModuleName
cmscli module-purge ModuleName -f # Forcecmscli module-activate ModuleName
cmscli module-deactivate ModuleNamecmscli module-hide ModuleName
cmscli module-unhide ModuleNameUpgrade a module to its latest available version.
cmscli module-upgrade ModuleNameInstall a module from a local XML package file.
cmscli module-install-xml /path/to/ModuleName-1.0.xml
cmscli module-install-xml ModuleName-1.0.xml # Relative to CMS rootExtracts the XML package into modules/, then installs. Useful for deploying modules packaged with module-package-xml without needing the Forge.
Package an installed module into an XML distribution file.
cmscli module-package-xml ModuleName # Output to modules/Name/releases/version/
cmscli module-package-xml ModuleName -o /tmp # Custom output directory
cmscli module-package-xml ModuleName --stdout # Output to stdoutList admin users.
cmscli user-listCreate a new admin user.
cmscli user-add username email@example.com password
cmscli user-add username email@example.com password -g "Editor" # Add to groupEdit admin account details.
cmscli user-edit username --email new@email.com
cmscli user-edit username --firstname "John" --lastname "Doe"Change an admin user's password.
cmscli user-password username newpasswordcmscli user-activate username
cmscli user-deactivate usernameRemove an admin user account.
cmscli user-del usernameAdd or remove a user from admin groups.
cmscli user-group username "Editor" --add
cmscli user-group username "Editor" --removeList admin groups.
cmscli group-listCreate a new admin group.
cmscli group-add "My Group"Remove an admin group.
cmscli group-del "My Group"List permissions associated with a group.
cmscli group-perm-list "Editor"Display mailer configuration (type, from address, host).
cmscli mail-infoSend a test email.
cmscli mail-test recipient@example.com
cmscli mail-test recipient@example.com -s "Subject" -B "Body text"These commands do NOT require a CMSMS installation:
Display usage information.
cmscli aboutGet the latest released CMSMS version number.
cmscli cmsms-latestversion # Output: 2.2.22Download the latest CMSMS installation assistant.
cmscli cmsms-download| Code | Meaning |
|---|---|
| 0 | Success |
| 1+ | Error (message printed to stdout or stderr) |
#!/bin/bash
cd /var/www/mysite
php cmscli.phar site-down
php cmscli.phar db-dump -F tmp/dump.sql
tar zcf ../backup-$(date +%Y%m%d).tar.gz .
php cmscli.phar site-upcd /var/www/mysite
php cmscli.phar site-down
git pull
php cmscli.phar cache-clear
php cmscli.phar template-file-import --all
php cmscli.phar site-up# Export templates to disk for IDE editing
php cmscli.phar template-file-export --all
# Edit .tpl files in assets/templates/ with your editor...
# Import changes back to database
php cmscli.phar template-file-import --all*/3 * * * * cd /var/www/mysite && php cmscli.phar jobs-run --force 2>/dev/null# Install module with dependencies from Forge
php cmscli.phar module-install CGSmartImage --with-deps
# Package for distribution
php cmscli.phar module-package-xml MyModuleModules can provide additional CLI commands by declaring the clicommands capability:
// In your module class:
public function HasCapability($capability, $params = [])
{
if ($capability == 'clicommands') return true;
return parent::HasCapability($capability, $params);
}
public function get_cli_commands(\CMSMS\CLI\App $app)
{
return [
new \MyModule\CLI\MyCommand($app),
];
}Commands must extend \CMSMS\CLI\GetOptExt\Command.
- PHP 7.4+ (CLI)
- humbug/box (phar compiler)
- A working CMSMS 2.2.14+ installation for testing
src-extracted/
├── bin/cmscli # Entry point script
├── src/
│ ├── App.php # Main application bootstrap
│ ├── Commands/ # All command implementations
│ ├── GetOptExt/ # Extended getopt-php classes
│ └── resources/ # Help templates
├── vendor/ # Composer dependencies (ulrichsg/getopt-php)
├── box.json # Phar build configuration
└── composer.json # Project dependencies
- Create a new file in
src-extracted/src/Commands/ - Extend
\CMSMS\CLI\GetOptExt\Command - Register it in
src-extracted/src/App.php(the_load_commands()method)
After making changes to the source:
bash build.shOr manually:
cd src-extracted/
php -d phar.readonly=0 ~/.config/composer/vendor/bin/box compile
cp cmscli.phar ../cmscli.pharTest against a live CMSMS installation:
cd /var/www/mysite
php /path/to/cmscli.phar --nopermcheck site-info- Source: github.com/cmsmadesimple/cmsms-cmscli
- Issues and pull requests welcome