Skip to content

Repository files navigation

oxfmt-quick

npm version npm downloads coverage unpacked size types included license

CI Conventional Commits Code Style: oxfmt Linted with oxlint

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

Install

# pnpm
pnpm add -D oxfmt oxfmt-quick
# npm
npm install -D oxfmt oxfmt-quick

oxfmt is a peer dependency, so you choose the version.

Usage

# pnpm
pnpm exec oxfmt-quick

# npx
npx oxfmt-quick

Pre-Commit Hook

With husky:

pnpm add -D husky && pnpm exec husky init

In .husky/pre-commit:

pnpm exec oxfmt-quick --staged

Or with simple-git-hooks, in package.json:

"simple-git-hooks": {
  "pre-commit": "npx oxfmt-quick --staged"
}

A non-zero exit aborts the commit, so an unformatted tree cannot land.

CLI Flags

--staged

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.

--since <rev>

Compare against a specific revision - a commit hash, tag or ref - instead of the merge-base. For example oxfmt-quick --since HEAD~5.

--branch <name>

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.

--no-restage

Use with --staged to format without re-staging. You then stage the formatting yourself.

--check

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.

--bail

Exit non-zero if any file needed formatting, even though it was formatted. Use it to stop a commit that was not already clean.

--config <path>

Path to an oxfmt config file, passed through as oxfmt --config.

--verbose

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.

Partially staged files

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).

Configuration and Ignore Files

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.

API

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.

Notes

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.

What it accesses

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.

Changelog

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.

Licence

MIT - Powered by Soroush.tech

About

pretty-quick for oxfmt: format your staged files on pre-commit, at Rust speed.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages