diff --git a/.github/workflows/lint-php-cs.yml b/.github/workflows/lint-php-cs.yml
new file mode 100644
index 0000000..b460796
--- /dev/null
+++ b/.github/workflows/lint-php-cs.yml
@@ -0,0 +1,53 @@
+name: Lint php-cs
+
+on: pull_request
+
+permissions:
+  contents: read
+
+concurrency:
+  group: lint-php-cs-${{ github.head_ref || github.run_id }}
+  cancel-in-progress: true
+
+jobs:
+  lint:
+    runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        php:
+          - "8.1"
+          - "8.2"
+          - "8.3"
+          - "8.4"
+
+    name: php-cs
+
+    steps:
+      - name: Checkout
+        uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+        with:
+          persist-credentials: false
+
+      - name: Set up php${{ matrix.php }}
+        uses: shivammathur/setup-php@ec406be512d7077f68eed36e63f4d91bc006edc4 # v2.35.4
+        with:
+          php-version: ${{ matrix.php }}
+          coverage: none
+          ini-file: development
+
+      - name: Get composer cache directory
+        id: composer-cache
+        run: echo "::set-output name=dir::$(composer config cache-files-dir)"
+
+      - name: Cache composer cache
+        uses: actions/cache@v4
+        with:
+          path: ${{ steps.composer-cache.outputs.dir }}
+          key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
+          restore-keys: ${{ runner.os }}-composer-
+
+      - name: Install dependencies
+        run: composer install
+
+      - name: Lint
+        run: composer cs:check || ( echo 'Please run `composer run cs:fix` to format your code' && exit 1 )
diff --git a/.gitignore b/.gitignore
index 0c2a5dd..f764d68 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,5 +3,6 @@ composer.lock
 /vendor/
 /vendor-bin/**/vendor/
 *.swp
+.php-cs-fixer.cache
 .phpunit.result.cache
 /tests/logs
diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php
new file mode 100644
index 0000000..4b9869d
--- /dev/null
+++ b/.php-cs-fixer.dist.php
@@ -0,0 +1,18 @@
+setParallelConfig(ParallelConfigFactory::detect())
+	->getFinder()
+	->ignoreVCSIgnored(true)
+	->notPath('vendor')
+	->notPath('vendor-bin')
+	->in(__DIR__);
+return $config;
diff --git a/composer.json b/composer.json
index d043eca..9e8b5e9 100644
--- a/composer.json
+++ b/composer.json
@@ -31,6 +31,8 @@
     "scripts": {
         "bin": "echo 'bin not installed'",
         "lint": "find . -name \\*.php -not -path './vendor/*' -not -path './vendor-bin/*' -print0 | xargs -0 -n1 php -l",
+        "cs:check": "php-cs-fixer fix --dry-run --diff",
+        "cs:fix": "php-cs-fixer fix",
         "post-install-cmd": [
             "@composer bin all install --ansi",
             "composer dump-autoload"
diff --git a/src/Command.php b/src/Command.php
index 0919e6b..aa9f886 100644
--- a/src/Command.php
+++ b/src/Command.php
@@ -1,4 +1,5 @@
 > >>
 endobj
 trailer
diff --git a/src/InfoFields.php b/src/InfoFields.php
index 09f4655..9599e14 100644
--- a/src/InfoFields.php
+++ b/src/InfoFields.php
@@ -1,4 +1,5 @@
 _command === null) {
-            $this->_command = new Command;
+            $this->_command = new Command();
         }
         return $this->_command;
     }
diff --git a/src/XfdfFile.php b/src/XfdfFile.php
index c1be2d9..ff75a16 100644
--- a/src/XfdfFile.php
+++ b/src/XfdfFile.php
@@ -1,4 +1,5 @@
 
 
 
@@ -60,7 +61,7 @@ class XfdfFile extends File
 FDF;
 
     // XFDF file footer
-    const XFDF_FOOTER = <<
 
 
@@ -198,14 +199,14 @@ protected function writeXml($fields)
     protected function writeFields($fp, $fields)
     {
         foreach ($fields as $key => $value) {
-            $key = $this->xmlEncode(substr($key,1));
+            $key = $this->xmlEncode(substr($key, 1));
             fwrite($fp, "\n");
             if (!is_array($value)) {
                 $value = array($value);
             }
             if (array_key_exists(0, $value)) {
                 // Numeric keys: single or multi-value field
-                foreach($value as $val) {
+                foreach ($value as $val) {
                     $val = $this->xmlEncode($val);
                     fwrite($fp, "$val\n");
                 }
diff --git a/tests/unit/CommandTest.php b/tests/unit/CommandTest.php
index c87069b..3a9fa62 100644
--- a/tests/unit/CommandTest.php
+++ b/tests/unit/CommandTest.php
@@ -1,4 +1,5 @@
 getDocument2();
         $file = $this->getOutFile();
 
-        $command = new Command;
+        $command = new Command();
         $this->assertEquals(0, $command->getFileCount());
         $this->assertInstanceOf('mikehaertl\pdftk\Command', $command->addFile($document1, 'A'));
         $this->assertInstanceOf('mikehaertl\pdftk\Command', $command->addFile($document2, 'B', 'complex\'"password'));
@@ -37,7 +38,7 @@ public function testCanAddOptions()
         $document1 = $this->getDocument1();
         $file = $this->getOutFile();
 
-        $command = new Command;
+        $command = new Command();
         $this->assertInstanceOf('mikehaertl\pdftk\Command', $command->addFile($document1, 'A'));
         $this->assertInstanceOf('mikehaertl\pdftk\Command', $command->addOption('encrypt_40bit'));
         $this->assertInstanceOf('mikehaertl\pdftk\Command', $command->addOption('allow', 'Printing', false));
@@ -53,7 +54,7 @@ public function testCanSetAndGetOperationAndArgument()
         $document1 = $this->getDocument1();
         $file = $this->getOutFile();
 
-        $command = new Command;
+        $command = new Command();
         $this->assertInstanceOf('mikehaertl\pdftk\Command', $command->addFile($document1, 'A'));
         $this->assertInstanceOf('mikehaertl\pdftk\Command', $command->setOperation('cat'));
         $this->assertInstanceOf('mikehaertl\pdftk\Command', $command->setOperationArgument('A'));
@@ -70,7 +71,7 @@ public function testCanAddPageRanges()
         $document1 = $this->getDocument1();
         $file = $this->getOutFile();
 
-        $command = new Command;
+        $command = new Command();
         $this->assertInstanceOf('mikehaertl\pdftk\Command', $command->addFile($document1, 'A'));
         $this->assertInstanceOf('mikehaertl\pdftk\Command', $command->setOperation('cat'));
         $this->assertInstanceOf('mikehaertl\pdftk\Command', $command->addPageRange(1));
diff --git a/tests/unit/DataFieldsTest.php b/tests/unit/DataFieldsTest.php
index 727fed6..0333087 100644
--- a/tests/unit/DataFieldsTest.php
+++ b/tests/unit/DataFieldsTest.php
@@ -1,4 +1,5 @@
 getDocument2();
         $file = $this->getOutFile();
 
-        $pdf = new Pdf;
+        $pdf = new Pdf();
         $this->assertInstanceOf('mikehaertl\pdftk\Pdf', $pdf->addFile($document1, null, 'complex\'"password'));
         $this->assertInstanceOf('mikehaertl\pdftk\Pdf', $pdf->addFile($document2, 'D'));
         $this->assertTrue($pdf->saveAs($file));
@@ -136,7 +137,7 @@ public function testCanPerformEmptyOperation()
         $document1 = $this->getDocument1();
         $file = $this->getOutFile();
 
-        $pdf = new Pdf;
+        $pdf = new Pdf();
         $this->assertInstanceOf('mikehaertl\pdftk\Pdf', $pdf->addFile($document1, null, 'complex\'"password'));
         $this->assertTrue($pdf->saveAs($file));
         $this->assertFileExists($file);
diff --git a/tests/unit/XfdfFileTest.php b/tests/unit/XfdfFileTest.php
index e899e52..430bc50 100644
--- a/tests/unit/XfdfFileTest.php
+++ b/tests/unit/XfdfFileTest.php
@@ -1,4 +1,5 @@