routie dev init since i didn't adhere to any proper guidance up until now

This commit is contained in:
2026-04-29 22:27:29 -06:00
commit e1dabb71e2
15301 changed files with 3562618 additions and 0 deletions
+136
View File
@@ -0,0 +1,136 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.run = run;
const yargs_1 = __importDefault(require("yargs"));
const helpers_1 = require("yargs/helpers");
const handlers_1 = require("./handlers");
const index_1 = require("../agents/index");
/**
* Sets up and parses CLI commands.
*/
function run() {
(0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
.scriptName('ruler')
.usage('$0 <command> [options]')
.command('apply', 'Apply ruler configurations to supported AI agents', (y) => {
return y
.option('project-root', {
type: 'string',
description: 'Project root directory',
default: process.cwd(),
})
.option('agents', {
type: 'string',
description: `Comma-separated list of agent identifiers: ${(0, index_1.getAgentIdentifiersForCliHelp)()}`,
})
.option('config', {
type: 'string',
description: 'Path to TOML configuration file',
})
.option('mcp', {
type: 'boolean',
description: 'Enable or disable applying MCP server config',
default: true,
})
.alias('mcp', 'with-mcp')
.option('mcp-overwrite', {
type: 'boolean',
description: 'Replace (not merge) the native MCP config(s)',
default: false,
})
.option('gitignore', {
type: 'boolean',
description: 'Enable/disable automatic .gitignore updates (default: enabled)',
})
.option('gitignore-local', {
type: 'boolean',
description: 'Write generated ignore entries to .git/info/exclude instead of .gitignore',
})
.option('verbose', {
type: 'boolean',
description: 'Enable verbose logging',
default: false,
})
.alias('verbose', 'v')
.option('dry-run', {
type: 'boolean',
description: 'Preview changes without writing files',
default: false,
})
.option('local-only', {
type: 'boolean',
description: 'Only search for local .ruler directories, ignore global config',
default: false,
})
.option('nested', {
type: 'boolean',
description: 'Enable nested rule loading from nested .ruler directories (default: from config or disabled)',
})
.option('backup', {
type: 'boolean',
description: 'Enable/disable creation of .bak backup files (default: enabled)',
default: true,
})
.option('skills', {
type: 'boolean',
description: 'Enable/disable skills support (experimental, default: enabled)',
});
}, handlers_1.applyHandler)
.command('init', 'Scaffold a .ruler directory with default files', (y) => {
return y
.option('project-root', {
type: 'string',
description: 'Project root directory',
default: process.cwd(),
})
.option('global', {
type: 'boolean',
description: 'Initialize in global config directory (XDG_CONFIG_HOME/ruler)',
default: false,
});
}, handlers_1.initHandler)
.command('revert', 'Revert ruler configurations from supported AI agents', (y) => {
return y
.option('project-root', {
type: 'string',
description: 'Project root directory',
default: process.cwd(),
})
.option('agents', {
type: 'string',
description: `Comma-separated list of agent identifiers: ${(0, index_1.getAgentIdentifiersForCliHelp)()}`,
})
.option('config', {
type: 'string',
description: 'Path to TOML configuration file',
})
.option('keep-backups', {
type: 'boolean',
description: 'Keep backup files after revert',
default: false,
})
.option('verbose', {
type: 'boolean',
description: 'Enable verbose logging',
default: false,
})
.alias('verbose', 'v')
.option('dry-run', {
type: 'boolean',
description: 'Preview changes without writing files',
default: false,
})
.option('local-only', {
type: 'boolean',
description: 'Only search for local .ruler directories, ignore global config',
default: false,
});
}, handlers_1.revertHandler)
.demandCommand(1, 'You need to specify a command')
.help()
.strict()
.parse();
}
+232
View File
@@ -0,0 +1,232 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.applyHandler = applyHandler;
exports.initHandler = initHandler;
exports.revertHandler = revertHandler;
const lib_1 = require("../lib");
const revert_1 = require("../revert");
const path = __importStar(require("path"));
const os = __importStar(require("os"));
const fs = __importStar(require("fs/promises"));
const constants_1 = require("../constants");
const ConfigLoader_1 = require("../core/ConfigLoader");
function assertNotInsideRulerDir(projectRoot) {
const normalized = path.resolve(projectRoot);
const segments = normalized.split(path.sep);
if (segments.includes('.ruler')) {
console.error(`${constants_1.ERROR_PREFIX} Cannot run from inside a .ruler directory. Please run from your project root.`);
process.exit(1);
}
}
/**
* Handler for the 'apply' command.
*/
async function applyHandler(argv) {
const projectRoot = argv['project-root'];
assertNotInsideRulerDir(projectRoot);
const agents = argv.agents
? argv.agents.split(',').map((a) => a.trim())
: undefined;
const configPath = argv.config;
const mcpEnabled = argv.mcp;
const mcpStrategy = argv['mcp-overwrite']
? 'overwrite'
: undefined;
const verbose = argv.verbose;
const dryRun = argv['dry-run'];
const localOnly = argv['local-only'];
const backup = argv.backup;
// Determine gitignore preference: CLI > TOML > Default (enabled)
// yargs handles --no-gitignore by setting gitignore to false
let gitignorePreference;
if (argv.gitignore !== undefined) {
gitignorePreference = argv.gitignore;
}
else {
gitignorePreference = undefined; // Let TOML/default decide
}
let gitignoreLocalPreference;
if (argv['gitignore-local'] !== undefined) {
gitignoreLocalPreference = argv['gitignore-local'];
}
else {
gitignoreLocalPreference = undefined; // Let TOML/default decide
}
// Determine nested preference: CLI > TOML > Default (false)
let nested;
if (argv.nested !== undefined) {
// CLI explicitly set nested (either --nested or --no-nested)
nested = argv.nested;
}
else {
// CLI didn't set nested, check TOML configuration
try {
const config = await (0, ConfigLoader_1.loadConfig)({
projectRoot,
configPath,
});
// Use TOML setting if available, otherwise default to false
nested = config.nested ?? false;
}
catch {
// If config loading fails, use default (false)
nested = false;
}
}
// Determine skills preference: CLI > TOML > Default (enabled)
let skillsEnabled;
if (argv.skills !== undefined) {
skillsEnabled = argv.skills;
}
else {
skillsEnabled = undefined; // Let config/default decide
}
try {
await (0, lib_1.applyAllAgentConfigs)(projectRoot, agents, configPath, mcpEnabled, mcpStrategy, gitignorePreference, verbose, dryRun, localOnly, nested, backup, skillsEnabled, gitignoreLocalPreference);
console.log('Ruler apply completed successfully.');
}
catch (err) {
const message = err instanceof Error ? err.message : String(err);
console.error(`${constants_1.ERROR_PREFIX} ${message}`);
process.exit(1);
}
}
/**
* Handler for the 'init' command.
*/
async function initHandler(argv) {
const projectRoot = argv['project-root'];
const isGlobal = argv['global'];
const rulerDir = isGlobal
? path.join(process.env.XDG_CONFIG_HOME || path.join(os.homedir(), '.config'), 'ruler')
: path.join(projectRoot, '.ruler');
await fs.mkdir(rulerDir, { recursive: true });
const instructionsPath = path.join(rulerDir, constants_1.DEFAULT_RULES_FILENAME); // .ruler/AGENTS.md
const tomlPath = path.join(rulerDir, 'ruler.toml');
const exists = async (p) => {
try {
await fs.access(p);
return true;
}
catch {
return false;
}
};
const DEFAULT_INSTRUCTIONS = `# AGENTS.md\n\nCentralised AI agent instructions. Add coding guidelines, style guides, and project context here.\n\nRuler concatenates all .md files in this directory (and subdirectories), starting with AGENTS.md (if present), then remaining files in sorted order.\n`;
const DEFAULT_TOML = `# Ruler Configuration File
# See https://ai.intellectronica.net/ruler for documentation.
# To specify which agents are active by default when --agents is not used,
# uncomment and populate the following line. If omitted, all agents are active.
# default_agents = ["copilot", "claude"]
# Enable nested rule loading from nested .ruler directories
# When enabled, ruler will search for and process .ruler directories throughout the project hierarchy
# nested = false
# [gitignore]
# enabled = true
# local = false # set true to write generated ignores to .git/info/exclude instead
# --- Agent Specific Configurations ---
# You can enable/disable agents and override their default output paths here.
# Use lowercase agent identifiers: aider, amp, claude, cline, codex, copilot, cursor, jetbrains-ai, kilocode, pi, windsurf
# [agents.copilot]
# enabled = true
# output_path = ".github/copilot-instructions.md"
# [agents.aider]
# enabled = true
# output_path_instructions = "AGENTS.md"
# output_path_config = ".aider.conf.yml"
# [agents.gemini-cli]
# enabled = true
# --- MCP Servers ---
# Define Model Context Protocol servers here. Two examples:
# 1. A stdio server (local executable)
# 2. A remote server (HTTP-based)
# [mcp_servers.example_stdio]
# command = "node"
# args = ["scripts/your-mcp-server.js"]
# env = { API_KEY = "replace_me" }
# [mcp_servers.example_remote]
# url = "https://api.example.com/mcp"
# headers = { Authorization = "Bearer REPLACE_ME" }
`;
if (!(await exists(instructionsPath))) {
// Create new AGENTS.md regardless of legacy presence.
await fs.writeFile(instructionsPath, DEFAULT_INSTRUCTIONS);
console.log(`[ruler] Created ${instructionsPath}`);
}
else {
console.log(`[ruler] ${constants_1.DEFAULT_RULES_FILENAME} already exists, skipping`);
}
if (!(await exists(tomlPath))) {
await fs.writeFile(tomlPath, DEFAULT_TOML);
console.log(`[ruler] Created ${tomlPath}`);
}
else {
console.log(`[ruler] ruler.toml already exists, skipping`);
}
}
/**
* Handler for the 'revert' command.
*/
async function revertHandler(argv) {
const projectRoot = argv['project-root'];
assertNotInsideRulerDir(projectRoot);
const agents = argv.agents
? argv.agents.split(',').map((a) => a.trim())
: undefined;
const configPath = argv.config;
const keepBackups = argv['keep-backups'];
const verbose = argv.verbose;
const dryRun = argv['dry-run'];
const localOnly = argv['local-only'];
try {
await (0, revert_1.revertAllAgentConfigs)(projectRoot, agents, configPath, keepBackups, verbose, dryRun, localOnly);
}
catch (err) {
const message = err instanceof Error ? err.message : String(err);
console.error(`${constants_1.ERROR_PREFIX} ${message}`);
process.exit(1);
}
}
+5
View File
@@ -0,0 +1,5 @@
#!/usr/bin/env node
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const commands_1 = require("./commands");
(0, commands_1.run)();