Skip to main content
Don’t trust your memory — write it down.
Use this page when a demo, test, script, or extension needs predictable local files without hand-rolling path handling and serialization details. The File System utilities center on two ideas: pj(...) for portable paths and a serialization family for consistent read/write across JSON, YAML, text, JSONL, jstr, binary, and related formats.

1. Why a Unified File System Utility

Without a unified file system utility, every script and demo re-implements path joining, alias resolution, encoding handling, and serialization. The results are inconsistent: one module uses os.path.join(...) with hardcoded relative paths, another uses pathlib.Path with expanduser(), and a third hardcodes / separators that break on Windows. Serialization diverges the same way — one caller writes JSON with indent=2, another uses default=str, and a third hard-codes utf-8 encoding.
HeavenBase treats paths and serialization as paired infrastructure. pj(...) is the single path vocabulary: it expands ~, resolves environment variables, normalizes separators, optionally returns absolute paths, and resolves caller-provided aliases. The serialization family uses config-driven defaults (CM_HVNB at heavenbase.serialize.encoding and heavenbase.serialize.indent) so every caller gets consistent output without repeating those parameters.
Both halves matter equally: you build a path with pj(...), then read or write through the matching serialization helper without re-specifying encoding, indentation, or platform details.

2. Two Core Ideas

File System utilities split cleanly into path vocabulary and serialization I/O. Everything else on this page — touching folders, listing files, copying artifacts, folder diagrams — supports those two flows.

2.1. pj(...) — Portable Paths

pj(...) is the canonical path join helper. It joins path parts, expands ~ and environment variables, normalizes separators, optionally returns an absolute path, and can resolve caller-provided aliases. Think of it as a small path vocabulary. . means the current working location, ~ expands to the user home, environment variables expand through the operating system, and aliases such as % or & can point to a package data folder or resource folder when the caller or config manager provides that alias map.
Utility pj(...) handles normal paths and caller aliases. CM_HVNB.pj(...) handles HeavenBase package aliases: %/ for package-local data and &/ for package resources.

2.2. Serialization Family — Config-Driven I/O

The serialization helpers wrap common read/write for the same reason configuration wraps hyperparameters: callers should not pass encoding, indentation, and platform path details through every function. Each format exposes the same naming pattern: Text encodings default to heavenbase.serialize.encoding, which is utf-8 in the default config. JSON and YAML indentation default to heavenbase.serialize.indent, which is 4. Missing files return empty defaults ("", {}, [], or b"") unless you pass strict=True. This shows the benefit of the config-driven approach: you can change the default encoding or indentation without changing every caller. JSON helpers use HbJsonEncoder and HbJsonDecoder, which preserve common HeavenBase values such as datetimes, decimals, tuples, sets, and callable references — so artifacts round-trip without ad-hoc default=str handlers.

3. Build a Path

Use pj(...) for ordinary local paths:
Pass aliases when the first path segment is a project-specific shortcut:
Use package aliases through the config manager:

4. Prepare Files and Folders

Use touch_dir(...) and touch_file(...) before writing artifacts. Both create missing parents and return an absolute path.
Use clear=True only when the folder or file should start empty:

5. Read and Write Data

Serialization is the second pillar of this page. Pick a format, call the matching helper, and let CM_HVNB supply encoding and indentation defaults. Combine with pj(...) and touch_dir(...) for a complete artifact workflow.

5.1. JSON

Use JSON for structured machine-readable artifacts — configs, run metadata, workspace snapshots, and interchange with other tools.
Pass sort_keys=True when deterministic key order matters (for example, before hashing). Pass compact=True or indent=None for one-line output.

5.2. YAML

Use YAML for human-editable structured files such as config templates and small manifests.
YAML shares the same indentation default as JSON through heavenbase.serialize.indent.

5.3. Text

Use text helpers for logs, Markdown notes, plain reports, and any human-readable line-oriented output.
load_txt returns "" for a missing file unless strict=True. append_txt adds a trailing newline after each write.

5.4. JSONL

Use JSONL when a workflow appends one event or record at a time — run logs, streaming exports, and incremental audit trails.
Prefer append_jsonl for incremental writes and dump_jsonl when you have the full iterable in memory. Use iter_jsonl to stream large files without loading every line at once.

5.5. jstr — Python-Facing Text

jstr means “JSON when the top-level value is a container, otherwise string.” Use dumps_jstr, loads_jstr, dump_jstr, load_jstr, and save_jstr at text boundaries such as Tool results, memstate rows, and MCP payloads where structured values should stay machine-readable while scalars and other values stay human-readable through str(...). Rules:
  • Top-level dict or list values (including nested containers) serialize as compact JSON through the same encoder as dumps_json.
  • All other values, including int, float, bool, None, tuples, sets, and custom objects, use str(obj).
  • loads_jstr parses text that looks like a JSON object or array; invalid JSON in that shape, and all other text, is returned unchanged as a string.
Toolkit and MCP boundaries use this format by default. Each Tool keeps serializer=None and resolves to the shared jstr_serializer Capsule at execution time, so toolkit.run_to_str(...) and FastMCP serving route successful tool outputs through dumps_jstr. Local Python callers can still use toolkit.run(...) for raw objects.

5.6. Binary

Use binary helpers for raw byte payloads — model weights, compressed blobs, image bytes, and other non-text artifacts.
load_bin returns b"" for a missing file unless strict=True.

5.7. Hex and Base64

Use hex and Base64 helpers when byte payloads need a text-safe representation in files or logs.
dump_hex and dump_b64 decode a hex or Base64 string and write the resulting bytes. load_hex and load_b64 read a binary file and return a hex or Base64 text representation. Use dumps_b64 / loads_b64 for in-memory encoding without touching the filesystem.

5.8. Pickle

Use pickle only for trusted local artifacts produced by your own environment. Pickle can execute arbitrary code during load and must never cross a trust boundary.
load_pkl(...) reads Python pickle data. Use pickle only for trusted local artifacts produced by your own environment.

6. List, Copy, and Delete Artifacts

list_files(...) reads direct children. enum_files(...) walks recursively. Both return stable, case-insensitive order.
Copy helpers use explicit conflict modes. Files support replace, skip, and strict; directories also support merge.

7. Show a Folder Diagram

Use folder_diagram(...) for compact diagnostics in logs, reports, and docs snippets.
delete_dir(...) and delete_path(...) remove local data. Keep demo cleanup targets under known temporary folders such as demos/.temp/.

Further Exploration

Related resources:
  • Configuration - config-driven defaults used by serialization helpers.
  • Hash - deterministic file-safe identifiers and fingerprints.
  • Miscs - command execution around local artifacts.