Obfuscate file and folder names without tampering their content. Fash recursively hashes names using a configurable algorithm, stores an encrypted mapping so you can restore them later, and leaves file contents completely untouched.
You have a directory of sensitive documents, project files, or media and you want to share or store them without revealing the original naming structure. Fash turns every file and folder name into a hash digest while preserving the directory tree and all file contents.
npm install -g @udlearn/fashRequires Node.js >= 22.
# Navigate to the directory you want to obfuscate
cd my-project
# Initialize fash (creates a .fash/ config directory)
fash init
# Hash all file and folder names (you will be prompted for a secret)
fash commit
# Restore original names when needed
fash undoInitialize fash in the current directory. Creates a .fash/ directory with default configuration.
fash init
fash init --algorithm sha1 --exclude "*.log" "node_modules"| Option | Description | Default |
|---|---|---|
-a, --algorithm <alg> |
Hash algorithm (md5, sha1, sha256) |
sha256 |
-e, --exclude <patterns...> |
Glob patterns to skip | none |
View or update configuration. Run without options to print current settings.
fash config
fash config --algorithm md5
fash config --exclude "*.log" "*.tmp" "dist"Hash all file and folder names and save an AES-256-CBC encrypted mapping. You will be prompted for a secret password -- this is required to decrypt the mapping later.
fash commit
fash commit --force # overwrite an existing mappingInspect the current mapping (requires your secret to decrypt).
fash show # show all items
fash show --files # files only
fash show --directories # directories only
fash show --config # print configurationRestore all original file and folder names from the encrypted mapping.
fash undoinitcreates a.fash/directory withconfig.jsonand an emptylog.jsonl.commitwalks the directory tree, computes a hash for every file and folder name, builds a full mapping, encrypts it with your secret (AES-256-CBC), saves it asmap.encrypted, then renames everything on disk.undodecrypts the mapping and renames everything back to the original names, working from the deepest paths upward.
The .fash/ directory contains:
| File | Purpose |
|---|---|
config.json |
Algorithm and exclude patterns |
log.jsonl |
Append-only action log (JSON Lines) |
map.encrypted |
Encrypted original-to-hashed name mapping |
Tip: Add
.fash/to your.gitignore-- the encrypted mapping and log are local state.
- Mappings are encrypted with AES-256-CBC using a key derived from your secret.
- Hash names use the full digest length, making the original names unguessable.
- The secret is never stored on disk. If you lose it, the mapping cannot be decrypted.
- Exclude patterns let you skip files that should remain untouched.
MIT