PHPackages                             nodus-it/dev-tools - 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. [DevOps &amp; Deployment](/categories/devops)
4. /
5. nodus-it/dev-tools

ActiveComposer-plugin[DevOps &amp; Deployment](/categories/devops)

nodus-it/dev-tools
==================

Einheitliche Dev-Befehle fuer Nodus-Projekte via Composer (d:\* Docker, qa:\* Lint/Analyse/Test) und bin/nd.

v1.0.1(3w ago)0127MITPHPPHP ^8.2

Since Jun 13Pushed 1w agoCompare

[ Source](https://github.com/nodus-it/dev-tools)[ Packagist](https://packagist.org/packages/nodus-it/dev-tools)[ Docs](https://github.com/nodus-it/dev-tools)[ RSS](/packages/nodus-it-dev-tools/feed)WikiDiscussions main Synced 1w ago

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

nodus-it/dev-tools
==================

[](#nodus-itdev-tools)

Unified developer commands for Nodus projects. Instead of maintaining copied `dev:up`/`dup`/`pint`/`qa` scripts in every repo, the logic lives centrally in this Composer plugin. Per project you only **configure**, you don't copy.

Two command groups from one codebase:

- **`d:*`** — Docker Compose control (`d:up`, `d:sh`, `d:art`, …)
- **`qa:*`** — code style, static analysis, tests (`qa:pint`, `qa:stan`, `qa:test`, `qa`)
- **`app:setup`** — get a freshly cloned project running

Three invocation layers:

Formworks whereexample`composer d:up` / `composer qa`everywhere, no setupsafest fallback`./vendor/bin/nd up`everywhere after `composer install`CI`nd up` / `nd qa`with `.envrc`/direnv or an aliaslocal everyday useInstallation (in the consuming project)
---------------------------------------

[](#installation-in-the-consuming-project)

`dev-tools` is a dev tool and belongs in the project's **`require-dev`**:

```
composer require --dev nodus-it/dev-tools
```

Composer will ask whether the plugin may run. Allow it permanently:

```
"config": {
    "allow-plugins": {
        "nodus-it/dev-tools": true
    }
}
```

### Why `require-dev` — and why the tools still come along

[](#why-require-dev--and-why-the-tools-still-come-along)

`dev-tools` pulls in `laravel/pint` and `phpstan/phpstan` through its own **`require`** (not `require-dev`, which is not installed transitively). They still **never end up in production**:

- `composer install` (dev/CI) → `dev-tools` is installed → pint/phpstan come with it.
- `composer install --no-dev` (prod) → `dev-tools` sits in the project's `require-dev` → the **entire subtree** incl. pint/phpstan is skipped.

The one rule: always put `dev-tools` in `require-dev`, never in `require`.

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

[](#configuration)

**Zero-config goal:** if a project follows the convention (compose files `.tools/docker/compose.yml` + `compose..yml`, service `app`, Pest, a root `phpstan.neon`), it needs **no** `extra.nodus-dev` block at all. The section below is only for deviations.

Everything project-specific lives under `extra.nodus-dev` in `composer.json`. Every field has a default.

```
"extra": {
    "nodus-dev": {
        "dir": ".tools/docker",
        "app-service": "app",
        "artisan": "php artisan",
        "default-env": "dev",
        "environments": {
            "dev":   ["compose.yml", "compose.dev.yml"],
            "stage": ["compose.yml", "compose.stage.yml"],
            "prod":  ["compose.yml", "compose.prod.yml"]
        },
        "test": "vendor/bin/pest"
    }
}
```

FieldDefaultMeaning`dir``.tools/docker`directory holding the compose files`app-service``app`service used by `sh`, `art`, `fresh``artisan``php artisan`artisan invocation inside the container`default-env``dev`environment used without `--env``environments`dev/stage/prodcompose file layers per environment`test`*heuristic*test runner; without a value: Pest, otherwise `artisan test``pint-config`*auto*path to a Pint config (else local `pint.json` / package default)`phpstan-config`*auto*path to a PHPStan config (else local `phpstan.neon` / central base)`phpstan-paths``["app","src"]`analysis paths in the zero-config case only (no local `phpstan.neon`)Migrating an existing project
-----------------------------

[](#migrating-an-existing-project)

Point an AI agent in the target project at [`ADOPT.md`](ADOPT.md) — it migrates the command layer and QA and clears out old script/config leftovers (Docker images are left untouched):

```
Read https://raw.githubusercontent.com/nodus-it/dev-tools/main/ADOPT.md
and run the migration for this project.

```

Docker commands (`d:*`)
-----------------------

[](#docker-commands-d)

`composer …``nd …`effect`d:up``nd up``compose up -d``d:down``nd down``compose down``d:build``nd build``compose build``d:ps``nd ps``compose ps``d:logs [svc]``nd logs [svc]``compose logs -f``d:sh [svc]``nd sh [svc]`shell in the container (bash, else sh)`d:art …``nd art …``artisan` in the app container`d:fresh``nd fresh``artisan migrate:fresh --seed`—`nd exec …`arbitrary command in the app container—`nd run …`one-off container (`run --rm`)Pick the environment: `--env=prod` or `-e prod`.

Passing options through to artisan:

```
nd art migrate --force                 # passed through cleanly
composer d:art -- migrate --force      # via Composer with the leading --
```

QA commands (`qa:*`)
--------------------

[](#qa-commands-qa)

`composer …``nd …`effect`qa:pint``nd pint`run Pint — `--test` to only check`qa:stan``nd stan`PHPStan analysis`qa:test``nd test`tests (Pest/PHPUnit/artisan test)`qa``nd qa``pint --test` → `stan` → `test`, stops at the first failure> Deliberately **no** short composer aliases (`pint`/`test`/…) so the plugin never shadows identically named project scripts. The short forms exist via the `nd` binary. Docker stays under `d:*`.

### Central QA rules, locally inheritable

[](#central-qa-rules-locally-inheritable)

`dev-tools` ships a base config: `config/pint.json` and `config/phpstan.neon`. The commands use them automatically as long as the project does not provide its own.

- **Pint** cannot inherit natively — `qa:pint` therefore points `--config` at the central `pint.json` (or a local one, if present).
- **PHPStan** inherits natively. Create a thin `phpstan.neon` in the project:

    ```
    includes:
        - vendor/nodus-it/dev-tools/config/phpstan.neon
    parameters:
        level: 6
        paths:
            - app
            - src
    ```

    Baselines (`phpstan-baseline.neon`) and level overrides stay **in the project**. Laravel projects add `larastan` to their own `require-dev` and to the local `includes` list — `dev-tools` stays framework-agnostic and pulls in no `illuminate/*`.

`app:setup`
-----------

[](#appsetup)

`composer app:setup` (or `nd setup`) gets a freshly cloned project running — every step is guarded by file existence:

1. `.env` from `.env.example` (if missing)
2. `artisan key:generate` + `artisan migrate --force` (if `artisan` exists)
3. `npm install && npm run build` (if `package.json` exists)
4. `artisan boost:install` (if `laravel/boost` is installed)

`nd` without `vendor/bin/` (optional)
-------------------------------------

[](#nd-without-vendorbin-optional)

An `.envrc` in the project (using [direnv](https://direnv.net/)):

```
PATH_add vendor/bin
```

Then `nd up` / `nd qa` works inside the project directory. Without direnv an alias does the job: `nd() { ./vendor/bin/nd "$@"; }`.

License
-------

[](#license)

MIT — see [LICENSE](LICENSE).

###  Health Score

43

—

FairBetter than 89% of packages

Maintenance97

Actively maintained with recent releases

Popularity14

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% 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 ~22 days

Total

2

Last Release

22d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/030fe5fffddf0c329473564b64057c625a3a6e92b0841650d6b196fbc644e0a6?d=identicon)[bastian-schur](/maintainers/bastian-schur)

---

Top Contributors

[![bastian-schur](https://avatars.githubusercontent.com/u/2923151?v=4)](https://github.com/bastian-schur "bastian-schur (6 commits)")

---

Tags

PHPStandockercomposer-plugindeveloper-toolsPintdocker-composenodus-it

### Embed Badge

![Health badge](/badges/nodus-it-dev-tools/health.svg)

```
[![Health](https://phpackages.com/badges/nodus-it-dev-tools/health.svg)](https://phpackages.com/packages/nodus-it-dev-tools)
```

###  Alternatives

[shipmonk/dead-code-detector

Dead code detector to find unused PHP code via PHPStan extension. Can automatically remove dead PHP code. Supports libraries like Symfony, Doctrine, PHPUnit etc. Detects dead cycles. Can detect dead code that is tested.

4853.5M98](/packages/shipmonk-dead-code-detector)[norsys/rothenberg

Tool which allow a developper to create or maintain a Symfony application or a Symfony bundle very easily and without install something on his workstation

2410.9k3](/packages/norsys-rothenberg)[orrison/meliorstan

Provides PHPStan rules for improved code quality by detecting code smells and possible issues. In addition to enforcing particular naming and code style conventions to reduce bike-shedding.

1915.9k5](/packages/orrison-meliorstan)[downtoworld/laravel-devops

Laravel Cloudflare-Tunnels Ready Production Docker-Compose

161.1k](/packages/downtoworld-laravel-devops)

PHPackages © 2026

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