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. 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]
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); the lone exception 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.2

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.2
File Size Uploaded
scoop_latex_packer-0.1.2.tar.gz 28.2 kB Details

Built distribution (wheel)

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

Total release size: 57.1 kB

Release files / scoop_latex_packer-0.1.2.tar.gz

Download URL scoop_latex_packer-0.1.2.tar.gz
Size 28.2 kB
Tags Source
SHA-256 checksum
How to use checksums
50aae395396ed63e03f51765f99356956c37ca81f292b6bcf6e2df1c321cc239
BLAKE2b-256 checksum
How to use checksums
5f8f7f165eadaeeae05910036480078455b15832ca0666d59cd4538c28fed147
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.2-py3-none-any.whl

Download URL scoop_latex_packer-0.1.2-py3-none-any.whl
Size 28.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4833ce13eada2f1a192d5b67a4a7909c2203fba2e23a8dcc32e2c643430f576c
BLAKE2b-256 checksum
How to use checksums
4f08517f479e2d38e9a085a187faf35213075dcd1e59844cbe9a999e86d48fdf
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

0.1.4

2 release files

0.1.3

2 release files

This release

0.1.2 This release

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