skillZs
★ LIVE SKILL TAGS ★
>>> LIVE SKILLS INDEX <<<
* OPEN SOURCE *
NO LOGIN, NO TRACKING
※ REAL INSTALL DATA ※
← back to all skills
grasmash/drupal-claude-skills176 installs

drupal-config-mgmt

Guides Drupal configuration management safely - single-config export/set/delete, config:import and config:export (cim/cex) with preview-first --no --diff, config:status checks, Config Split (complete vs partial splits, csex/csim, activation), and syncing config from remote environments through Terminus, acli, platform/upsun, lagoon or drush aliases. Use when exporting or importing Drupal config, inspecting or changing a single config object, merging production config into a feature branch, working with config_split, or diagnosing config that will not import or vanishes from config/default on export.

How do I install this agent skill?

npx skills add https://github.com/grasmash/drupal-claude-skills --skill drupal-config-mgmt
view source ↗

Is this agent skill safe to install?

  • Gen Agent Trust Hubpass

    This skill provides comprehensive instructions for Drupal configuration management using industry-standard tools like Drush, Git, and various hosting CLIs. While it executes shell commands and uses dynamic PHP evaluation to update configuration, these actions are essential for its purpose and are implemented using established developer workflows.

  • Socketpass

    No alerts

  • Snykpass

    Risk: LOW · No issues

  • Runlayerwarn

    2/2 files flagged

  • ZeroLeakspass

    Score: 93/100 · 2 sections analyzed

What does this agent skill do?

Drupal Configuration Management

Comprehensive guide for Drupal configuration management including imports, exports, config splits, and environment syncing.

Remote CLI — host-neutral

Examples below use Pantheon's Terminus (terminus drush <site>.<env> -- <cmd>). The commands are identical on any host — substitute your platform's remote-drush form. If your platform provides Drush site aliases, the generic drush @<alias> <cmd> works everywhere.

TaskAcquia (acli)Pantheon (Terminus)Platform.sh / UpsunLagoon (amazee.io)Generic (Drush aliases)
Remote drushacli remote:drush -- <cmd>terminus drush <site>.<env> -- <cmd>platform drush -e <env> -- <cmd> (Upsun: upsun drush …)lagoon ssh -p <project> -e <env> -C "drush <cmd>"drush @<alias> <cmd>
Get/inspect configacli remote:drush -- config:get <name>terminus drush <site>.<env> -- config:get <name>platform drush -e <env> -- config:get <name>lagoon ssh -p <project> -e <env> -C "drush config:get <name>"drush @<alias> config:get <name>

The auto-confirm warning below applies to every host — append --no to cim/config:import to preview instead of apply. Drush defaults to --yes when invoked non-interactively (which all remote-CLI wrappers do).

Problem: Avoid Accidental Config Imports

CRITICAL: Terminus drush commands default to --yes unless explicitly told --no. This means commands like config:import or cim will AUTO-CONFIRM and import configuration even when you only want to inspect differences.

Dangerous vs Safe Patterns

❌ DANGEROUS - Auto-imports without confirmation:

terminus drush {site}.{env} -- cim --diff  # DON'T DO THIS!

✅ SAFE - Shows diff without importing:

terminus drush {site}.{env} -- cim --no --diff

✅ SAFEST - Read-only commands:

terminus drush {site}.{env} -- config:get config.name
terminus drush {site}.{env} -- config:status

Table of Contents

  1. Preferred Prod Config Merge Workflow
  2. Configuration Import & Export Basics
  3. Config Splits Overview
  4. Complete vs Partial Splits
  5. Config Split Commands
  6. Safe Inspection Workflow
  7. Syncing Config from Upstream Environments

Configuration Import & Export Basics

Default to one named object at a time. A blanket cex writes every active-vs-sync difference to disk and a blanket cim imports (and deletes) every difference, so in a tree with drift you did not create they sweep that drift into your commit or your database. An agent changes config with config:get / config:set / config:delete / a partial import of one file, and leaves the full import to the deploy (the tail is in the drupal-deploy-safety skill). Run a blanket export only from a clean, committed tree when a full export is the point (a prod config merge, a split change), and review git status config/ afterwards. Full rules: surgical-config.md.

Exporting Configuration

Export ALL configuration (from active config to YAML files; clean tree only, see above):

# Local
ddev drush config:export
ddev drush cex

# Remote
terminus drush {site}.{env} -- config:export

Export a SINGLE config object:

# Get config and save to file
ddev drush config:get config.name --format=yaml > config/default/config.name.yml

# Example: Export a specific view
ddev drush config:get views.view.content --format=yaml > config/default/views.view.content.yml

Importing Configuration

Import ALL configuration (from YAML files to active config; this is what a deploy does, so preview locally and leave remote imports to the deploy tail):

# Local
ddev drush config:import
ddev drush cim

# Remote (DANGEROUS - auto-confirms with terminus!)
terminus drush {site}.{env} -- config:import --no  # Use --no to preview only

Import a SINGLE config object (partial import from a directory holding only that file; under DDEV the directory must be inside the project, see surgical-config.md):

mkdir -p .config-one && cp config/default/config.name.yml .config-one/
ddev drush config:import --partial --source=/var/www/html/.config-one -y
rm -rf .config-one

# Or use config:set for specific values
ddev drush config:set config.name key.subkey value

Best Practice: Always preview changes first:

ddev drush config:import --no --diff  # Show what would change
ddev drush cim --no --diff            # Alias

Config Split Commands

CRITICAL: Active vs Exported Configuration

⚠️ IMPORTANT: When updating config split definitions, changes must be in ACTIVE configuration (database), not just exported files!

Workflow:

  1. Edit config/default/config_split.config_split.{name}.yml
  2. Import to make active: a single-file partial import (see above) OR use PHP (see below)
  3. Export: ddev drush cex. This is the one routine case that needs a full export, because config_split writes the split directory and its patch files during cex. Start from a clean tree and revert anything in git status config/ you did not intend.

Quick method - Set active config via PHP:

ddev drush php:eval "\$config = \Drupal::configFactory()->getEditable('config_split.config_split.local'); \$config->set('partial_list', ['config.name']); \$config->save();"

See examples.md for detailed workflow.

Export Config with Splits

Export ALL config including active splits:

ddev drush config:export

This exports:

  • Base config to config/default/
  • Active split config to config/{split-name}/

Export a specific split:

ddev drush config-split:export {split-name}
ddev drush csex {split-name}

Import Config with Splits

Import ALL config including active splits:

ddev drush config:import
ddev drush cim

This imports:

  • Base config from config/default/
  • Active split config from config/{split-name}/

Import a specific split:

ddev drush config-split:import {split-name}
ddev drush csim {split-name}

Import only base config (ignore splits): Drush 13's config:import has no option for this (--skip-modules was Drush 8). drush config-split:deactivate <split> itself imports the config without the split, writing status: false into active config; a later full config:import re-activates the split if its synced YAML has status: true. To keep it off across imports, set a status override: drush config-split:status-override <split> inactive (stored in state; values active|inactive|default, alias csso), or in settings.php:

ddev drush config-split:deactivate {split-name}                     # one-off
ddev drush config-split:status-override {split-name} inactive       # sticks across imports
$config['config_split.config_split.{split-name}']['status'] = FALSE;  // settings.php

A --partial import skips config transformation, so no split is applied to it at all.

Activate/Deactivate Splits

Activate a split:

ddev drush config-split:activate {split-name}

Deactivate a split:

ddev drush config-split:deactivate {split-name}

Check Split Status

List all splits and their status:

ddev drush config-split:status
ddev drush css

Example output:

Split       Active  Configuration directory
local       Yes     ../config/local
dev         No      ../config/dev
test        No      ../config/test

Safe Inspection Workflow

Use config:get and config:status for read-only inspection, or use --no flag with cim/cex to prevent auto-confirmation.

Get Config Values

# Get full config object
terminus drush {site}.{env} -- config:get config.name

# Get as YAML
terminus drush {site}.{env} -- config:get config.name --format=yaml

# Extract specific values
terminus drush {site}.{env} -- config:get config.name 2>&1 | grep "setting_name"

Compare Local vs Remote

# View diffs without importing (SAFE with --no)
terminus drush {site}.{env} -- cim --no --diff

# Get remote and compare manually
terminus drush {site}.{env} -- config:get config.name --format=yaml > /tmp/remote.yml
diff -u config/default/config.name.yml /tmp/remote.yml

CRITICAL: Always use --no flag with terminus! Without it, commands auto-confirm.

Apply Changes

Preferred: never hand-author the YAML. Either make the change in the site (UI, config:set for simple config, or the entity API for config entities) and export that one object, or, to take an environment's value, write that environment's config:get output for the one object (see surgical-config.md):

ddev drush config:get config.name --format=yaml > config/default/config.name.yml
# or: terminus drush {site}.{env} -- config:get config.name --format=yaml > config/default/config.name.yml
git diff config/default/config.name.yml
git add config/default/config.name.yml
git commit -m "Update config from {env}"

Syncing Config from Upstream Environments

Quick Methods

Single config object:

terminus drush {site}.{env} -- config:get config.name --format=yaml > config/default/config.name.yml
git add config/default/config.name.yml && git commit -m "Update from {env}"
# Then apply that one file locally with a single-file partial import (see above)

Full config sync via rsync:

Caution: a remote cex writes every drifted config object on that environment, and a local cim imports (and deletes) everything that differs. Never run a blanket export/import against a shared or remote environment as a casual step — prefer the single-config method above, and review the full diff before anything is imported. See surgical-config.md.

terminus drush {site}.{env} -- cex
terminus rsync {site}.{env}:code/config/default /tmp/remote
diff -r config/default /tmp/remote  # Review
cp /tmp/remote/*.yml config/default/
git add config/default/ && git commit -m "Sync from {env}"
ddev drush cim

Via database pull (DDEV + Pantheon). This is a deliberate full export: commit your own work first and restore any of your files the export deletes, as in prod-config-merge.md:

ddev pull pantheon --environment={env}  # Warning: Overwrites local DB!
ddev drush cex
git diff config/ && git add config/ && git commit -m "Config from {env}"

See examples.md for detailed workflows.

Best practices: Review diffs, commit separately, test locally, document source, avoid syncing environment-specific config.


Deep Dive References

For comprehensive technical documentation, see:

  • config-split-deep-dive.md - Complete technical reference on Config Split 2.0, patch files, export/import process, and dependency handling
  • surgical-config.md - One-config-at-a-time export/set/delete for agents, the core.extension.yml exception, raw config writes that drop dependencies, baked (PHP-computed) config, and verifying imports with config:status
  • examples.md - Practical examples and workflows

References

FileRead it when
references/surgical-config.mdBefore any config change an agent makes: exporting, setting or deleting ONE named config object, the core.extension.yml exception, raw config writes that drop dependencies, baked (PHP-computed) config, verifying an import with config:status, shipping a config-only change
references/prod-config-merge.mdMerging production config changes into a branch that carries local feature config (pull prod DB, export, restore your deleted/overwritten files)
references/config-splits.mdDeciding whether to use a split, or choosing between a Complete and a Partial split
references/config-split-deep-dive.mdYou need the Config Split 2.0 internals: patch files, file naming, the export/import process, dependency handling, and worked local-vs-remote Solr examples (including a complete-split server with auto-generated index patches)
references/examples.mdYou want worked examples: syncing one config from dev, syncing Search API config, comparing environments, updating split definitions

Config Status Check

Check what config would be imported (read-only):

# Local environment
ddev drush config:status

# Remote environment
terminus drush {site}.{env} -- config:status

Best Practices

  1. Always inspect before importing - Use config:get and --no --diff flags
  2. Change config in the site, export one object - UI / config:set / entity API, then config:get --format=yaml; hand-editing exported YAML is the exception (it skips dependency calculation), and when you do it, import that one file and confirm with config:status
  3. One config type per commit - Separate concerns for clean history
  4. Clear commit messages - Reference source environment
  5. Clean up temp files - Remove temporary YAML files
  6. Verify before committing - Always review git diff output
  7. Test locally first - Import and test before deploying
  8. Use config splits - Keep environment-specific config separate

Troubleshooting

Config files deleted from working directory

If files are marked as deleted in git status:

git checkout HEAD -- config/default/*.yml

This can happen if a drush command runs unexpectedly.

Split not activating

Check split status:

ddev drush config-split:status

Manually activate:

ddev drush config-split:activate {split-name}
# Save the activation state: export only the split definition
ddev drush config:get config_split.config_split.{split-name} --format=yaml > config/default/config_split.config_split.{split-name}.yml

Config deleted from config/default on export

COMMON ISSUE: Config (like search_api.server.my_search_server) gets removed from config/default/ when you run drush cex.

Root cause (99% of cases): Config is in complete_list instead of partial_list!

Complete split = Config is REMOVED from config/default/ and moved to split directory entirely Partial split = Config STAYS in config/default/, only differences are patched

Diagnosis:

# Check if config is in complete_list (will be deleted from config/default)
grep -A10 "complete_list:" config/default/config_split.config_split.local.yml

# Check if config is in partial_list (will stay in config/default)
grep -A10 "partial_list:" config/default/config_split.config_split.local.yml

Solution: Move from complete_list to partial_list

# Edit the split definition
# Move: search_api.server.my_search_server
# FROM: complete_list
# TO: partial_list

ddev drush cex  # Re-export
# Check that config/default/search_api.server.my_search_server.yml exists
# Check that config/local/config_split.patch.search_api.server.my_search_server.yml exists

See config-split-deep-dive.md for complete technical explanation.

Config won't import

Common issues:

  • Dependencies missing: Install required modules first
  • Site UUID mismatch ("Site UUID in source storage does not match the target storage"): the database was installed separately from the exported config. Install from config with drush site:install --existing-config, or set system.site:uuid to the exported value with drush config:set system.site uuid <uuid>
  • Config entity UUID differs: not an error, but the import deletes and recreates that entity (for a field storage, its data goes with it); see the drupal-config-reconcile skill

Drush 13's config:import has no --skip-config option. To keep one object out of an import, use the config_ignore module or a single-file partial import (above).

Related Commands

Read-only: config:get, config:status Exports: config:export (alias: cex) Imports: config:import (alias: cim) - Use with --no --diff to preview Splits: config-split:status, csex, csim, config-split:activate

Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.

<a href="https://skillzs.dev/skills/grasmash/drupal-claude-skills/drupal-config-mgmt">View drupal-config-mgmt on skillZs</a>