# Comments in composer.json

`composer.json` is JSON, and JSON has no comment syntax. Composer reads the file strictly: a `//` or `/* */` comment anywhere in it stops every command — `validate`, `install`, `update`, `require` — before it does anything:

```
"./composer.json" does not contain valid JSON
Lexical error on line 7. Comments are not allowed.
```

Composer's maintainers have [declined to allow comments](https://github.com/composer/composer/pull/11292) and point to the `_comment` key instead.

## The _comment key

Composer documents one top-level key for comments, `_comment`: a string or an array of strings. `composer validate` accepts it, with `--strict` too, and `composer require` and `composer remove` leave it where it is:

```json
{
  "_comment": [
    "guzzlehttp/guzzle: the payment provider's SDK needs 7.x (PAY-12)",
    "monolog/monolog: the log shipper parses the JSON formatter's output"
  ],
  "require": {
    "guzzlehttp/guzzle": "^7.9",
    "monolog/monolog": "^3.8"
  }
}
```

That works, within limits:

- **It sits away from the packages.** The comments are at the top, the packages further down, and nothing ties a line to its package.
- **It cannot be a map.** With `"_comment": { "monolog/monolog": "…" }`, both `composer validate` and `composer install` stop: `Object value found, but an array or a string is required`.
- **It cannot go inside `require`.** There Composer reads it as a package and stops with `Could not parse version constraint`.
- **It outlives the package.** `composer remove monolog/monolog` deletes the `require` line and leaves the comment about it. A second `_comment` key does not help either: `composer validate` warns that the key is a duplicate, and PHP keeps only the last one.

## A "//" key, or extra

A `"//"` key works for `composer install`, but `composer validate` fails it: `The property // is not defined and the definition does not allow additional properties`. The file is then valid for installing and not for publishing as a package.

`extra` holds arbitrary data for scripts and plugins. A note under it validates and installs cleanly, and Composer does not read it — but it is as far from the package as `_comment`, and as stale once the package is gone.

## A note on the package's line

Pacmon keeps the notes in a file of their own, `.pacmon/composer/DEPENDENCY-NOTES.md`, beside `composer.json`, one section per package:

```md
## monolog/monolog

Logging for the API and the queue workers.

### Agent notes

- purpose: logging for the API and the queue workers
- constraint: stay on 3.x — the log shipper parses the JSON formatter's output (OPS-19)
- verify: `vendor/bin/phpunit --testsuite logging`
```

In `composer.json`, the first line of the note appears at the end of the package's line, and the whole note on hover. `composer.json` itself stays plain JSON, which Composer reads as before. When a package is removed, its section stays, with `- status: removed <YYYY-MM> — <reason>` under `### Agent notes`.

[Dependency notes for PHP](https://pacmon.dev/php/) covers the details.
