
Security News
Next.js moves to scheduled security releases
Vercel is formalizing a monthly release program for Next.js. The change follows React2Shell and a sharp rise in AI-assisted vulnerability discovery.
git-permachine
Advanced tools
Automatically merge machine-specific config files with base configs using git hooks
Per-machine config management with git for tools that don't support it natively. Automatically merge machine-specific configurations with a base config.
When syncing dotfiles across multiple machines, you often need:
permachine automatically:
config.my-laptop.json, config.workstation.json)config.base.json)config.json)# Install globally
npm install -g git-permachine
# In your repository
cd /path/to/your/repo
# Initialize (one-time setup)
permachine init
# That's it! Your configs will now auto-merge on git operations when a file ends with `.<machine-name>.<ext>`
permachine - Automatically merge machine-specific config files
USAGE:
permachine <command> [options]
COMMANDS:
init Initialize permachine in current repository
merge Manually trigger merge operation
info Show information about current setup
uninstall Uninstall git hooks
watch Watch for file changes and auto-merge
OPTIONS:
--help, -h Show this help message
--version, -v Show version number
--silent, -s Suppress all output except errors (for merge command)
--legacy Use legacy .git/hooks wrapping (for init command)
--auto Auto-detect best installation method (for init command)
--no-gitignore Don't manage .gitignore or git tracking (for init/merge commands)
--debounce <ms> Debounce delay in milliseconds (for watch command, default: 300)
--verbose Show detailed file change events (for watch command)
EXAMPLES:
permachine init
permachine merge --silent
permachine info
permachine uninstall
permachine watch
permachine watch --debounce 500 --verbose
Given machine name my-laptop (auto-detected from hostname):
| Purpose | Filename | In Git? |
|---|---|---|
| Base config (shared) | config.base.json | ✅ Yes |
| Machine-specific | config.my-laptop.json | ✅ Yes |
| Final output (merged) | config.json | ❌ No (gitignored) |
Same pattern works for .env files:
| Purpose | Filename | In Git? |
|---|---|---|
| Base config | .env.base | ✅ Yes |
| Machine-specific | .env.my-laptop | ✅ Yes |
| Final output | .env | ❌ No (gitignored) |
permachine init
What it does:
laptop, desktop, workstation).gitignore and removes them from git trackingExample output:
✓ Machine detected: laptop
✓ Git hooks installed via core.hooksPath
✓ Merged 2 file(s)
✓ Added 2 file(s) to .gitignore
✓ Removed 1 file(s) from git tracking
Git hooks will auto-merge on:
- checkout (switching branches)
- merge (git pull/merge)
- commit
permachine merge
Prompts for confirmation if existing files will be overwritten. Useful for testing or running without git hooks.
permachine watch
What it does:
Perfect for development - just leave it running and your configs stay up-to-date as you type.
Example output:
✓ Machine detected: laptop
✓ Watching 4 file(s) for changes...
- config.base.json
- config.laptop.json
- .env.base
- .env.laptop
[12:34:56] Changed: config.laptop.json
[12:34:56] Merged config.base.json + config.laptop.json → config.json
✓ Ready
^C
✓ Stopped watching
Options:
--debounce <ms> - Adjust debounce delay (default: 300ms)--verbose - Show detailed file change eventspermachine info
Example output:
Machine name: laptop
Repository: /path/to/repo
Hooks method: core.hooksPath
Hooks path: .permachine/hooks
Tracked patterns: 2
- config.base.json + config.laptop.json → config.json
- .env.base + .env.laptop → .env
Output files: 2 total, 1 existing
Existing output files:
- config.json
Different settings for work laptop vs home desktop:
# On work laptop (machine: "worklaptop")
.vscode/
├── settings.base.json # Shared: theme, font size
├── settings.worklaptop.json # Work paths, proxy settings
└── settings.json # ← Merged output (gitignored)
# On home desktop (machine: "desktop")
.vscode/
├── settings.base.json # Shared: theme, font size
├── settings.desktop.json # Home paths, no proxy
└── settings.json # ← Merged output (gitignored)
setup.base.json:
{
"editor.fontSize": 14,
"workbench.colorTheme": "Dark+"
}
settings.worklaptop.json:
{
"http.proxy": "http://proxy.company.com:8080",
"terminal.integrated.cwd": "C:/Projects"
}
Different database credentials per environment:
# .env.base (shared defaults)
NODE_ENV=development
LOG_LEVEL=info
API_PORT=3000
# .env.laptop (local dev)
DATABASE_URL=postgresql://localhost:5432/myapp_dev
API_KEY=dev_key_123
# .env.prodserver (production)
DATABASE_URL=postgresql://prod.db.com:5432/myapp
API_KEY=prod_key_xyz
# .env ← Merged output (gitignored)
Different build scripts for different machines:
# package.base.json
{
"name": "my-app",
"version": "1.0.0",
"scripts": {
"test": "jest"
},
"dependencies": {
"express": "^4.18.0"
}
}
# package.laptop.json (local development)
{
"scripts": {
"dev": "nodemon src/index.js",
"build": "webpack --mode development"
}
}
# package.buildserver.json (CI/CD)
{
"scripts": {
"build": "webpack --mode production",
"deploy": "aws s3 sync dist/ s3://my-bucket"
}
}
# package.json ← Merged output
# Each machine gets appropriate scripts!
Multi-environment database setup:
# config/database.base.json
{
"pool": {
"min": 2,
"max": 10
},
"migrations": {
"directory": "./migrations"
}
}
# config/database.laptop.json
{
"connection": {
"host": "localhost",
"port": 5432,
"database": "myapp_dev",
"user": "dev",
"password": "dev123"
}
}
# config/database.prodserver.json
{
"connection": {
"host": "db.production.com",
"port": 5432,
"database": "myapp_production",
"user": "produser",
"password": "secure_password_from_vault"
},
"pool": {
"min": 10,
"max": 50
}
}
Complex projects with multiple config files:
project/
├── config.base.json
├── config.laptop.json
├── settings/
│ ├── app.base.json
│ ├── app.laptop.json
│ ├── database.base.json
│ └── database.laptop.json
├── .env.base
└── .env.laptop
# After `permachine init`, all files auto-merge:
# - config.json
# - settings/app.json
# - settings/database.json
# - .env
permachine uses a simple three-step process:
Machine Detection - Automatically detects your machine name from hostname (Windows: COMPUTERNAME, Linux/Mac: hostname())
File Discovery - Scans your repository for files matching the pattern *.{machine}.* (e.g., config.laptop.json, .env.desktop)
Smart Merging - Merges base and machine-specific configs:
Gitignore Management - Automatically adds output files to .gitignore and removes already-tracked files from git
Git Hooks - Installs hooks to auto-merge on checkout, merge, and commit operations
For detailed implementation information, see CONTRIBUTING.md.
| Type | Extensions | Merge Strategy | Status |
|---|---|---|---|
| JSON | .json | Deep recursive merge | ✅ Supported |
| JSONC | .json with comments | Deep merge + comment preservation | ✅ Supported |
| ENV | .env, .env.* | Key-value override | ✅ Supported |
| YAML | .yaml, .yml | Deep recursive merge | 🔜 Planned |
| TOML | .toml | Deep recursive merge | 🔜 Planned |
Check hook installation:
permachine info
Verify git config:
git config --get core.hooksPath
# Should output: .permachine/hooks
Check hook files exist:
ls .permachine/hooks/
Run manually to see errors:
permachine merge
Check machine name matches your files:
permachine info
# Verify "Machine name" matches your file pattern
Machine names are auto-detected from your system hostname. To verify:
# Windows
echo %COMPUTERNAME%
# Linux/Mac
hostname
Files must match this name (case-insensitive).
If you use Husky or other hook managers, use legacy mode:
permachine uninstall
permachine init --legacy
This wraps existing hooks instead of replacing them.
By default, permachine init and permachine merge automatically add output files to .gitignore. If this isn't working:
.gitignore exists and contains your output filesgit ls-files config.json (should return nothing)--no-gitignore, re-run without that flagTo manually fix:
echo "config.json" >> .gitignore
git rm --cached config.json
Contributions are welcome! Please see CONTRIBUTING.md for:
MIT © JosXa
Inspired by:
FAQs
Automatically merge machine-specific config files with base configs using git hooks
The npm package git-permachine receives a total of 5 weekly downloads. As such, git-permachine popularity was classified as not popular.
We found that git-permachine demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Vercel is formalizing a monthly release program for Next.js. The change follows React2Shell and a sharp rise in AI-assisted vulnerability discovery.

Research
/Security News
11 malicious NuGet tools pose as game cheats to deploy Windows payloads, track hosts, and use Google Sheets for telemetry and control.

Research
/Security News
4 compromised asyncapi packages deliver miasma botnet loader on macOS, Linux and Windows.