PHPackages                             kanopi/wp-core-installer - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. kanopi/wp-core-installer

ActiveComposer-plugin[Utility &amp; Helpers](/categories/utility)

kanopi/wp-core-installer
========================

A Composer plugin that safely installs WordPress core files without overwriting project files, and manages .gitignore for all Composer-managed WordPress packages.

1.1.1(1mo ago)1444[1 issues](https://github.com/kanopi/wp-core-installer/issues)[1 PRs](https://github.com/kanopi/wp-core-installer/pulls)MITPHPPHP &gt;=8.0

Since Mar 13Pushed 2w agoCompare

[ Source](https://github.com/kanopi/wp-core-installer)[ Packagist](https://packagist.org/packages/kanopi/wp-core-installer)[ RSS](/packages/kanopi-wp-core-installer/feed)WikiDiscussions main Synced 3w ago

READMEChangelogDependencies (4)Versions (5)Used By (0)

kanopi/wp-core-installer
========================

[](#kanopiwp-core-installer)

A Composer plugin that safely installs WordPress core files into a configured `web-root` **without** overwriting your project's own files, and automatically manages a `.gitignore` block for all Composer-managed WordPress packages.

The problem it solves
---------------------

[](#the-problem-it-solves)

The default `johnpbloch/wordpress-core-installer` maps the install path directly to your project root or web-root, causing Composer's extractor to **mirror / clobber the entire target directory** — wiping `composer.json`, `composer.lock`, `.env`, and everything else that lives there.

This plugin instead:

1. Extracts WordPress core into a **private staging directory** inside `vendor`so Composer's internal tracking works correctly.
2. **Selectively copies** files from staging into your web-root.
3. **Skips** a built-in list of protected paths (and any extras you declare).
4. **Manages two `.gitignore` blocks** — one for WP core files, one for every Composer-managed plugin, theme, and the vendor directory — so you never accidentally commit them.

---

Installation
------------

[](#installation)

```
composer require kanopi/wp-core-installer
```

Then require WordPress core:

```
composer require johnpbloch/wordpress-core
```

---

Configuration
-------------

[](#configuration)

All configuration lives under `extra` in your **project's** `composer.json`:

```
{
    "extra": {
        "wordpress-install-dir": ".",

        "wp-core-installer": {
            "protected-paths": [
                "my-custom-loader.php",
                "config"
            ],
            "skip-if-exists": [
                "robots.txt"
            ]
        }
    }
}
```

### `wordpress-install-dir`

[](#wordpress-install-dir)

ValueMeaning`"."`Deploy WP files into the project root itself`"public"`Deploy into `/public/``"public/wp"`Deploy into `/public/wp/`*(omitted)*Defaults to `"public"`### `wp-core-installer.protected-paths`

[](#wp-core-installerprotected-paths)

Additional paths **relative to the web-root** that must never be touched. Extends the built-in list.

### `wp-core-installer.skip-if-exists`

[](#wp-core-installerskip-if-exists)

Paths that are copied on **first** install only, never overwritten on update. The built-in list covers `.htaccess`, `wp-config-sample.php`, and the silence-is-golden `wp-content/index.php` stubs.

---

Three-tier protection model
---------------------------

[](#three-tier-protection-model)

TierBehaviourExamples`protected-paths`Never copied, never gitignored`wp-config.php`, `wp-content/themes`, `wp-content/plugins``skip-if-exists`Copied on first install only; not gitignored`.htaccess`, `wp-content/index.php`Everything elseAlways synced from core; gitignored`wp-admin/`, `wp-includes/`, `wp-login.php`---

Managed `.gitignore` blocks
---------------------------

[](#managed-gitignore-blocks)

The plugin writes and maintains **two independent marked blocks** in your project's `.gitignore`. Everything outside these blocks is untouched.

### Core block

[](#core-block)

Updated whenever `composer install` or `composer update` runs the WordPress core installer:

```
#
# Managed by kanopi/wp-core-installer — do not edit this block manually.

# WordPress core staging directory (Composer internal — do not commit)
/wp-content/mu-plugins/vendor/.wordpress-core-staging/

# WordPress core files (managed via Composer — do not commit)
/wp-admin/
/wp-includes/
/index.php
/wp-activate.php
…

#
```

### Packages block

[](#packages-block)

Updated on every `composer install` / `composer update` run via a `post-install-cmd` / `post-update-cmd` hook:

```
#
# Managed by kanopi/wp-core-installer — do not edit this block manually.

# Composer vendor directory
/wp-content/mu-plugins/vendor/

# Composer-managed WordPress plugins
/wp-content/plugins/akismet/
/wp-content/plugins/woocommerce/

# Composer-managed WordPress themes
/wp-content/themes/twentytwentyfive/

#
```

Both blocks are **replaced wholesale** on each run (not appended), so adding or removing a package automatically keeps the ignore list in sync. Running `composer remove johnpbloch/wordpress-core` strips the **core** block.

---

Built-in protected paths (never overwritten)
--------------------------------------------

[](#built-in-protected-paths-never-overwritten)

PathReason`composer.json`, `composer.lock`Project manifests`wp-config.php`WordPress runtime config`wp-content/themes`Project-owned themes`wp-content/plugins`Project-owned plugins`wp-content/mu-plugins`Project-owned must-use plugins`wp-content/uploads`User-uploaded media`wp-content/upgrade`, `wp-content/languages`WordPress-managed dirs`.env` / `.env.*`Environment / secrets`.git`, `.gitignore`, `.gitattributes`VCS metadata`node_modules`, `vendor`Other dependency trees---

Typical project layout
----------------------

[](#typical-project-layout)

```
my-wordpress-site/
├── composer.json               ← protected
├── composer.lock               ← protected
├── wp-config.php               ← protected (you create this)
├── wp-admin/                   ← deployed by this plugin; gitignored
├── wp-includes/                ← deployed by this plugin; gitignored
├── index.php                   ← deployed by this plugin; gitignored
├── .htaccess                   ← skip-if-exists (first install only)
└── wp-content/
    ├── index.php               ← skip-if-exists (first install only)
    ├── mu-plugins/
    │   └── vendor/             ← gitignored (Composer vendor dir)
    ├── plugins/
    │   ├── index.php           ← skip-if-exists
    │   └── akismet/            ← gitignored (Composer-managed plugin)
    └── themes/
        ├── index.php           ← skip-if-exists
        ├── twentytwentyfive/   ← gitignored (Composer-managed theme)
        └── my-custom-theme/    ← NOT gitignored (not Composer-managed)

```

---

License
-------

[](#license)

MIT

###  Health Score

38

—

LowBetter than 83% of packages

Maintenance74

Regular maintenance activity

Popularity20

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity42

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 60% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~28 days

Total

3

Last Release

46d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/bf9dca5c46910be861bb00920034637b5a36a1f6277413be6817a50a1ce6fc74?d=identicon)[kanopi\_studios](/maintainers/kanopi_studios)

---

Top Contributors

[![sean-e-dietrich](https://avatars.githubusercontent.com/u/1564748?v=4)](https://github.com/sean-e-dietrich "sean-e-dietrich (3 commits)")[![paulsheldrake](https://avatars.githubusercontent.com/u/1062456?v=4)](https://github.com/paulsheldrake "paulsheldrake (2 commits)")

### Embed Badge

![Health badge](/badges/kanopi-wp-core-installer/health.svg)

```
[![Health](https://phpackages.com/badges/kanopi-wp-core-installer/health.svg)](https://phpackages.com/packages/kanopi-wp-core-installer)
```

###  Alternatives

[symfony/runtime

Enables decoupling PHP applications from global state

74694.9M938](/packages/symfony-runtime)[ergebnis/composer-normalize

Provides a composer plugin for normalizing composer.json.

1.1k40.0M2.6k](/packages/ergebnis-composer-normalize)[drupal/core-composer-scaffold

A flexible Composer project scaffold builder.

5344.1M526](/packages/drupal-core-composer-scaffold)[drupal/core-project-message

Adds a message after Composer installation.

2124.0M193](/packages/drupal-core-project-message)[sandersander/composer-link

Adds ability to link local packages for development with composer

94441.4k](/packages/sandersander-composer-link)[phpro/grumphp-shim

GrumPHP Phar distribution

284.6M333](/packages/phpro-grumphp-shim)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
