Skip to main content

scoop-latex-packer

scoop-latex-packer takes a top-level .tex file, resolves its dependencies, and packs them into a .zip suitable for submission to a publisher or to arXiv. It also validates the resulting archive by re-compiling it in a sterile environment, so you find out before submission whether anything is missing.

Installation

pip install scoop-latex-packer

This installs the slp command (with scoop-latex-packer available as a longer-form alias). The examples below use slp.

Requirements

  • Python 3.11 or newer.
  • latexmk and kpsewhich on PATH. Both ship with every standard TeX distribution (TeX Live, MiKTeX, MacTeX).

Usage

The CLI has three subcommands: pack builds a submission archive, analyze prints what pack would include without writing the archive, and validate verifies that an archive compiles in isolation. Run slp with no arguments to see the top-level help.

The top-level .tex file argument to pack is optional: if you omit it, slp looks for a unique .tex file containing \documentclass in the current directory and uses that. With several top-level files in one directory, the top-level config key (see below) saves naming the file on every call. If the argument carries a directory component (e.g. papers/preprint.tex or /abs/path/preprint.tex), slp changes into that directory before packing, so all output files — including the resulting .zip — land beside the source.

# Pack the only top-level .tex file in the current directory.
slp pack

# Pack a specific top-level .tex file.
slp pack preprint.tex

# Pack a paper that lives in another directory — slp changes
# into that directory first, so the resulting .zip lands beside the source.
slp pack papers/preprint.tex
slp pack ~/Work/papers/preprint.tex

# Pack for arXiv submission (currently the same as --freeze-minted).
slp pack --arxiv preprint.tex

# Include extra data files that the recorder doesn't detect (repeat for multiple).
slp pack --extra-file data/run1.csv --extra-file data/run2.csv preprint.tex

# Show what pack would include in the archive without actually writing it.
# Accepts the same flags as `pack` (e.g. --arxiv to preview the prepends).
slp analyze preprint.tex
slp analyze --arxiv preprint.tex

# Verify that the resulting archive compiles with no help from your local
# TEXINPUTS/BIBINPUTS/BSTINPUTS environment.
slp validate preprint.zip

# Keep the extraction directory around for poking at after a failure.
slp validate --keep-tmpdir preprint.zip

slp <subcommand> --help (or scoop-latex-packer <subcommand> --help) lists every option for that subcommand.

Project-local config

A slp.toml file next to the top-level .tex is auto-loaded; CLI flags always win over config values, which in turn win over the built-in defaults. pack and analyze share the [pack] section; validate reads [validate].

[pack]
top-level = "preprint.tex"
arxiv = true
extra-files = ["data/run1.csv", "data/run2.csv"]

[validate]
no-open = true

You can keep several configs side-by-side in the same directory (arxiv.toml, journal-x.toml, …) and pick one with -c / --config:

slp pack -c arxiv.toml preprint.tex
slp pack -c journal-x.toml preprint.tex

Config keys mirror the CLI flag names with hyphens (e.g. freeze-minted = true); top-level stands in for the positional argument and must be a bare filename next to the config file; the lone exception to the mirroring is include-bibfiles = false, the positive form of --exclude-bibfiles. Unknown keys produce a warning so typos surface immediately.

A reference examples/slp.toml ships in the development repository (not in the PyPI wheel) with every supported key set to its default value — copy it as a starting point.

Features

  • Works with bibtex and biber/biblatex bibliographies.
  • Auto-detects the top-level .tex file from the presence of \documentclass.
  • Finds dependent files on TEXINPUTS, BIBINPUTS, and BSTINPUTS.
  • Ships bibliography sources (.bib/.bst) by default and drops the generated .bbl (as well as .toc/.lof/.lot); the recipient regenerates them. This avoids the arXiv TeX Live 2025 .bbl version-mismatch error, and matches arXiv's current recommendation to upload .bib files. A publisher that wants the .bbl anyway gets it via --extra-file preprint.bbl.
  • --freeze-minted makes the archive compile without --shell-escape, which arXiv disables, by prepending \PassOptionsToPackage{frozencache}{minted} to the top-level file and shipping the minted cache. --arxiv is currently an alias for --freeze-minted; see minted and arXiv below.
  • validate re-compiles the archive in an isolated temp directory with the TEXINPUTS/BIBINPUTS/BSTINPUTS variables stripped, catching missing dependencies before you submit.

minted and arXiv

arXiv compiles without --shell-escape, so minted must read every snippet from a cache shipped inside the archive. How that cache is produced depends on the minted version, which slp detects via kpsewhich minted.sty:

minted Discovery run Cache shipped Top-level prepend
v2 with \PassOptionsToPackage{finalizecache}{minted} injected via latexmk -usepretex _minted-<jobname>/ with listingN.pygtex files frozencache
v3 plain --shell-escape run _minted/ with content-addressed *.highlight.minted files frozencache

The minted cache files are picked up like any other dependency, through the latexmk -recorder file, so no special handling is needed to include them. arXiv's default TeX Live 2025 compiler uses minted v3, while its optional TeX Live 2023 compiler uses minted v2.9. A v2 cache is useless to minted v3 and vice versa, so pack under the TeX Live generation you will select at arXiv, e.g. in a texlive/texlive:TL2025-historic container.

Limitations

  • Files included via relative paths outside the current directory (e.g. \includegraphics{../somedir/result.pdf}) cannot be packed: the archive layout assumes everything lives at or below the project root. pack (and analyze) detect these and abort with a non-zero exit and a message naming every offending file, rather than silently producing a broken archive. Move such files under the project directory (and update the reference in your .tex) before packing.
  • A bibliography resource named with a subdirectory (e.g. \addbibresource{shared/refs.bib}) that lives outside the project — found through an absolute BIBINPUTS/BSTINPUTS search path — is packed under its bare filename at the archive root, so the shared/ part of the reference no longer resolves. Keep such resources under the project directory. validate catches this case by failing the sterile recompile.

Development

The development repository lives at https://gitlab.com/scoopgroup-public/scoop-latex-packer and contains a tests/ directory with sample .tex and .bib fixtures. The tests/ directory is excluded from the PyPI wheel and sdist, so end users never see it.

git clone https://gitlab.com/scoopgroup-public/scoop-latex-packer
cd scoop-latex-packer
python -m venv .venv && source .venv/bin/activate
pip install -e .
# Now run pack/validate against the fixtures in tests/.

License

MIT — see LICENSE.

Metadata

Release files for scoop-latex-packer 0.1.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for scoop-latex-packer 0.1.4
File Size Uploaded
scoop_latex_packer-0.1.4.tar.gz 29.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for scoop-latex-packer 0.1.4
File Interpreter ABI Platform
scoop_latex_packer-0.1.4-py3-none-any.whl Python 3 none any Details

Total release size: 58.3 kB

Release files / scoop_latex_packer-0.1.4.tar.gz

Download URL scoop_latex_packer-0.1.4.tar.gz
Size 29.0 kB
Tags Source
SHA-256 checksum
How to use checksums
824b505aeb35324f6a435dcdde8da9e373f2d43ec11a0a5584df6754b5e56b63
BLAKE2b-256 checksum
How to use checksums
b355315bd635a3c93bb0d6bbb2e2b49bbf40eed9afde1e87f7d39fb2aac6ba5e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / scoop_latex_packer-0.1.4-py3-none-any.whl

Download URL scoop_latex_packer-0.1.4-py3-none-any.whl
Size 29.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e958ea92d096bcca0566bb898d6937f545a696d216630ca9371431906c3166d7
BLAKE2b-256 checksum
How to use checksums
d5ded154ee74ebf9fb35a91f9203cb3c7e4dc21d5ad6d1612a4725b7714c15de
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release history Release notifications | RSS feed

This release

0.1.4 This release

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page