Skip to content

civicrm/cv

Folders and files

NameName
Last commit message
Last commit date

Latest commit

1192eea · Mar 22, 2025
Sep 10, 2024
Feb 20, 2025
Feb 28, 2025
Feb 26, 2024
Aug 7, 2024
Jun 25, 2024
Mar 14, 2025
Feb 20, 2025
Jul 29, 2023
Feb 20, 2025
Feb 20, 2025
Aug 9, 2024
Nov 6, 2024
Jun 9, 2024
Feb 5, 2025
Feb 26, 2024

Repository files navigation

cv

The cv command is a utility for interacting with a CiviCRM installation. It performs an automatic scan to locate and boot the CiviCRM installation. It provides command-line access to helper functions and configuration data, such as APIv3 and site URLs.

Requirements

  • PHP v7.3+.
  • A local CiviCRM installation.
  • Systems with special file-layouts may need to configure bootstrap.

Download

cv is distributed in PHAR format, which is a portable executable file (for PHP). It should run on most Unix-like systems where PHP is installed. Here are three quick ways to download it:

There are several more options for downloading cv. See also:

Documentation

cv provides a number of subcommands. To see a list, run cv without any arguments.

For detailed help about a specific subcommand, use -h as in cv api -h.

There are some general conventions:

  • Many subcommands support common bootstrap options, such as --user, --level, and --test.
  • Many subcommands support multiple output formats using --out. You may set a general preference with an environment variable, e.g. export CV_OUTPUT=json-pretty or export CV_OUTPUT=php.

Example: CLI

me@localhost$ cd /var/www/my/web/site

## Clear caches
me@localhost$ cv flush

## Manage extensions
me@localhost$ cv ext -Li
me@localhost$ cv dl cividiscount
me@localhost$ cv en cividiscount
me@localhost$ cv dis cividiscount
me@localhost$ cv path -x cividiscount
me@localhost$ cv url -x cividiscount

## Manage settings
me@localhost$ cv vget
me@localhost$ cv vget /mail/
me@localhost$ cv vset mailerBatchLimit=100

## Call APIs
me@localhost$ cv api3 contact.get last_name=Smith
me@localhost$ cv api4 Contact.get +w last_name=Smith

## Improvise PHP
me@localhost$ cv ev 'echo Civi::paths()->getPath("[civicrm.root]/.");'
me@localhost$ cv scr /path/to/my-script.php
me@localhost$ cv cli

## Improvise web requests
me@localhost$ cv url civicrm/dashboard --open
me@localhost$ cv url civicrm/dashboard --open -LU admin
me@localhost$ cv http civicrm/dashboard
me@localhost$ cv http civicrm/dashboard -LU admin

## Inspect events and services
me@localhost$ cv event
me@localhost$ cv event /flexmailer/
me@localhost$ cv service
me@localhost$ cv service /flexmailer/

If you intend to run unit-tests, and if you do not use civibuild, then you may need to supply some additional site information (such as the name of the test users). To do this, run:

me@localhost$ cd /var/www/my/web/site
me@localhost$ cv vars:show
me@localhost$ cv vars:fill
me@localhost$ vi ~/.cv.json
me@localhost$ cv vars:show

Example: PHP

Suppose you have a standalone script or a test runner which needs to execute in the context of a CiviCRM site. You don't want to hardcode it to a specific path, create special-purpose config files, or require a specific directory structure. Instead, call cv php:boot and eval(). The simplest way:

eval(`cv php:boot`)

However, it is better to create a small wrapper function to improve error-handling and output parsing:

/**
 * Call the "cv" command.
 *
 * @param string $cmd
 *   The rest of the command to send.
 * @param string $decode
 *   Ex: 'json' or 'phpcode'.
 * @return string
 *   Response output (if the command executed normally).
 * @throws \RuntimeException
 *   If the command terminates abnormally.
 */
function cv($cmd, $decode = 'json') {
  $cmd = 'cv ' . $cmd;
  $descriptorSpec = array(0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => STDERR);
  $env = (!empty($_ENV) ? $_ENV : getenv()) + array('CV_OUTPUT' => 'json');
  $process = proc_open($cmd, $descriptorSpec, $pipes, __DIR__, $env);
  fclose($pipes[0]);
  $result = stream_get_contents($pipes[1]);
  fclose($pipes[1]);
  if (proc_close($process) !== 0) {
    throw new RuntimeException("Command failed ($cmd):\n$result");
  }
  switch ($decode) {
    case 'raw':
      return $result;

    case 'phpcode':
      // If the last output is /*PHPCODE*/, then we managed to complete execution.
      if (substr(trim($result), 0, 12) !== "/*BEGINPHP*/" || substr(trim($result), -10) !== "/*ENDPHP*/") {
        throw new \RuntimeException("Command failed ($cmd):\n$result");
      }
      return $result;

    case 'json':
      return json_decode($result, 1);

    default:
      throw new RuntimeException("Bad decoder format ($decode)");
  }
}

eval(cv('php:boot', 'phpcode'));
$config = cv('vars:show');
printf("We should navigate to the dashboard: %s\n\n", cv('url civicrm/dashboard'));

Example: NodeJS

See https://github.com/civicrm/cv-nodejs

Bootstrap

cv must find and bootstrap the local instance of CiviCRM, Drupal, WordPress, or similar. This may work a few ways:

  • Automatic: By default, cv checks the current directory and each parent directory for evidence of well-known environment (such as Drupal or WordPress).

    The automatic search is designed to work with a default site-layout -- as seen in a typical "zip" or "tar" file from drupal.org, wordpress.org, or similar. Some deployments add more advanced options -- such as configuring "multi-site", adding bespoke "symlinks", or moving the wp-admin folder. For advanced layouts, you may need to set an environment variable.

  • CIVICRM_BOOT (new protocol): Boot the CMS first (and then ask it to boot CiviCRM). This is more representative of a typical HTTP page-view, and it is compatible with commands like core:install. Set this environment variable to specify the CMS type and base-directory. Compare:

    export CIVICRM_BOOT="Drupal://var/www/public"
    export CIVICRM_BOOT="Drupal8://admin@/var/www/public"
    export CIVICRM_BOOT="WordPress:/$HOME/sites/my-wp-site/web/"
    export CIVICRM_BOOT="Auto://."
  • CIVICRM_SETTINGS (old protocol): Boot CiviCRM first (and then ask it to boot the CMS). Set this environment variable to specify the civicrm.settings.php location. Compare:

    export CIVICRM_SETTINGS="/var/www/sites/default/files/civicrm.settings.php"
    export CIVICRM_SETTINGS="Auto"

    (Note: In the legacy protocol, cv loads CiviCRM and then asks CiviCRM to boostrap the CMS. However, it is less representative of a typical HTTP page-view, and it is incompatible with commands like core:install. You might use it for headless testing or as fallback/work-around if any bugs are discovered in the standard protocol.)

NOTE: In absence of a configuration variable, the Automatic mode will behave like CIVICRM_SETTINGS="Auto" (in v0.3.x). This is tentatively planned to change in v0.4.x, where it will behave like CIVICRM_BOOT="Auto://."

Additionally, some deployments handle multiple sites ("multisite"/"multidomain"). You should target a specific site using --url or HTTP_HOST.

Here are a few examples of putting these together:

## Use --url for a domain
export CIVICRM_BOOT="WordPress:/$HOME/public_html/"
cv --url='https://www.example.org' ext:list -L
## Use HTTP_HOST for a domain
export CIVICRM_BOOT="WordPress:/$HOME/public_html/"
export HTTP_HOST=www.example.org
cv ext:list -L
## Use --url for a subfolder
export CIVICRM_BOOT="WordPress:/$HOME/public_html/"
cv --url='www.example.org/nyc' ext:list -L

Autocomplete

There is limited/experimental support for shell autocompletion based on stecman/symfony-console-completion. To enable it:

# BASH ~4.x, ZSH
source <(cv _completion --generate-hook)

# BASH ~3.x, ZSH
cv _completion --generate-hook | source /dev/stdin

# BASH (any version)
eval $(cv _completion --generate-hook)

Development

For more information, see doc/develop.md.