diff --git a/.github/workflows/tasks.yml b/.github/workflows/tasks.yml
new file mode 100644
index 0000000..dbf2616
--- /dev/null
+++ b/.github/workflows/tasks.yml
@@ -0,0 +1,26 @@
+name: Tasks
+
+on: [push, pull_request]
+
+jobs:
+ lint-php:
+ name: "php: ${{ matrix.php }}"
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ php: [ '7.3', '7.4', '8.0', '8.1' ]
+ steps:
+ - name: Setup PHP with PECL extension
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php }}
+ - uses: actions/checkout@v2
+ - uses: actions/cache@v2
+ with:
+ path: ~/.composer/cache/files
+ key: ${{ runner.os }}-${{ matrix.php }}-composer-${{ hashFiles('**/composer.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-${{ matrix.php }}-composer-
+ - run: composer install --no-interaction --no-progress
+ - run: ./vendor/bin/grumphp run --ansi
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..d1502b0
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+vendor/
+composer.lock
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..7efbb9e
--- /dev/null
+++ b/README.md
@@ -0,0 +1,31 @@
+# @no-ci composer plugin
+
+## install
+
+``composer req andersundsehr/no-ci``
+
+## what dose it do
+
+This plugin adds the possibility to add `@no-ci`/`@ci` to any composer script.
+you can Add it in front of every possible composer script. [documentation](https://getcomposer.org/doc/articles/scripts.md#writing-custom-commands)
+
+### Example composer.json
+````json
+{
+ "scripts": {
+ "test": [
+ "@no-ci @php vendor/bin/phpunit -c phpunit.xml",
+ "@ci @php vendor/bin/phpunit -c phpunit-ci.xml"
+ ],
+ "other:examples": [
+ "@no-ci Composer\\Config::disableProcessTimeout",
+ "@no-ci @clearCache",
+ "@no-ci @composer install",
+ "@no-ci @php script.php",
+ "@no-ci @putenv COMPOSER=phpstan-composer.json",
+ "@no-ci ls -alh"
+ ],
+ "clearCache": "rm -rf var"
+ }
+}
+````
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..832c792
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,47 @@
+{
+ "name" : "andersundsehr/no-ci",
+ "description" : "composer @no-ci addon",
+ "type" : "composer-plugin",
+ "license" : "GPL-2.0-or-later",
+ "autoload" : {
+ "psr-4" : {
+ "AUS\\NoCi\\" : "src/"
+ }
+ },
+ "authors" : [
+ {
+ "name" : "Matthias Vogel",
+ "email" : "m.vogel@andersundsehr.com"
+ }
+ ],
+ "scripts" : {
+ "test": "@no-ci @php -v"
+ },
+ "require" : {
+ "composer-plugin-api" : "^2.0",
+ "ondram/ci-detector": "^4.1",
+ "php": "^7.3 || ^8.0"
+ },
+ "require-dev": {
+ "composer/composer": "^2.0",
+ "pluswerk/grumphp-config": "^5"
+ },
+ "extra": {
+ "class": "AUS\\NoCi\\Plugin",
+ "pluswerk/grumphp-config": {
+ "auto-setting": true
+ },
+ "grumphp": {
+ "config-default-path": "vendor/pluswerk/grumphp-config/grumphp.yml"
+ }
+ },
+ "config": {
+ "allow-plugins": {
+ "typo3/cms-composer-installers": true,
+ "typo3/class-alias-loader": true,
+ "phpro/grumphp": true,
+ "phpstan/extension-installer": true,
+ "pluswerk/grumphp-config": true
+ }
+ }
+}
diff --git a/src/Plugin.php b/src/Plugin.php
new file mode 100644
index 0000000..639bdec
--- /dev/null
+++ b/src/Plugin.php
@@ -0,0 +1,70 @@
+ 'noCi',
+ 'ci' => 'ci',
+ ];
+ }
+
+ public function noCi(Event $event): void
+ {
+ if ($this->isCi()) {
+ $event->getIO()->write('CI detected, skipping: ' . implode(' ', $event->getArguments()) . '');
+ return;
+ }
+ $this->runOriginalScript($event);
+ }
+
+ public function ci(Event $event): void
+ {
+ if (!$this->isCi()) {
+ $event->getIO()->write('no CI detected, skipping: ' . implode(' ', $event->getArguments()) . '');
+ return;
+ }
+ $this->runOriginalScript($event);
+ }
+
+ private function runOriginalScript(Event $event): void
+ {
+ $eventName = 'run-@no-ci-' . implode('-', $event->getArguments());
+ $dispatcher = $event->getComposer()->getEventDispatcher();
+ $childEvent = new Event($eventName, $event->getComposer(), $event->getIO(), $event->isDevMode(), [], $event->getFlags());
+ if (!$dispatcher->hasEventListeners($childEvent)) {
+ $dispatcher->addListener($eventName, implode(' ', $event->getArguments()));
+ }
+ $dispatcher->dispatch(null, $childEvent);
+ }
+
+ public function activate(Composer $composer, IOInterface $io)
+ {
+ }
+
+ public function deactivate(Composer $composer, IOInterface $io)
+ {
+ }
+
+ public function uninstall(Composer $composer, IOInterface $io)
+ {
+ }
+
+ private function isCi(): bool
+ {
+ return (new CiDetector())->isCiDetected();
+ }
+}