# Usage: curl -sSL https://dom.vin/fold | bash -s # is the directory where the file should land. set -euo pipefail [ -z "${1:-}" ] && { echo "install requires a path: curl -sSL https://dom.vin/fold | bash -s " >&2 exit 1 } TARGET="$1" mkdir -p "$TARGET" DEST="$TARGET/skill.folded.md" cat > "$DEST" <<'PORTDOWN_B2A609CF' --- fold: true marker: 031cba at: 2026-05-01T18:54:18Z root: skill --- --- name: fold description: > Pack a directory of text files into one self-describing `.folded.md` file (`fold `), or unpack one back to a directory (`unfold `). Use when the user says fold/unfold, asks to share a folder of markdown as one artifact, asks to zip or unzip a folder of markdown into / out of a single markdown file, or pastes you a `.folded.md` file. Self-installing polyglot at dom.vin/fold. --- # fold Two commands, one job: a directory of text files ↔ one markdown file. ``` fold pack → .folded.md unfold unpack → / ``` A `.folded.md` is a plain markdown file. Open it in any editor; it carries an instruction block at the top so any agent receiving it can self-install fold and unpack it. Inside, file sections are delimited by `` markers and terminated by ``. ## When to reach for it - The user says "fold this folder" or "unfold this file." - The user wants to share a directory as a single artifact (chat, gist, email, agent context window). - A `.folded.md` arrives and the user wants to operate on it as a tree. ## How to invoke Call the scripts directly from where the skill is installed. **Fold** a directory into a single file: ``` /scripts/fold ./notes # → ./notes.folded.md (alongside the source dir) /scripts/fold ./notes -o /tmp/x.folded.md # custom output /scripts/fold ./notes -f # overwrite existing ``` **Unfold** a `.folded.md` back into a directory: ``` /scripts/unfold ./notes.folded.md # → ./notes/ (alongside the source file) /scripts/unfold ./notes.folded.md /tmp/restored # positional dest /scripts/unfold ./notes.folded.md -o /tmp/restored # flag form /scripts/unfold ./notes.folded.md -f # overwrite existing ``` `` is the directory you passed to the installer (e.g. `$CLAUDE_SKILLS_DIR/fold`). Both commands refuse to overwrite existing output by default; pass `-f` to override. ## Install ``` curl -sSL https://dom.vin/fold | bash -s ``` `` is the directory where the fold skill should land — typically your agent's skills directory + `/fold`. The installer writes `SKILL.md` and `scripts/fold` + `scripts/unfold` into that path. No side effects outside it. #!/usr/bin/env bash # fold — pack a directory of text files into one self-describing .folded.md # # Usage: # fold pack → .folded.md # fold -o pack → # fold --help this help set -euo pipefail MAX_BYTES_DEFAULT=5242880 # 5 MB — share-via-paste is the design intent usage() { cat < pack → /.folded.md fold -o pack → fold -f overwrite existing output fold --max-size override the default size cap (current default: ${MAX_BYTES_DEFAULT} bytes) fold --help this help The output file carries instructions at the top so any agent that receives it can install fold (from dom.vin/fold) and unfold it. EOF } emit_orientation() { cat <<'EOF' EOF } main() { local SRC="" OUT="" FORCE=0 MAX_BYTES="$MAX_BYTES_DEFAULT" while [ $# -gt 0 ]; do case "$1" in -o|--output) OUT="$2"; shift 2 ;; -f|--force) FORCE=1; shift ;; --max-size) MAX_BYTES="$2"; shift 2 ;; -h|--help) usage; exit 0 ;; *) [ -z "$SRC" ] && { SRC="$1"; shift; } || { echo "fold: unexpected arg: $1" >&2; exit 1; } ;; esac done [ -z "$SRC" ] && { usage >&2; exit 1; } if [ ! -d "$SRC" ]; then if [ -f "$SRC" ]; then echo "fold: $SRC is a file, not a directory. fold packs directories — to fold one file, fold its parent dir, or wrap the file in a dir first (mkdir x && mv $SRC x/ && fold x)." >&2 else echo "fold: not a directory: $SRC" >&2 fi exit 1 fi local ROOT ROOTNAME PARENT MARKER ROOT=$(cd "$SRC" && pwd) ROOTNAME=$(basename "$ROOT") PARENT=$(dirname "$ROOT") [ -z "$OUT" ] && OUT="${PARENT}/${ROOTNAME}.folded.md" if [ -e "$OUT" ] && [ "$FORCE" = "0" ]; then echo "fold: refusing to overwrite $OUT — pass -f / --force to overwrite" >&2 exit 1 fi MARKER=$(LC_ALL=C dd if=/dev/urandom bs=256 count=1 2>/dev/null | tr -dc '0-9a-f' | head -c 6) local FILES=() while IFS= read -r -d '' f; do FILES+=("${f#./}"); done < <(cd "$ROOT" && find . -type f -print0 | sort -z) [ ${#FILES[@]} -eq 0 ] && { echo "fold: no files in $SRC" >&2; exit 1; } for f in "${FILES[@]}"; do case "$f" in *\"*|*$'\n'*) echo "fold: refusing — unsafe character (quote or newline) in filename: $f. Rename the file and re-run." >&2; exit 1 ;; esac done local binary binary=$(cd "$ROOT" && printf '%s\0' "${FILES[@]}" \ | LC_ALL=C xargs -0 grep -laP '\x00' 2>/dev/null | head -n 1) || true [ -n "$binary" ] && { echo "fold: refusing — binary file: $binary. fold packs text files only." >&2; exit 1; } # Total size check — fold is designed for share-via-paste; bigger # bundles probably want a real archiver. local TOTAL=0 sz for f in "${FILES[@]}"; do sz=$(stat -c "%s" "$ROOT/$f" 2>/dev/null) \ || sz=$(stat -f "%z" "$ROOT/$f" 2>/dev/null) \ || sz=0 TOTAL=$((TOTAL + sz)) done if [ "$TOTAL" -gt "$MAX_BYTES" ]; then echo "fold: refusing — total size ${TOTAL} bytes exceeds ${MAX_BYTES} cap. Pass --max-size to override, or use a real archiver for bundles this big." >&2 exit 1 fi # Warn (don't block) on symlinks and empty dirs — they won't survive # the round-trip but we don't want to refuse for them. Name the paths # so the user can audit at a glance. local SYMS EMPTY SYMS=$(cd "$ROOT" && find . -type l 2>/dev/null | sed 's|^\./||') EMPTY=$(cd "$ROOT" && find . -type d -empty 2>/dev/null | sed 's|^\./||') if [ -n "$SYMS" ]; then echo "fold: note — symlink(s) skipped (only regular files are folded):" >&2 printf ' %s\n' $SYMS >&2 fi if [ -n "$EMPTY" ]; then echo "fold: note — empty directory/ies will not survive the round-trip:" >&2 printf ' %s\n' $EMPTY >&2 fi { emit_orientation echo "---" echo "fold: true" echo "marker: $MARKER" echo "at: $(date -u +%Y-%m-%dT%H:%M:%SZ)" echo "root: $ROOTNAME" echo "---" echo for f in "${FILES[@]}"; do local mode mode=$(stat -c "%a" "$ROOT/$f" 2>/dev/null) \ || mode=$(stat -f "%Lp" "$ROOT/$f" 2>/dev/null) \ || mode="644" echo "" cat "$ROOT/$f" [ -n "$(tail -c 1 "$ROOT/$f" 2>/dev/null)" ] && echo done echo "" } > "$OUT" local SIZE SIZE=$(wc -c < "$OUT" | tr -d ' ') echo "✓ folded ${#FILES[@]} files from $SRC → $OUT ($SIZE bytes)" >&2 } main "$@" #!/usr/bin/env bash # unfold — unpack a .folded.md file back into a directory # # Usage: # unfold unpack → / # unfold -o unpack → / # unfold --help this help set -euo pipefail MAX_BYTES_DEFAULT=5242880 # 5 MB — symmetric with fold's cap usage() { cat < unpack → // unfold unpack → / (positional) unfold -o unpack → / (flag form) unfold -f overwrite existing destination unfold --max-size override the default size cap (current default: ${MAX_BYTES_DEFAULT} bytes) unfold --help this help EOF } main() { local SRC="" OUT="" FORCE=0 MAX_BYTES="$MAX_BYTES_DEFAULT" while [ $# -gt 0 ]; do case "$1" in -o|--output) OUT="$2"; shift 2 ;; -f|--force) FORCE=1; shift ;; --max-size) MAX_BYTES="$2"; shift 2 ;; -h|--help) usage; exit 0 ;; *) if [ -z "$SRC" ]; then SRC="$1"; shift elif [ -z "$OUT" ]; then OUT="$1"; shift else echo "unfold: unexpected arg: $1" >&2; exit 1; fi ;; esac done [ -z "$SRC" ] && { usage >&2; exit 1; } [ ! -f "$SRC" ] && { echo "unfold: not a file: $SRC" >&2; exit 1; } local SRC_SIZE SRC_SIZE=$(stat -c "%s" "$SRC" 2>/dev/null) \ || SRC_SIZE=$(stat -f "%z" "$SRC" 2>/dev/null) \ || SRC_SIZE=0 if [ "$SRC_SIZE" -gt "$MAX_BYTES" ]; then echo "unfold: refusing — input ${SRC_SIZE} bytes exceeds ${MAX_BYTES} cap. Pass --max-size to override." >&2 exit 1 fi local MARKER MARKER=$(awk ' /^---$/ { f++; if (f==2) exit; next } f==1 && /^marker:[[:space:]]/ { sub(/^marker:[[:space:]]+/, ""); print; exit } ' "$SRC") [ -z "$MARKER" ] && { echo "unfold: no 'marker:' in frontmatter — not a .folded.md artifact" >&2; exit 1; } if [ -z "$OUT" ]; then local base parent base=$(basename "$SRC") parent=$(cd "$(dirname "$SRC")" && pwd) OUT="${base%.folded.md}" [ "$OUT" = "$base" ] && OUT="${base%.*}" OUT="${parent}/${OUT}" fi if [ -e "$OUT" ] && [ "$FORCE" = "0" ]; then echo "unfold: refusing to write into existing $OUT — pass -f to overwrite, or pick a different destination: unfold $SRC " >&2 exit 1 fi mkdir -p "$OUT" OUT=$(cd "$OUT" && pwd) awk -v marker="$MARKER" -v outdir="$OUT" ' BEGIN { # Match a fold @file marker: capture path, optionally a mode= attribute. file_re = "^$" end_re = "^$" } $0 ~ end_re { if (current) close(current); exit } $0 ~ file_re { if (current) close(current) # Extract path (between path=" and the closing ") path = $0 sub(/^ PORTDOWN_B2A609CF # ── post ── # GENERATED by playground/fold-publish/build.sh — do not edit. # Inlines playground/fold/scripts/unfold so the bootstrap can # extract before unfold is on disk. #!/usr/bin/env bash # unfold — unpack a .folded.md file back into a directory # # Usage: # unfold unpack → / # unfold -o unpack → / # unfold --help this help set -euo pipefail MAX_BYTES_DEFAULT=5242880 # 5 MB — symmetric with fold's cap usage() { cat < unpack → // unfold unpack → / (positional) unfold -o unpack → / (flag form) unfold -f overwrite existing destination unfold --max-size override the default size cap (current default: ${MAX_BYTES_DEFAULT} bytes) unfold --help this help EOF } main() { local SRC="" OUT="" FORCE=0 MAX_BYTES="$MAX_BYTES_DEFAULT" while [ $# -gt 0 ]; do case "$1" in -o|--output) OUT="$2"; shift 2 ;; -f|--force) FORCE=1; shift ;; --max-size) MAX_BYTES="$2"; shift 2 ;; -h|--help) usage; exit 0 ;; *) if [ -z "$SRC" ]; then SRC="$1"; shift elif [ -z "$OUT" ]; then OUT="$1"; shift else echo "unfold: unexpected arg: $1" >&2; exit 1; fi ;; esac done [ -z "$SRC" ] && { usage >&2; exit 1; } [ ! -f "$SRC" ] && { echo "unfold: not a file: $SRC" >&2; exit 1; } local SRC_SIZE SRC_SIZE=$(stat -c "%s" "$SRC" 2>/dev/null) \ || SRC_SIZE=$(stat -f "%z" "$SRC" 2>/dev/null) \ || SRC_SIZE=0 if [ "$SRC_SIZE" -gt "$MAX_BYTES" ]; then echo "unfold: refusing — input ${SRC_SIZE} bytes exceeds ${MAX_BYTES} cap. Pass --max-size to override." >&2 exit 1 fi local MARKER MARKER=$(awk ' /^---$/ { f++; if (f==2) exit; next } f==1 && /^marker:[[:space:]]/ { sub(/^marker:[[:space:]]+/, ""); print; exit } ' "$SRC") [ -z "$MARKER" ] && { echo "unfold: no 'marker:' in frontmatter — not a .folded.md artifact" >&2; exit 1; } if [ -z "$OUT" ]; then local base parent base=$(basename "$SRC") parent=$(cd "$(dirname "$SRC")" && pwd) OUT="${base%.folded.md}" [ "$OUT" = "$base" ] && OUT="${base%.*}" OUT="${parent}/${OUT}" fi if [ -e "$OUT" ] && [ "$FORCE" = "0" ]; then echo "unfold: refusing to write into existing $OUT — pass -f to overwrite, or pick a different destination: unfold $SRC " >&2 exit 1 fi mkdir -p "$OUT" OUT=$(cd "$OUT" && pwd) awk -v marker="$MARKER" -v outdir="$OUT" ' BEGIN { # Match a fold @file marker: capture path, optionally a mode= attribute. file_re = "^$" end_re = "^$" } $0 ~ end_re { if (current) close(current); exit } $0 ~ file_re { if (current) close(current) # Extract path (between path=" and the closing ") path = $0 sub(/^