rootless-config
v1.9.0
Published
Store project config files outside the project root, auto-deploy them where tools expect them.
Maintainers
Readme
rootless-config
Keep your project root clean. Store all config files in
.root/, generate them where tools expect them.
Problem
Every modern JS project accumulates a pile of config files at the root:
vite.config.js
eslint.config.js
prettier.config.js
postcss.config.js
tailwind.config.js
.envThey aren't your code. They clutter navigation, git diffs, and onboarding.
Solution
Move them into .root/. rootless-config generates proxy files (or copies) exactly where tools expect them.
project/
.root/
configs/
vite.config.js
eslint.config.js
env/
.env
assets/
favicon.ico
src/
package.jsonAfter rootless prepare:
vite.config.js ← proxy → .root/configs/vite.config.js
eslint.config.js ← proxy → .root/configs/eslint.config.js
.env ← copy from .root/env/.envAll generated files are git-ignored automatically.
Installation
npm install -D rootless-configQuick Start
rootless init # scaffold .root/ structure
# move your configs into .root/configs/, .root/env/, .root/assets/
rootless prepare # generate proxy/copy filesAdd to package.json:
{
"scripts": {
"dev": "rootless prepare && vite"
}
}Project Structure
.root/
configs/ ← *.config.js, *.config.ts
env/ ← .env, .env.production
assets/ ← favicon.ico, robots.txt
rootless.config.json
rootless.versionCommands
| Command | Description |
|---------|-------------|
| rootless init | Scaffold a new .root/ container |
| rootless prepare | Generate proxy/copy files |
| rootless watch | Watch .root/ and regenerate on change |
| rootless clean | Remove generated files |
| rootless doctor | Health-check the container |
| rootless status | Show status of generated files |
| rootless migrate | Move existing configs into .root/ |
| rootless inspect | Show detected config sources |
| rootless graph | Display config dependency graph |
| rootless validate | Validate rootless.config.json |
| rootless debug | Dump internal state |
| rootless stats | Show project statistics |
| rootless benchmark | Measure prepare pipeline timings |
| rootless completion | Generate shell autocompletion |
Flags
rootless prepare --yes # auto-approve file override prompts (CI-friendly)
rootless prepare --no # auto-decline file override prompts
rootless prepare --verbose # verbose output
rootless prepare --silent # suppress all outputProgrammatic API
import { prepare, watch, clean } from 'rootless-config'
await prepare()
await prepare({ yes: true })
const watcher = await watch()
// ...
await watcher.stop()
await clean()rootless.config.json
{
"mode": "proxy",
"containerPath": ".root",
"plugins": [],
"remote": [],
"experimental": {
"virtualFS": false,
"capsule": false
}
}| Field | Type | Default | Description |
|-------|------|---------|-------------|
| mode | "proxy" \| "copy" | "proxy" | Generation mode |
| containerPath | string | ".root" | Path to container (relative to project root) |
| plugins | string[] | [] | External plugin module names |
| remote | string[] | [] | Remote config URLs |
| experimental | object | {} | Feature flags |
FAQ
Q: Will this break my tools?
Proxy mode generates export { default } from "./.root/configs/vite.config.js" — tools load the original file through the re-export. Copy mode duplicates the file.
Q: What about CI?
Use rootless prepare --yes or set CI=true in environment — overrides are auto-approved.
Q: Monorepo?
Place .root/ at the monorepo root. Each sub-package finds it automatically via upward traversal. Or set containerPath per package.
Q: My config file already exists at root?
rootless prepare will ask Override? (y/n). Existing unmanaged files are never silently overwritten.
Documentation
License
MIT
