# Changelog

This changelog format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

<!-- Posible headings: Added, Changed, Deprecated, Fixed, Removed, Security -->

## [0.9.0] - Unreleased

### Added

- `mutate_content` operation: mutate page content streams
  using a user-supplied Python script

- `update_info`: Support setting `PdfID0` to "RESET" to force valid
  ID regeneration on save.

- `replacement_font` option: change the font used for user
  text in forms

### Changed

- `--version` includes optional dependency versions

- Documentation updated for `dump_data`, `dump_annots`, and
  `dump_data_fields` to better explain output formats and
  pdftk compatibility.

### Fixed

- Compatibility: `generate_fdf` fixed and `replacement_font`
  implemented. Now passes the pdftk-java tests using
  bleeding edge `pikepdf`.

- startup performance improvements: lazy loading, and
  working around heavy Rich formatting for default help text

- Pipeline: Read-only operations (like `dump_text`) now
  implicitly pass the input PDF to the next stage, fixing
  chained commands (e.g., `dump_text --- cat`).

- Handling of features with missing dependencies should be
  more consistent.

## [0.8.0] - 2026-17-01

### Added

- Official support for Python 3.14

- More comprehensive `vendor_tests/pdftk-java` test suite,
  from `pdftk-java`. This test suite only is licensed under
  the GPL 2, see NOTICE.md.

- `no_encrypt_metadata` option: do not encrypt
  metadata. Only supported by AES encryption methods.

- `COMPATIBILITY.md`: compatibility notes

- `dump_data_fields` now extracts tooltips (FieldNameAlt)
  and default values (FieldValueDefault).

- API: inputs now support pathlib.Path objects directly.

### Changed

- Encryption method now defaults to `encrypt_aes128` if
  `user_pw` or `owner_pw` are passed, instead of not
  encrypting. This is more similar to `pdftk`.

- `attach_files` is now an operation, not an output option
  (pdftk compatibility)

- exit codes better aligned with pdftk's exit codes

- CLI: stricter argument parsing now raises
  `DuplicateArgumentError` if keywords are repeated.

### Fixed

- `cat` should now properly handle forms.

- `fill_form` compatibility fixes

- `dump_data_fields_utf8`: fixed crash/output issues.

- `set_info`: added validation for page label indices and
  better error handling for rotation/mediabox.

## [0.7.0] - 2026-01-11

### Added

- automated `pdftk` compatibility testing using third party
  php test suite.

- `drop_xfa` output option to drop XFA form data (pdftk compatibility)

- `render` operation: rasterize pages

- `move`, `update_info`, `update_info_utf8` now accept
  instructions from a JSON "at-file" using `@filename.json`
  in place of CLI arguments

- `dump_data` gives JSON output via the `json` keyword

- extensibility: add custom operations by putting Python
  files in `~/.config/pdftl/operations` (*nix) or
  `%APPDATA%\pdftl\config` (windows)

### Fixed

- bug in `add_pages.py` when a page has an integer key-value

- more comprehensive handling of the five PDF page boxes for
  `dump_data` and `update_info`

- `drop_info` and `drop_xmp` output options should now work
  as claimed

- `flatten` reimplemented for robustness

## [0.6.0] - 2026-01-04

### Added

- `move` operation: move pages within a PDF file

- `place` operation: shift, scale and/or spin content within
  the page

### Changed

- Now handles compound page specifications like `1,3-4,7-end`

### Fixed

- Improved API documentation generation

### Removed

- `spin` operation. See `place` for this functionality.

## [0.5.0] - 2026-01-03

### Added

- `add_text` features:

  - source metadata variables (`source_filename`,
    `source_page`, etc)

  - Bates stamping variable features,
    e.g. `DEF-{page+120:06d}` produces DEF-000121, DEF-000122,
    ...

- `insert` operation: insert blank pages

## [0.4.1] - 2026-01-02

### Fixed

- Broken link in README.md

## [0.4.0] - 2026-01-01

### Added

- API with fluent and functional interfaces
- `docs/api_tutorial.md` and auto-generated API docs

### Changed

- Renamed operation: `list_files` is now `dump_files`

### Fixed

- Fixed bug preventing parsing of the page specification "right"

## [0.3.1] - 2025-12-20

### Fixed

- `README.md` corrected, and "platform" badge added

## [0.3.0] - 2025-12-20

### Added

- Get `help` by tag with `pdftl help tag:<tagname>`

- `dump_signatures`: view and validate PDF signatures

- PDF signature output options:

  - `sign_cert <file>` Path to certificate PEM

  - `sign_field <name>` Signature field name (default: Signature1)

  - `sign_key <file>` Path to private key PEM

  - `sign_pass_env <var>` Environment variable with sign_cert passphrase

  - `sign_pass_prompt` Prompt for sign_cert passphrase

- `dump_layers`: dump PDF optional content groups (OCGs), a.k.a. "layers"

### Fixed

- performance improvements for `cat`

## [0.2.1] - 2025-12-17

### Added

- `crop`: added `fit` and `fit-group`

- artwork

- extended NOTICE.md: acknowledge `pikepdf`/`qpdf` and `pypdfium2`

- Windows testing

### Fixed

- performance improvements (lazy-loaded imports)

- help tweaks: add sources for non-operations; more help topic aliases

## [0.2.0] - 2025-12-13

### Added

- readthedocs integration and docs generation

### Fixed

- Improved help text

## [0.1.1] - 2025-12-12

### Added

- codecov integration
- PyPI publish integration

## [0.1.0] - 2025-12-11

### Added

- Initial public release of `pdftl`.
- Operations:
  - ``add_text``               Add user-specified text strings to PDF pages
  - ``background``             Use a 1-page PDF as the background for each page
  - ``burst``                  Split a single PDF into individual page files
  - ``cat``                    Concatenate pages from input PDFs into a new PDF
  - ``chop``                   Chop pages into multiple smaller pieces
  - ``crop``                   Crop pages
  - ``delete``                 Delete pages from an input PDF
  - ``delete_annots``          Delete annotation info
  - ``dump_annots``            Dump annotation info
  - ``dump_data``              Metadata, page and bookmark info (XML-escaped)
  - ``dump_data_annots``       Dump annotation info in pdftk style
  - ``dump_data_fields``       Print PDF form field data with XML-style escaping
  - ``dump_data_fields_utf8``  Print PDF form field data in UTF-8
  - ``dump_data_utf8``         Metadata, page and bookmark info (in UTF-8)
  - ``dump_dests``             Print PDF named destinations data to the console
  - ``dump_text``              Print PDF text data to the console or a file
  - ``fill_form``              Fill a PDF form
  - ``filter``                 Do nothing. (The default if ``<operation>`` omitted.)
  - ``generate_fdf``           Generate an FDF file containing PDF form data
  - ``inject``                 Inject code at start or end of page content streams
  - ``list_files``             List file attachments
  - ``modify_annots``          Modify properties of existing annotations
  - ``multibackground``        Use multiple pages as backgrounds
  - ``multistamp``             Stamp multiple pages onto an input PDF
  - ``normalize``              Reformat page content streams
  - ``optimize_images``        Optimize images
  - ``replace``                Regex replacement on page content streams
  - ``rotate``                 Rotate pages in a PDF
  - ``shuffle``                Interleave pages from multiple input PDFs
  - ``spin``                   Spin page content in a PDF
  - ``stamp``                  Stamp a 1-page PDF onto each page of an input PDF
  - ``unpack_files``           Unpack file attachments
  - ``update_info``            Update PDF metadata
  - ``update_info_utf8``       Update PDF metadata from dump_data_utf8 instructions
- Output options:
  - ``allow <perm>...``        Specify permissions for encrypted files
  - ``attach_files <file>``... Attach files to the output PDF
  - ``compress``               (default) Compress output file streams
  - ``drop_info``              Discard document-level info metadata
  - ``drop_xmp``               Discard document-level XMP metadata
  - ``encrypt_128bit``         Use 128 bit encryption (obsolete, maybe insecure)
  - ``encrypt_40bit``          Use 40 bit encryption (obsolete, highly insecure)
  - ``encrypt_aes128``         Use 128 bit AES encryption (maybe obsolete)
  - ``encrypt_aes256``         Use 256 bit AES encryption
  - ``flatten``                Flatten all annotations
  - ``keep_final_id``          Copy final input PDF's ID metadata to output
  - ``keep_first_id``          Copy first input PDF's ID metadata to output
  - ``linearize``              Linearize output file(s)
  - ``need_appearances``       Set a form rendering flag in the output PDF
  - ``output <file>``          The output file path, or a template for 'burst'
  - ``owner_pw <pw>``          Set owner password and encrypt output
  - ``uncompress``             Disables compression of output file streams
  - ``user_pw <pw>``           Set user password and encrypt output
  - ``verbose``                Turn on verbose output
