Pack and unpack multiple text files into single readable text file.
Find a file
2025-11-02 23:49:13 +01:00
.idea Initial 2025-11-02 16:54:36 +01:00
src/monofile Fixes 2025-11-02 23:49:13 +01:00
pyproject.toml Initial 2025-11-02 16:54:36 +01:00
README.md Fixes and README.md 2025-11-02 21:31:40 +01:00

monofile — Pack/Unpack a project into one humanreadable file (.mono)

monofile is a tiny CLI that bundles a directory tree into a single UTF8 text file with the .mono extension and reconstructs the project back on disk later. Its designed for pasting, diffing, code review, and moving small projects around without binary blobs or tarballs.

The .mono format is intentionally simple: its just text with clear markers for directories and files plus each files encoding. Example snippets look like:

MONOFILE v1
# Root: my-project

----- DIR src -----
----- END DIR -----

----- FILE src/app.py -----
EncodingUsed: utf-8
----- BEGIN CONTENT -----
print("hello")
----- END CONTENT -----
----- END FILE -----

Features

  • monofile pack → create project.mono from a directory
  • monofile unpack → restore files from the configured .mono
  • monofile init → generate a starter monofile.config
  • Sensible defaults:
    • Whitelist of common text extensions (e.g. .py,.md,.toml,.yml,.json,… plus Makefile, Dockerfile, etc.)
    • Blacklist excludes *.mono and monofile.config by default
  • Skips obvious binary files (null bytes or nonUTF8 by default)

Installation

Requires Python ≥ 3.9

pip install git+https://github.com/Cubiss/monofile.git

The package installs a console script named monofile.


CLI reference

monofile pack [PATH]       # Pack a directory into a .mono archive
monofile unpack [PATH]     # Unpack the configured/default .mono
monofile init [PATH]       # Create a default monofile.config
  -f, --force              # Overwrite existing config on init
  • PATH defaults to ..
  • On pack, the output archive path is taken from the configs project_file (default: project.mono) and written next to monofile.config.
  • On unpack, files are written relative to the configured root and created as needed; directories are created recursively.

Configuration (monofile.config)

monofile reads a plain INIlike file with simple key = value lines, generated by monofile init.

Example (with defaults shown as comments):

# monofile.config (auto-generated)
# Human-readable project packer configuration
# project_file = project.mono
# extension_whitelist = .py,.txt,.md,.json,.yaml,.yml,.toml,.ini,.cfg,.env,.html,.css,.js,.ts,Makefile,Dockerfile,.gitignore,.gitattributes,.mk,.conf,.sh,.bash,.zsh,.dockerfile
# blacklist = *.mono,monofile.config
# verbose = False

Keys

  • project_file — Output archive file name/path relative to project root.
  • extension_whitelist — Commaseparated list of allowed file name endings. A file is included if filename.endswith(any_whitelist_item). This covers both extensions (e.g. .py) and exact names (e.g. Makefile).
  • blacklist — Commaseparated list of fnmatch glob patterns to exclude (matched against the relative path using POSIX / separators).
  • verbose — If true, print include/exclude decisions while packing.

Tip: keep the whitelist tight; anything not matching is skipped unless the whitelist is empty (in which case everything is considered).


Archive format (v1)

All data is UTF8 text. The file begins with:

MONOFILE v1
# Root: <basename-of-project-root>

Directories:

----- DIR <path/to/dir> -----
----- END DIR -----

Files:

----- FILE <path/to/file> -----
EncodingUsed: <python-codec-name>   # currently "utf-8"
----- BEGIN CONTENT -----
<raw file contents>
----- END CONTENT -----
----- END FILE -----

The packer escapes any line that would collide with a marker so that the output stays unambiguous. The unpacker reconstructs directories and writes files using the declared encoding.


Safety

  • Path traversal is blocked: unpack uses a safe join to ensure paths stay under the configured root.
  • Existing files are overwritten during unpack; commit or back up before restoring if you have local changes.

Limitations (0.1.0)

  • UTF8 only. Other encodings arent attempted yet.
  • Binaries (or undecodable files) are skipped with a warning.

Python API (minimal)

from monofile import MonoConfig, Packer, Unpacker

cfg = MonoConfig.load(project_root_path)
Packer(cfg).pack()    # -> Path to created archive
Unpacker(cfg).unpack()