Get oxfmt Quick
Runs oxfmt on your changed files.
Formatting a whole repository every time is wasteful, and a --check gate that only tells
you off is worse. oxfmt-quick formats what you actually touched and gets out of the way.
By default it takes everything changed since the merge-base with your branch, plus
untracked files. Add --staged and it takes the index instead, re-staging what it
formats - that is the pre-commit mode, and the same split pretty-quick uses.
Supported source control managers:
- Git
# pnpm
pnpm add -D oxfmt oxfmt-quick# npm
npm install -D oxfmt oxfmt-quickoxfmt is a peer dependency, so you choose the version.
# pnpm
pnpm exec oxfmt-quick
# npx
npx oxfmt-quickWith husky:
pnpm add -D husky && pnpm exec husky initIn .husky/pre-commit:
pnpm exec oxfmt-quick --stagedOr with simple-git-hooks, in
package.json:
A non-zero exit aborts the commit, so an unformatted tree cannot land.
Pre-commit mode. Only staged files are formatted, and they are re-staged afterwards. Anything unstaged is not going into the commit, so formatting it would be work the commit never uses.
Partially staged files are formatted but not re-staged, and oxfmt-quick exits with a
non-zero code. See Partially staged files.
Compare against a specific revision - a commit hash, tag or ref - instead of the
merge-base. For example oxfmt-quick --since HEAD~5.
The branch to find the merge-base against, in the default mode. Defaults to main.
The merge-base is used rather than the branch tip, so a feature branch that has fallen
behind does not drag in every file that changed on main in the meantime.
Use with --staged to format without re-staging. You then stage the formatting yourself.
Report which files are not formatted without writing anything, and exit non-zero if any are. Useful in CI to verify that the changed files on a branch were formatted.
Exit non-zero if any file needed formatting, even though it was formatted. Use it to stop a commit that was not already clean.
Path to an oxfmt config file, passed through as oxfmt --config.
Print the name of every file considered, not just the ones that changed. Useful when oxfmt errors and you cannot tell which file caused it.
If a file is staged and then edited again, only the staged content is going into the
commit. oxfmt-quick formats the file on disk but deliberately does not re-stage it -
git add would sweep the unstaged edits in and silently widen your commit. The file is
reported and the run exits non-zero, so you can amend your staging to include the
formatting fix.
This is the one case where doing less is safer, and it is a real bug in at least one comparable tool (biomejs/biome#3608).
oxfmt-quick resolves nothing itself. oxfmt already reads
.oxfmtrc, .gitignore, .prettierignore
and .editorconfig, searching up the file system as it goes - so there is no second
implementation here to drift out of step with it.
For the same reason there is no extension filter: oxfmt skips files it cannot format, so
the raw git diff list is handed straight over.
Gitignored files can never appear, because git diff reports only tracked files.
import { oxfmtQuick } from 'oxfmt-quick'
const { success, errors } = oxfmtQuick(process.cwd(), {
staged: true,
onWriteFile: (file) => console.log(`formatted ${file}`),
})errors contains any of BAIL_ON_WRITE, CHECK_FAILED, FORMAT_FAILED,
PARTIALLY_STAGED_FILE or STAGE_FAILED. Every callback is optional - the CLI is a thin
reporting layer over this one function.
Changed files are collected with git diff -z and split on NUL, so paths containing
spaces, non-ASCII characters or newlines survive intact. git add is issued in batches of
100, so a large changeset cannot exceed the command-line length limit.
oxfmt is invoked by resolving its own bin script and running it with the current node,
rather than looking oxfmt up on PATH - on Windows that entry is a .CMD shim which
cannot be spawned without a shell, and a shell would reintroduce the quoting problems that
passing an argv array exists to avoid.
Supply-chain scanners flag the Node built-ins a package imports. There are two, each used in one file for one purpose:
| Built-in | Where | What for |
|---|---|---|
node:child_process |
src/run.ts |
running git and oxfmt |
node:module |
src/resolveOxfmt.ts |
createRequire, to find oxfmt's bin script |
Worth being precise about, since scanners often label the first one "shell access":
no shell is ever used. spawnSync is called with an argument array and without
shell: true, so paths containing spaces, quotes or glob characters cannot be
reinterpreted. There is no eval, no dynamic require of user input, no network access,
and nothing is read from the environment.
No filesystem API is used at all: every question about the repository - including where its root is - goes to git, which knows the answer better than a directory walk does.
The package writes no files itself - oxfmt does that - and its only writes to your
repository are the git add calls that re-stage what oxfmt formatted.
Every released version has its own notes in
release-notes/ -
one file per version, and the publish workflow refuses to ship a version without them.
MIT - Powered by Soroush.tech