Tatuagem (Portuguese for βtattooβ) v.0.1.4 is done.
This was a fun collaboration between me and @DerekDickerson. The idea is stupid simple: you have a directory of source files, and you want to stamp a text banner β βCONFIDENTIALβ, βDRAFTβ, βCOPYRIGHT 2026 ACME CORPβ, whatever β across every single file, recursively. A tattoo for your code.
You can find the project on PyPI at https://pypi.org/project/tatuagem/ and on GitHub.
Why This Exists
I kept running into the same annoyance: corporate projects that require license headers, confidentiality banners, or copyright notices at the top of every source file. You can write a bash one-liner with find and sed, sure. But then you need to handle different file types (some use # comments, some use //, some use /* */), you need to avoid double-stamping files that already have the banner, and you need to not accidentally corrupt binary files. It is the kind of task that feels like it should take five minutes and actually takes an hour of edge-case whacking.
Tatuagem handles all of this. One command.
How It Works
Under the hood, Tatuagem walks your directory tree with os.walk, filters files by a glob pattern (default *.*), reads each file, prepends the text banner with a configurable βbacksplashβ decoration (the line art surrounding the text), and writes it back. The text rendering uses Pillowβs ImageFont and ImageDraw to rasterize the banner text into ASCII art β so your stamp is not just plain text, it is a rendered block of Unicode characters that looks intentional and professional.
The font rendering pipeline is the interesting bit. Tatuagem loads a TrueType font (bundled or user-specified), renders the text string into a Pillow Image, then converts each pixel into a Unicode block character based on brightness. The result is a text-art banner that scales with font size and works in any monospace environment β terminals, source files, log outputs.
Usage
pip install tatuagem
usage: tatuagem [-h] [--text TEXT] [--backsplash BACKSPLASH] [--font FONT]
[--pattern PATTERN] [--margin MARGIN] [--recurse-path RECURSE_PATH]
[--file FILE] [--overwrite]
Tatuagem
options:
-h, --help show this help message and exit
--text TEXT Set the text
--backsplash BACKSPLASH
Choose backsplash
--font FONT Set the font
--pattern PATTERN Set the pattern for backsplash
--margin MARGIN Margin top and bottom for text
--recurse-path RECURSE_PATH
Path to recurse and apply tattoo
--file FILE, -f FILE Read text from file
--overwrite Overwrite existing tattoos in files
To use it, you can simply run it with the text you want to βtattooβ onto your files:
tatuagem --text "CONFIDENTIAL" --recurse-path ./src
Want a different font? Different decoration style? Read the text from a file instead of the command line?
tatuagem --text "DRAFT v2.0" --font ./myfont.ttf --backsplash 2 --recurse-path ./docs
tatuagem --file ./license_header.txt --pattern "*.py" --recurse-path ./src --overwrite
The --overwrite flag is key: it detects existing tatuagem stamps and replaces them rather than stacking duplicates. Without it, running the command twice would give you two banners. With it, the old tattoo gets cleanly replaced.
Design Choices
-
Pillow for text rendering: I could have used a simpler ASCII art library, but Pillow gives us TrueType font support, which means the banner actually looks good. The pixel-to-Unicode conversion uses the block characters
ββββββββ(among others) to approximate grayscale values. The result is surprisingly legible even at small font sizes. -
Recursive by default, filterable by pattern: The
--patternflag lets you target only.pyfiles, only.jsfiles, or whatever subset you care about. No accidental tattooing of your.pngfiles. -
File-based text input: The
--fileflag reads the stamp text from a file, which is useful for multi-line license headers that would be awkward to pass as a CLI argument.
Derek handled the backsplash decoration system β the border art that frames the text β while I focused on the recursive file walking and the overwrite detection. Good division of labor for a weekend project.
Built in Python. Published on PyPI. Does one thing. Does it well.
βββββββββ ββββββββββ
βββββββ
β
βββββ ββ β βββββββββββββ
ββββββββββββ
β
β
βββ ββ ββ βββββ
β
βββββββββββ
ββββββββββ
ββββββββ βββ βββ ββββββββββββββββββ
ββββββββββββ
βββββββ
ββ βββ βββ βββ
βββββββ
ββββββββββ
βββββββββββββ βββββββ ββββ βββββββ βββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββ
βββββ ββββββββββββββββββββββββββββββ ββββββ
βββββββββ βββββββββββββββββ βββββββββ
βββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββ
βββββββββ ββββββββββ βββββββββ
ββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββ
ββββββββββββββ
ββββββββββ β ββββββ
ββ ββββββ
ββββ
βββββββ
βββ β ββββββ
β ββββ
βββββ
ββ
βββββββ
β
ββββββββββ
βββββββ
β
βββ
βββββββββββββββββββ
ββ
ββββββββββββββββββ
ββββββββββββββββββββββ
βββββββ βββ
βββββ
ββ βββββββ
ββββββββββββ
β βββββ ββ
βββββββββββ
ββββββββββββββββββββββ
βββ
βββββββββββββββββββββ
ββββββββββββββββββββββ ββββ βββββββββββββββββββββ
βββββββββββββββββββ ββββ βββββββββββββββββββ
βββββββββββββββββββ ββββββ βββββββββββββββββββ
βββββββββββββββββββββ ββββββ ββββββββββββββββββββ
βββββββββββββββββββββ ββββββ βββββββββββββββββββββ
ββββββββββββββββββββββ ββββββ ββββββββββββββββββββββ
ββββββββββββββββββββββ ββββββ ββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββ ββββββββββββββββββββββββββββββββββββ βββββββββ
βββββββββ
β
βββββββββββββββββββββββββββββββββββ
βββββββββ
βββββββββ β
βββββββββββββββββββββββββββββββββββ βββββββββ
ββββββββ
β ββββββββββββββββββββββββββββββββ βββββββββ