Documentation menu

Guides

Bounded source formatting

Experimental: flog format formats complete JavaScript and TypeScript files that Stick can parse and print safely. Syntax coverage and layout rules may change; unsupported or unsafe files are refused without edits. Command status is tracked in experimental-commands.json at the repository root.

File, directory, and workspace selection#

Pass one or more explicit files or directories, or select exactly one declared workspace:

flog format src/config.js scripts/check.ts
flog format src packages/shared
flog format --check --workspace @example/shared

Explicit files must be regular files no larger than 8 MiB; shell-expanded paths remain explicit files. Directories are scanned recursively in lexical order within the project root. Symlinks are not followed: an unexcluded symlink, overlapping or hard-linked input, traversal error, empty selection, or path outside the root causes a refusal.

--workspace uses Flog's name, path, owned-file, or glob selectors but must resolve to exactly one declared workspace. It cannot be repeated or combined with path arguments; only the selected package directory is scanned.

Recursive selection always excludes dependency, VCS, vendored, generated, and common build-output directory names: .git, .hg, .svn, .rp, node_modules, vendor, generated, dist, build, coverage, out, target, .next, .nuxt, and .svelte-kit. Explicit file arguments are not affected by recursive exclusions.

The filename selects JavaScript or TypeScript syntax:

  • .js, .mjs, and .jsx select JavaScript ESM;
  • .ts, .mts, .tsx, .d.ts, and .d.mts select TypeScript ESM;
  • .cjs, .cts, and .d.cts are explicitly CommonJS-only and are refused.

These extensions select ESM grammar, not JSX support. Ordinary .js needs no package.json; a nearest manifest declaring "type": "commonjs" refuses ambiguous extensions (.js, .jsx, .ts, .tsx, .d.ts) but not explicit ESM extensions. An unreadable or invalid nearest manifest also causes refusal. Contextual top-level await requires independent ESM proof, such as a static import/export or import.meta, to avoid reinterpreting script syntax.

Canonical style#

There are no style options. Flog uses two-space indentation, semicolons for supported statements, safe double-quoted strings, spaces around supported operators and delimiters, LF structural lines, and one final newline. Literal, regular-expression, template raw-chunk, and comment bytes are preserved where changing them could alter meaning. Safe string-quote conversion is limited to equivalent spelling; other escapes are retained.

Where the printer owns width, comment-free lists and other layouts target 80 columns using syntax-safe breaks and trailing commas on multiline lists. Short forms stay compact when the complete rendered line fits; source line breaks alone do not choose a different layout. Flog does not reflow arbitrary expressions, strings, or comments to meet the target. It preserves ownership-sensitive section breaks and separates top-level module declarations from ordinary statements. If a safe canonical layout cannot be proven, it refuses the file instead of partly formatting it.

Supported syntax and current limits#

Stick formats complete ESM JavaScript or TypeScript files only when every construct fits its bounded grammar. That grammar covers selected ESM module, declaration, statement, expression, literal, comment, JSDoc, and TypeScript type forms, but coverage is intentionally incomplete within each category. Stick preserves literal spelling, comment ownership, and syntax semantics when printing. The reliable way to test a file against the current grammar is to run flog format --check.

Notable current limits include JSX syntax (even in .jsx or .tsx files), CommonJS, dynamic import expressions, many class bodies and advanced TypeScript declarations, and other lexical or grammar forms outside Stick's bounded coverage. These examples are not exhaustive: unsupported or ambiguous syntax and unsafe comment or module ownership are refused without edits. flog format is not a general JS/TS formatter or a Prettier-compatible printer. ESLint Stylistic guides style where the bounded printer owns a choice; it does not extend the supported grammar. Existing formatters should remain in place for files Flog cannot safely handle.

Project configuration#

No configuration is required. Flog discovers one optional committed flog.json at the project, workspace, or standalone package root, not a nested file below that root. Without package metadata, the nearest ancestor flog.json defines the standalone project root.

Canonical style has no options. The optional format.exclude array adds project-root-relative slash-separated path globs to recursive selection:

{
  "format": {
    "exclude": ["fixtures/**", "packages/legacy/*.js"]
  }
}

** matches zero or more path segments. A pattern that matches a directory prunes that tree; otherwise matching files are omitted. Patterns must be non-empty, unique, remain within the project root, and use forward slashes.

The file must be regular JSON no larger than 1 MiB, with one object, unique keys, and no unknown fields. Reserved lint and check sections are rejected.

Safety and refusals#

A file is eligible only when Stick reports no lexical, malformed, unsupported, or context diagnostic. The complete output must reparse in the same language and ESM context and print idempotently. Comments and syntax ownership are verified by Stick's reference printer.

All requested files are planned before any write. If one is refused, none are modified. Before replacement, Flog verifies that each file is still the same regular file with identical contents and permissions. Changed files are staged beside their targets and replaced transactionally; an ordinary multi-file replacement failure rolls back earlier replacements. Original permission bits are preserved. Rollback restores a target only while it still has the exact identity, permissions, and bytes staged by this formatter. If another process edits an already formatted target, Flog preserves those current bytes, reports the conflict, and retains the original backup path for manual recovery.

Successful formatting prints one line per selected file. Explicit files retain argument order; recursive results use deterministic lexical traversal order:

formatted src/config.js
unchanged scripts/check.ts

Check mode and exit status#

--check performs complete discovery and parse/print verification but never stages or modifies files. It prints every safely planned file whose bytes differ:

src/config.js: needs formatting

When drift is the only finding, standard error also receives the usual concise Flog diagnostic (flog: error: 1 file needs formatting, or the plural count). Every refusal discovered while scanning or planning is reported as well. Refusal, incomplete-discovery, and operational failures take exit precedence over formatting drift, while the drift lines remain available on standard output.

Exit statuses are:

Status Meaning
0 every file is already formatted, or formatting succeeded
1 a file was refused or an operational error occurred
2 command usage was invalid
3 --check found one or more files needing formatting

Diagnostics identify the refused path and, for Stick diagnostics, the first one-based line and UTF-16 column. Refusal and check modes never emit partial formatted source.