Skip to content

Configuration

purgeit looks for a configuration file via cosmiconfig. It searches upward from the current working directory for any of these files:

  • package.json (under a "purgeit" key)
  • purgeit.config.js, .mjs, .cjs
  • purgeit.config.ts, .mts, .cts
  • purgeit.config.json
  • .purgeitrc, .purgeitrc.json

Use --config <path> to specify an explicit file, or --no-config to skip config loading entirely.

export default {
extends: 'merge', // 'merge' (default) or 'replace'
skipDirs: ['tmp', '_tmp_clone'],
alwaysSafeRemove: ['coverage'],
gated: [
{ name: 'generated', when: { file: 'codegen.json' } },
],
targets: {
frontend: ['node_modules', '.next', 'dist'],
},
};
  • 'merge' (default): layer your config on top of the built-in ruleset.
  • 'replace': start from an empty ruleset and define everything yourself.

Array of directory names that are always safe to delete wherever they appear.

Array of directory names to remove from the built-in alwaysSafe list.

Array of rules that are only deletable when a sibling condition is met. Each rule has a name and either:

  • a declarative when condition, or
  • a function gate.
{
gated: [
{ name: 'build', when: { file: 'package.json' } },
{ name: 'custom', when: [{ file: 'Makefile' }, { glob: '*.mk' }] },
{ name: 'custom-code', gate: (ctx) => ctx.siblingFile('README.md') },
],
}

Declarative conditions:

ConditionMeaning
{ file: 'X' }X exists in the same parent directory
{ glob: 'X' }A sibling entry matches the glob
{ grep: { file: 'X', pattern: 'Y' } }X exists and its contents match Y

Array of gated rule names to remove from the built-in list.

Array of directory names that purgeit should not descend into during scanning.

Array of directory names to treat as VCS-like metadata (never descended into).

Named groups of rule names. You can then use --targets <group-name> on the CLI to restrict matching to that group.

{
targets: {
frontend: ['node_modules', '.next', 'dist'],
},
}
Terminal window
purgeit --targets frontend

Use extends: 'replace' when you want full control and do not want any built-in defaults:

export default {
extends: 'replace',
alwaysSafe: ['node_modules', 'dist'],
skipDirs: ['.git'],
};

If a built-in always-safe rule does not match your workflow, remove it instead of adding it:

export default {
alwaysSafeRemove: ['.nyc_output'],
};

Remove a gated rule entirely:

export default {
gatedRemove: ['Pods'],
};

Custom rules are useful for project-specific generated directories. For example, a generated/ directory that should only be deleted when a codegen.json manifest is present:

export default {
gated: [
{ name: 'generated', when: { file: 'codegen.json' } },
],
};

Use multiple OR conditions:

export default {
gated: [
{
name: 'build',
when: [{ file: 'Makefile' }, { glob: '*.cmake' }],
},
],
};

Use a function gate for logic that declarative conditions cannot express:

export default {
gated: [
{
name: 'scratch',
gate: (ctx) => ctx.siblingFile('README.md') && !ctx.siblingFile('keep-scratch'),
},
],
};

skipDirs prevents purgeit from descending into directories. This is useful for large, non-project folders inside your scan root:

export default {
skipDirs: ['backups', 'archives', 'node_modules'],
};

Define named groups of rules so you can run focused cleanups from the CLI:

export default {
targets: {
frontend: ['node_modules', '.next', 'dist'],
mobile: ['Pods', 'build', '.gradle'],
python: ['__pycache__', '.venv', '.tox'],
},
};
Terminal window
purgeit --targets frontend
purgeit --targets mobile,python

Target groups can also reference other target groups indirectly by listing their member names.

.js/.ts/.mjs/.cjs config files are executed as code (the same trust model as ESLint or Jest configs). Only run purgeit in directories where you trust the config files that cosmiconfig might discover during its upward search.