AI Agent Harness for Preferred Tooling Governance
This repository provides a unified system for AI agents to stay within preferred tooling boundaries while maintaining developer productivity. It serves as a harness for automated systems to enforce tooling policies without breaking existing workflows.
- Enforce tooling preferences for AI agents and automated systems
- Prevent tool drift in automated code generation and management
- Provide clear guidance when agents attempt to use disfavored tools
- Maintain consistency across AI-assisted development workflows
- Gradual migration support for teams adopting new tooling standards
- Multi-project environments where different projects use different tools
- Policy enforcement for organizations with specific tooling requirements
- Educational guidance for developers learning new tooling ecosystems
Install individual RTK wrapper:
# Via Nix
nix profile install .#rtk-wrap-ls
# Via Devbox
devbox add github:levonk/levonk-packages#rtk-wrap-ls
# Install complete RTK suite
nix profile install .#bundle-rtk-all
devbox add github:levonk/levonk-packages#bundle-rtk-allUsage:
# Commands automatically run through RTK for token optimization
ls -la # → rtk ls -la (compact output)
git status # → rtk git status (compact output)
npm install # → rtk npm install (filtered output)Install devbox-auto wrapper:
# Via Nix
nix profile install .#devbox-auto-npm
# Via Devbox
devbox add github:levonk/levonk-packages#devbox-auto-npm
# Install complete devbox-auto suite
nix profile install .#bundle-devbox-auto-all
devbox add github:levonk/levonk-packages#bundle-devbox-auto-allUsage:
# Commands automatically ensure tools via devbox
npm install # → Adds npm to devbox.json → devbox run -- npm install
python script.py # → Adds python to devbox.json → devbox run -- python script.pyInstall integrated package (environment + optimization + governance):
# Via Nix
nix profile install .#devbox-rtk-nodejs-pnpm-force
# Via Devbox
devbox add github:levonk/levonk-packages#devbox-rtk-nodejs-pnpm-forceUsage:
# npm → pnpm (force) + devbox environment + RTK optimization
npm install
# → ✅ Using pnpm instead of npm (forced by policy)...
# → 📦 Adding pnpm to devbox environment...
# → devbox run -- rtk pnpm installNote: Nix/Devbox packages work immediately. Other package managers require running just generate first.
# Add npm governance
devbox add github:levonk/levonk-packages#prefer-pnpm
# Add comprehensive governance
devbox add github:levonk/levonk-packages#command-governance
# Your existing workflow continues unchanged
npm install # Now governed by pnpm# Build locally from source
nix build .#prefer-pnpm
nix build .#command-governance
# Run governed commands
nix run .#prefer-pnpm -- --version
# Install to profile
nix profile install .#prefer-pnpm
nix profile install .#command-governance# First generate packages
git clone https://github.com/levonk/levonk-packages.git
cd levonk-packages
just generate
# Then install via your preferred package manager
# Example for Alpine:
apk add command-prefer-pnpm- Node.js with pnpm:
devbox-rtk-nodejs-pnpm-prefer,devbox-rtk-nodejs-pnpm-force,devbox-rtk-nodejs-pnpm-block,devbox-rtk-nodejs-pnpm-native - Node.js with yarn:
devbox-rtk-nodejs-yarn-prefer,devbox-rtk-nodejs-yarn-force,devbox-rtk-nodejs-yarn-block,devbox-rtk-nodejs-yarn-native - Node.js with bun:
devbox-rtk-nodejs-bun-prefer,devbox-rtk-nodejs-bun-force,devbox-rtk-nodejs-bun-block,devbox-rtk-nodejs-bun-native - Python with uv:
devbox-rtk-python-uv-prefer,devbox-rtk-python-uv-force,devbox-rtk-python-uv-block,devbox-rtk-python-uv-native
- Node.js:
devbox-auto-npm,devbox-auto-pnpm,devbox-auto-yarn - Python:
devbox-auto-python,devbox-auto-pip - Rust:
devbox-auto-cargo,devbox-auto-rustc - Go:
devbox-auto-go
Bundle Devbox Packages:
bundle-devbox-auto-nodejs- Node.js package managersbundle-devbox-auto-python- Python toolsbundle-devbox-auto-rust- Rust toolchainbundle-devbox-auto-go- Go toolsbundle-devbox-auto-all- All devbox-auto wrappers
Bundle RTK Packages:
-
bundle-rtk-core- Core command wrappers -
bundle-rtk-development- Development tool wrappers -
bundle-rtk-cloud- Cloud tool wrappers -
bundle-rtk-all- All 54 RTK wrapper packages -
Core Commands:
rtk-wrap-ls,rtk-wrap-tree,rtk-wrap-cat,rtk-wrap-find,rtk-wrap-grep,rtk-wrap-diff,rtk-wrap-wc,rtk-wrap-curl,rtk-wrap-json,rtk-wrap-env,rtk-wrap-deps,rtk-wrap-test,rtk-wrap-err -
Development Tools:
rtk-wrap-git,rtk-wrap-npm,rtk-wrap-npx,rtk-wrap-pnpm,rtk-wrap-tsc,rtk-wrap-jest,rtk-wrap-vitest,rtk-wrap-pytest,rtk-wrap-mypy,rtk-wrap-ruff,rtk-wrap-prettier,rtk-wrap-eslint,rtk-wrap-prisma,rtk-wrap-next,rtk-wrap-lint,rtk-wrap-format,rtk-wrap-playwright,rtk-wrap-cargo,rtk-wrap-pip,rtk-wrap-go,rtk-wrap-golangci-lint,rtk-wrap-rubocop,rtk-wrap-rake,rtk-wrap-rspec,rtk-wrap-gradlew -
Cloud & DevOps:
rtk-wrap-gh,rtk-wrap-glab,rtk-wrap-docker,rtk-wrap-kubectl,rtk-wrap-oc,rtk-wrap-aws,rtk-wrap-psql,rtk-wrap-dotnet,rtk-wrap-wget,rtk-wrap-gt
- npm → pnpm:
prefer-pnpm,eject-npm,force-pnpm,block-npm - npm → yarn:
prefer-yarn,eject-yarn,force-yarn,block-yarn - npm → bun:
prefer-bun,eject-bun,force-bun,block-bun
- pnpm → npm:
prefer-npm,eject-pnpm,force-npm,block-pnpm - pnpm → yarn:
prefer-yarn-from-pnpm,eject-yarn-from-pnpm,force-yarn-from-pnpm,block-yarn-from-pnpm - pnpm → bun:
prefer-bun-from-pnpm,eject-bun-from-pnpm,force-bun-from-pnpm,block-bun-from-pnpm
- yarn → npm:
prefer-npm-from-yarn,eject-npm-from-yarn,force-npm-from-yarn,block-npm-from-yarn - yarn → pnpm:
prefer-pnpm-from-yarn,eject-pnpm-from-yarn,force-pnpm-from-yarn,block-pnpm-from-yarn - yarn → bun:
prefer-bun-from-yarn,eject-bun-from-yarn,force-bun-from-yarn,block-bun-from-yarn
- bun → npm:
prefer-npm-from-bun,eject-npm-from-bun,force-npm-from-bun,block-npm-from-bun - bun → pnpm:
prefer-pnpm-from-bun,eject-pnpm-from-bun,force-pnpm-from-bun,block-pnpm-from-bun - bun → yarn:
prefer-yarn-from-bun,eject-yarn-from-bun,force-yarn-from-bun,block-yarn-from-bun
- all → nub (consolidated):
prefer-nub,force-nub,block-nub,eject-nub - npm → nub:
force-nub-from-npm - pnpm → nub:
prefer-nub-from-pnpm,force-nub-from-pnpm,block-nub-from-pnpm,eject-nub-from-pnpm - yarn → nub:
prefer-nub-from-yarn,force-nub-from-yarn,block-nub-from-yarn,eject-nub-from-yarn - bun → nub:
prefer-nub-from-bun,force-nub-from-bun,block-nub-from-bun,eject-nub-from-bun
force-nub*packages install nub fromgithub:nubjs/nub(compiled from source).prefer-nub*/block-nub*/eject-nub*do not install nub — it must already be on PATH.
- pip → uv:
prefer-uv,eject-pip,block-pip
- Environment setup:
prefer-devbox - Package manager management:
prefer-corepack
nodejs-ecosystem- All Node.js package manager governance (npm/pnpm/yarn/bun)python-ecosystem- Python package manager governance (pip/uv)dev-tools- Development tool governance (curl/devbox)migrate-to-pnpm-bundle- Complete npm→pnpm migration bundlemigrate-to-uv-bundle- Complete pip→uv migration bundle
force-uv- Individual package that forces pip→uv (as defined in specs)force-pnpm- Individual package that forces npm→pnpmforce-devbox- Individual package that forces curl→devbox
command-governance- All 47 governance packages in one bundle
Note: force-uv is an individual package (per specs), while migrate-to-uv-bundle is a convenience bundle that includes force-uv + eject-pip + prefer-uv for complete migration scenarios.
Total: 289 individual governance packages + 19 bundle packages = 308 packages
📖 See docs/PACKAGE_LIST.md for the complete detailed list.
Keep RTK wrapper packages synchronized with the official RTK README automatically:
# Run the sync workflow (requires Archon CLI)
bun run cli workflow run sync-rtk-commandsWorkflow location: .agents/workflows/sync-rtk-commands.yaml (also in .devin/workflows/)
All prefer-* wrappers now intelligently detect available alternatives on your system:
npm install
# ⚠️ Prefer pnpm over npm. Detecting available alternatives...
# ✅ Using pnpm (preferred)
# ℹ️ yarn is also available
# ℹ️ bun is also available
# 💡 Tip: Multiple alternatives detected. Consider standardizing on pnpm for best compatibility.New logical bundles organized by tool categories:
# Node.js ecosystem governance
devbox add github:levonk/levonk-packages#nodejs-ecosystem
# Python ecosystem governance
devbox add github:levonk/levonk-packages#python-ecosystem
# Development tool guidance
devbox add github:levonk/levonk-packages#dev-tools
# Complete migration scenarios
devbox add github:levonk/levonk-packages#migrate-to-pnpm
devbox add github:levonk/levonk-packages#migrate-to-uv# Start with gentle guidance
devbox add github:levonk/levonk-packages#prefer-pnpm
# npm commands now warn but still work
npm install
# ⚠️ Prefer pnpm over npm. Running pnpm instead...# Upgrade to strict replacement
devbox add github:levonk/levonk-packages#force-pnpm
# npm commands transparently use pnpm
npm install
# ✅ Using pnpm instead of npm (forced by policy)...# Block disallowed tools entirely
devbox add github:levonk/levonk-packages#block-npm
# npm commands are blocked
npm install
# ❌ npm is blocked by policy. Use pnpm or corepack instead.Each governance package wraps one or more binaries (e.g. npm, pnpm, yarn, bun). When you install multiple packages that wrap the same binary, they collide — whichever lands last in PATH wins, and the result is unpredictable. The rule is simple:
Each binary should be wrapped by exactly one package.
The main prefer-{tool} and force-{tool} packages are consolidated — each wraps all rival tools in one install:
| Package | Wraps | Redirects to |
|---|---|---|
prefer-nub / force-nub |
npm, pnpm, yarn, bun | nub |
prefer-pnpm / force-pnpm |
npm, yarn, bun | pnpm |
prefer-yarn / force-yarn |
npm, pnpm, bun | yarn |
prefer-bun / force-bun |
npm, pnpm, yarn | bun |
prefer-npm / force-npm |
pnpm, yarn, bun | npm |
Note: prefer-pnpm/force-pnpm/etc. do not wrap nub — nub is the superset tool, and users on nub shouldn't be downgraded.
Installing prefer-nub + force-nub is pointless — force wins, prefer is dead weight. Installing force-pnpm + force-nub is broken — both wrap npm, yarn, and bun, so they collide.
The *-from-{tool} packages wrap a single binary, so they compose without collisions. This lets you apply different governance modes to different tools:
# pnpm: polite suggestion to use nub (warns but falls back to pnpm)
nix profile install github:levonk/levonk-packages#prefer-nub-from-pnpm
# npm, yarn, bun: hard redirect to nub (no escape)
nix profile install github:levonk/levonk-packages#force-nub-from-npm
nix profile install github:levonk/levonk-packages#force-nub-from-yarn
nix profile install github:levonk/levonk-packages#force-nub-from-bunEach package wraps exactly one binary — no collisions:
| Package | Wraps | Mode |
|---|---|---|
prefer-nub-from-pnpm |
pnpm only |
warns → nub, falls back to pnpm |
force-nub-from-npm |
npm only |
hard → nub |
force-nub-from-yarn |
yarn only |
hard → nub |
force-nub-from-bun |
bun only |
hard → nub |
force-pnpm wraps npm, yarn, and bun — the same binaries already wrapped by force-nub-from-npm/yarn/bun. Adding it reintroduces collisions. If pnpm should be left alone (only nudged toward nub), prefer-nub-from-pnpm already handles that.
| Goal | Install |
|---|---|
| Everything → pnpm, hard | force-pnpm (one package) |
| Everything → nub, hard | force-nub (one package) |
| Everything → nub, polite | prefer-nub (one package) |
| pnpm polite, rest forced → nub | prefer-nub-from-pnpm + force-nub-from-npm + force-nub-from-yarn + force-nub-from-bun |
| npm blocked, rest → pnpm | block-npm + force-pnpm-from-yarn + force-pnpm-from-bun |
force-nub*packages pull nub fromgithub:nubjs/nubas a flake input — nub is compiled from source (Rust) and the wrapper execs the store-path binary.prefer-nub*,block-nub*,eject-nub*packages do not install nub — they usecommand -v nub(PATH lookup) or just print an error. nub must already be on PATH.
# Run basic functionality tests
just test
# Run comprehensive test suite
just test-comprehensive
# Test individual packages
just test-internal- 289 individual governance packages tested (115 existing + 92 devbox reminder + 54 RTK wrapper + 8 devbox-auto + 16 devbox-rtk-governance)
- 19 bundle packages tested (11 existing + 4 RTK bundle + 4 devbox-auto bundle)
- 303 test scenarios total
- Transient devbox environments for isolation
- Behavioral validation for all governance types
# Test traditional governance packages
nix run .#prefer-pnpm -- --version
nix run .#block-npm -- --version # Exits with error
# Test RTK wrapper packages
nix run .#rtk-wrap-ls -- --version
nix run .#rtk-wrap-git -- --version
# Test devbox-auto packages
nix run .#devbox-auto-npm -- --version
# Test integrated devbox-rtk packages
nix run .#devbox-rtk-nodejs-pnpm-force -- --version
# Test bundle packages
nix build .#nodejs-ecosystem
nix build .#python-ecosystem
nix build .#dev-tools
nix build .#migrate-to-pnpm
nix build .#migrate-to-uv
nix build .#bundle-rtk-all
nix build .#bundle-devbox-auto-allNote: Traditional governance packages must be generated first with just generate from this repository. RTK, devbox-auto, and integrated packages work immediately via Nix/Devbox.
| Manager | Command |
|---|---|
| Devbox | devbox add github:levonk/levonk-packages#prefer-pnpm |
| Nix | nix profile install .#prefer-pnpm |
| Nix (build) | nix build .#prefer-pnpm |
| Alpine | apk add command-prefer-pnpm (after generation) |
| Debian/Ubuntu | sudo apt install command-prefer-pnpm (after generation) |
| Fedora | sudo dnf install command-prefer-pnpm (after generation) |
| Arch | yay -S command-prefer-pnpm (after generation) |
| Homebrew | brew install command-prefer-pnpm (after generation) |
| mise | mise use prefer-pnpm (after generation) |
# Install individual RTK wrapper
nix profile install .#rtk-wrap-ls
devbox add github:levonk/levonk-packages#rtk-wrap-ls
# Install complete RTK suite
nix profile install .#bundle-rtk-all
devbox add github:levonk/levonk-packages#bundle-rtk-all# Install individual devbox-auto wrapper
nix profile install .#devbox-auto-npm
devbox add github:levonk/levonk-packages#devbox-auto-npm
# Install complete devbox-auto suite
nix profile install .#bundle-devbox-auto-all
devbox add github:levonk/levonk-packages#bundle-devbox-auto-all# Install integrated package (environment + optimization + governance)
nix profile install .#devbox-rtk-nodejs-pnpm-force
devbox add github:levonk/levonk-packages#devbox-rtk-nodejs-pnpm-force# Install traditional governance package
nix profile install .#prefer-pnpm
devbox add github:levonk/levonk-packages#prefer-pnpm
# Install comprehensive governance bundle
nix profile install .#command-governance
devbox add github:levonk/levonk-packages#command-governance# Generate packages for all ecosystems
just generate
# Or generate specific ecosystems
just generate-internal# Clone repository
git clone https://github.com/levonk/levonk-packages.git
cd levonk-packages
# Bootstrap development environment
just bootstrap
# Build all packages
just build
# Generate packaging for all ecosystems
just generate
# Test functionality
just testSee docs/SPEC.md for the behavioral model, dependency graph, and cross-ecosystem support.
Packages use shared Nix libraries in nix/lib/ that inline utility scripts at build time. See AGENTS.md for wrapper-authoring guidance.
This system integrates seamlessly with the Standard Developer UX Flow:
direnv → devbox → just (*-internal) → cargo
No changes to your existing workflow are required. Governance packages work like any other Devbox package.
build:
devbox shell build
test:
devbox shell test
dev:
devbox shell dev
# Internal targets work unchanged
build-internal:
npm run build # Automatically governed
test-internal:
npm test # Automatically governed# Test individual packages
nix run .#prefer-pnpm -- --version
nix run .#block-npm -- --version # Exits with error
# Test bundle package
nix build .#command-governance
# Test with Devbox
devbox add .#prefer-pnpm
npm --version # Shows governance behavior- Technical Specification - Complete technical details
- ADR Integration - Devbox workflow integration
- Requirements - Original requirements
- Fork the repository
- Create a feature branch
- See AGENTS.md for wrapper-authoring guidance (shared Nix libraries in
nix/lib/) - Test with
just test - Submit a pull request
MIT License - see LICENSE file for details.