Skip to content

.dotf File Format

The .dotf format is a structured text format designed for machine config snapshots. It's human-readable, git-diffable, and parseable by @dotformat/core. The format spec and parser/serializer API live in the core repo. This page covers usage from the CLI perspective.

Format Overview

A .dotf file is a collection of sections, each identified by a name in square brackets. Sections can contain three types of data:

  1. Pairs — key-value metadata
  2. Items — tabular data (lists with columns)
  3. Content — free-form text blocks

Syntax

Section Header

[section.name]

Section names use dot notation for hierarchy: ai.claude.settings, apps.brew.formulae, shell.zshrc.

Key-Value Pairs

[meta]
host = MacBook-Pro
os = Darwin arm64
date = 2026-04-07

Pairs appear immediately after the section header, one per line, in key = value format.

Items (Lists)

[apps.brew.formulae]
bat
eza
fd
fzf

Any line that isn't a section header, key-value pair, or multiline marker is treated as an item. For tabular data with columns, use the pipe | separator:

[ssh.hosts]
github.com | [REDACTED] | [REDACTED]
gitlab.com | [REDACTED] | [REDACTED]

Content Blocks

[shell.zshrc]
export PATH="$HOME/bin:$PATH"
source "$HOME/.oh-my-zsh/oh-my-zsh.sh"

plugins=(git zsh-autosuggestions zsh-syntax-highlighting)

Content is free-form text that follows the section header (or pairs/items if present). It preserves whitespace and newlines.

Example .dotf File

[meta]
host = MacBook-Pro
os = Darwin arm64
date = 2026-04-07

[ai.claude.settings]
enabledPlugins = computer-use
permissions.allow = Edit,Write

[ai.claude.skills]
superskill.md
web-dev.md

[ai.ollama.models]
llama3.2:latest | 2.0 GB | 2 days ago
codellama:7b | 3.8 GB | 5 days ago

[shell.zshrc]
<<<
export PATH="$HOME/bin:$PATH"
source "$HOME/.oh-my-zsh/oh-my-zsh.sh"
>>>

[terminal.p10k]
exists = true
lines = 1247

[apps.brew.formulae]
bat
eza
fd
fzf
git
ripgrep

@dotformat/core Library

The .dotf format is parsed and generated by @dotformat/core, a separate package. The CLI uses these functions:

parse(text: string): DotfDocument

Parses .dotf text into a structured document:

typescript
import { parse } from "@dotformat/core";

const doc = parse(dotfContent);
// doc.sections["meta"].pairs.host → "MacBook-Pro"
// doc.sections["shell.zshrc"].content → "export PATH=..."
// doc.sections["apps.brew.formulae"].items → [{ raw: "bat", columns: ["bat"] }, ...]

stringify(doc: DotfDocument): string

Converts a structured document back to .dotf text:

typescript
import { stringify } from "@dotformat/core";

const output = stringify(doc);
// → formatted .dotf text

compare(left: DotfDocument, right: DotfDocument): DotfDiff

Computes a structured diff between two documents:

typescript
import { compare } from "@dotformat/core";

const diff = compare(docA, docB);
// Returns sections that were added, removed, or modified

formatDiff(diff: DotfDiff, options): string

Formats a diff for human reading:

typescript
import { formatDiff } from "@dotformat/core";

const output = formatDiff(diff, {
  leftLabel: "home-mac",
  rightLabel: "work-mac",
  color: true,
});

DotfSection Type

typescript
interface DotfSection {
  name: string;                               // Section identifier
  pairs: Record<string, string>;              // Key-value pairs
  items: { raw: string; columns: string[] }[]; // List/tabular items
  content: string | null;                      // Free-form text content
}

interface DotfDocument {
  sections: Record<string, DotfSection>;
}

Section Types in Practice

Section PatternData TypeExample
metapairshost, os, date
ai.claude.settingspairsJSON field extractions
ai.claude.skillsitemsDirectory listing
ai.ollama.modelsitems (tabular)Name, size, modified columns
ssh.hostsitems (tabular)Host, hostname, identity columns
shell.zshrccontentFull file text
git.configcontentFull file text
terminal.p10kpairsexists, lines (metadata-only)
apps.raycastpairsinstalled status
apps.brew.formulaeitemsPackage list

Slim Mode

With dotfiles collect --slim, content sections are truncated to 10 lines:

[shell.zshrc]
export PATH="$HOME/bin:$PATH"
source "$HOME/.oh-my-zsh/oh-my-zsh.sh"
# ... (first 10 lines only)
... (47 more lines)

This reduces file size by ~65% — useful for feeding to AI tools where full config content isn't needed but structure and key settings are.

Naming Convention

Report files follow the pattern:

<hostname>-YYYYMMDDHHMMSS.dotf

Examples:

  • MacBook-Pro-20260407143022.dotf
  • work-linux-20260401080000.dotf

The timestamp prevents overwrites and enables chronological sorting.