- Python 100%
| .idea | ||
| src/monofile | ||
| pyproject.toml | ||
| README.md | ||
monofile — Pack/Unpack a project into one human‑readable file (.mono)
monofile is a tiny CLI that bundles a directory tree into a single UTF‑8 text file with the .mono extension and reconstructs the project back on disk later. It’s designed for pasting, diffing, code review, and moving small projects around without binary blobs or tarballs.
The .mono format is intentionally simple: it’s just text with clear markers for directories and files plus each file’s 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→ createproject.monofrom a directorymonofile unpack→ restore files from the configured.monomonofile init→ generate a startermonofile.config- Sensible defaults:
- Whitelist of common text extensions (e.g.
.py,.md,.toml,.yml,.json,…plusMakefile,Dockerfile, etc.) - Blacklist excludes
*.monoandmonofile.configby default
- Whitelist of common text extensions (e.g.
- Skips obvious binary files (null bytes or non‑UTF‑8 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 config’sproject_file(default:project.mono) and written next tomonofile.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 INI‑like 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— Comma‑separated list of allowed file name endings. A file is included iffilename.endswith(any_whitelist_item). This covers both extensions (e.g..py) and exact names (e.g.Makefile).blacklist— Comma‑separated list offnmatchglob 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 UTF‑8 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)
- UTF‑8 only. Other encodings aren’t 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()