🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

git-permachine

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

git-permachine

Automatically merge machine-specific config files with base configs using git hooks

Source
npmnpm
Version
0.1.3
Version published
Weekly downloads
3
-57.14%
Maintainers
1
Weekly downloads
 
Created
Source

permachine

Automatically merge machine-specific configuration files with base configurations in git repositories. Like Husky for git hooks, but for config file management.

Problem

When working across multiple machines, you often need:

  • Shared configuration - Settings that work across all machines
  • Machine-specific overrides - Local paths, API keys, ports, etc.
  • Automatic merging - No manual copy-paste or merge steps
  • Git-friendly - Base and machine configs in version control, output gitignored

Solution

permachine automatically:

  • Detects your machine name
  • Finds machine-specific config files (e.g., config.homezone.json)
  • Merges them with base configs (e.g., config.base.json)
  • Outputs the final config (e.g., config.json)
  • Manages .gitignore - Adds output files and removes from git tracking
  • Runs automatically on git operations via hooks

Quick Start

# In your repository
cd /path/to/your/repo

# Initialize (one-time setup)
npx permachine init

# That's it! Your configs will now auto-merge on git operations

Installation

Development (Local)

cd D:/projects/git-permachine
bun install
bun link

# In your target repo
cd /path/to/your/repo
bun link git-permachine

Production

npm install -g git-permachine
# or
bun add -g git-permachine

Usage

File Naming Convention

Given machine name homezone (auto-detected):

PurposeFilenameIn Git?
Base config (shared)config.base.json✅ Yes
Machine-specificconfig.homezone.json✅ Yes
Final output (merged)config.json❌ No (gitignored)

Same pattern works for .env files:

PurposeFilenameIn Git?
Base config.env.base✅ Yes
Machine-specific.env.homezone✅ Yes
Final output.env❌ No (gitignored)

Commands

init - Initialize in repository

permachine init [options]

Options:
  --legacy            Use .git/hooks wrapping instead of core.hooksPath
  --auto              Auto-detect best installation method
  --no-gitignore      Don't manage .gitignore or git tracking

What it does:

  • Detects machine name (e.g., homezone)
  • Installs git hooks (post-checkout, post-merge, post-commit)
  • Scans for existing *.{machine}.* files
  • Performs initial merge
  • Automatically manages .gitignore:
    • Adds output files (e.g., config.json, .env) to .gitignore
    • Removes already-tracked output files from git index (git rm --cached)
    • Creates .gitignore if it doesn't exist
    • Appends to existing .gitignore without duplicates

Example output:

✓ Machine detected: homezone
✓ 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

merge - Manually trigger merge

permachine merge [options]

Options:
  --silent            Suppress all output except errors
  --no-gitignore      Don't manage .gitignore or git tracking

What it does:

  • Scans for machine-specific files
  • Merges with base configs
  • Writes output files
  • Automatically updates .gitignore (unless --no-gitignore is used)

Useful for:

  • Testing merge logic
  • Running manually without git hooks
  • CI/CD pipelines

info - Show current setup

permachine info

Example output:

Machine name: homezone
Repository: /path/to/repo
Hooks method: core.hooksPath
Hooks path: .permachine/hooks
Tracked patterns: 2
  - config.base.json + config.homezone.json → config.json
  - .env.base + .env.homezone → .env

uninstall - Remove git hooks

permachine uninstall

Removes git hooks and restores original hooks (if using legacy mode).

How It Works

1. Machine Detection

Automatically detects machine name across platforms:

  • Windows: COMPUTERNAME environment variable
  • Linux/Mac: hostname()
  • Normalized to lowercase for consistency

2. File Discovery

Scans repository for files matching *.{machine}.* pattern:

  • config.homezone.json
  • .env.homezone
  • settings.homezone.json
  • Ignores node_modules/, .git/, dist/

3. Merging Strategy

JSON Files

  • Deep merge: Machine config recursively overrides base
  • Arrays: Replaced entirely (not merged by index)
  • Output: 2-space indentation, ends with newline

Example:

// config.base.json
{
  "server": { "host": "localhost", "port": 3000 },
  "logging": { "level": "info" }
}

// config.homezone.json
{
  "server": { "port": 8080 },
  "database": { "password": "secret" }
}

// config.json (merged output)
{
  "server": { "host": "localhost", "port": 8080 },
  "logging": { "level": "info" },
  "database": { "password": "secret" }
}

ENV Files

  • Simple key-value merge: Machine values override base
  • Preserves comments: From base file
  • Quoted values: Auto-quotes values with spaces or special chars

Example:

# .env.base
DATABASE_HOST=localhost
DATABASE_PORT=5432
API_KEY=default

# .env.homezone
DATABASE_PORT=3306
API_KEY=secret_key_123

# .env (merged output)
DATABASE_HOST=localhost
DATABASE_PORT=3306
API_KEY=secret_key_123

4. Gitignore Management

Automatic on init and merge:

  • Adds output files to .gitignore (e.g., config.json, .env)
  • Removes already-tracked files from git with git rm --cached
  • Creates .gitignore if missing
  • Appends to existing .gitignore without duplicates
  • Preserves comments and formatting
  • Normalizes paths (Windows \/)

Edge cases handled:

  • Files with spaces in names
  • Nested directories (config/app.json)
  • Mixed tracking states (some tracked, some not)
  • Idempotent - safe to run multiple times

Disable with --no-gitignore:

permachine init --no-gitignore
permachine merge --no-gitignore

5. Git Hooks

Two installation methods:

Preferred: core.hooksPath

git config core.hooksPath .permachine/hooks
  • Clean, modern approach
  • No modification of .git/hooks
  • Easy to uninstall

Legacy: .git/hooks wrapping

  • Backs up existing hooks to .git/hooks/*.pre-mcs
  • Wraps existing hooks (calls them after merge)
  • Compatible with other git hook tools

6. Automation

Hooks run on:

  • post-checkout: After switching branches
  • post-merge: After git pull or git merge
  • post-commit: After committing

Merge happens silently in background (only logs errors).

Examples

Example 1: OpenCode Configuration

cd C:\Users\josch\.config\opencode

# Initialize
permachine init

# Machine detected: homezone

# Reorganize existing config
mv config.json config.homezone.json

# Create base config with shared settings
cat > config.base.json << EOF
{
  "theme": "nightowl-transparent",
  "autoupdate": true
}
EOF

# Add machine-specific settings to config.homezone.json
# ...edit file...

# Merge
permachine merge

# Output: config.json (gitignored)
# Future git operations auto-merge!

Example 2: Multi-Environment Project

# Different machines, different settings
# Machine: "workstation"
config.workstation.json → Development settings, localhost
.env.workstation → Local database credentials

# Machine: "server"
config.server.json → Production settings, real domains
.env.server → Production database credentials

# Shared base
config.base.json → Common app settings
.env.base → Default environment variables

# Each machine gets its own merged config automatically!

Example 3: Multiple Config Files

# Project structure
project/
├── config.base.json
├── config.homezone.json
├── settings/
│   ├── app.base.json
│   ├── app.homezone.json
│   ├── database.base.json
│   └── database.homezone.json
└── .env.base
    .env.homezone

# All files auto-merge on git operations:
# - config.json
# - settings/app.json
# - settings/database.json
# - .env

Supported File Types

  • JSON (.json)
  • ENV (.env, .env.*)
  • 🔜 YAML (future)
  • 🔜 TOML (future)

Error Handling

Base missing, machine exists

→ Uses machine file only

Machine missing, base exists

→ Uses base file only (rare, scanner looks for machine files)

Both missing

→ Skips silently

Parse error

→ Logs error with file path, skips merge

Write error

→ Logs error, doesn't crash

Development

Setup

git clone <repo>
cd permachine
bun install

Run Tests

# All tests
bun test

# Watch mode
bun test --watch

# Specific test file
bun test tests/unit/json-adapter.test.ts

Build

bun run build

Run Locally

bun run dev init
bun run dev merge
bun run dev info

Troubleshooting

Hooks not running

Check hook installation:

permachine info

Verify git config:

git config --get core.hooksPath
# Should output: .permachine/hooks

Check hook files exist:

ls .permachine/hooks/

Merge not happening

Run manually to see errors:

permachine merge

Check machine name:

permachine info
# Verify "Machine name" matches your file pattern

Conflicts with other git hook tools

Use legacy mode:

permachine uninstall
permachine init --legacy

Contributing

Contributions welcome! Please:

  • Fork the repository
  • Create a feature branch
  • Add tests for new functionality
  • Ensure all tests pass (bun test)
  • Submit a pull request

License

MIT © JosXa

Roadmap

  • JSON support
  • ENV support
  • JSONC support (comments & trailing commas)
  • Git hooks (hooksPath & legacy)
  • Automatic .gitignore management
  • CLI interface
  • Comprehensive tests (74 tests)
  • npm package publication
  • YAML support
  • TOML support
  • Custom merge strategies
  • Config file for patterns
  • Watch mode for development
  • Dry-run mode

Credits

Inspired by:

  • Husky - Git hooks made easy
  • The need for machine-specific configurations across development environments

Keywords

git

FAQs

Package last updated on 12 Jan 2026

Did you know?

Socket

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.

Install

Related posts