cursor-directory
Version:
CLI tool to fetch and save Cursor rules from cursor.directory
93 lines (75 loc) • 2.81 kB
JavaScript
import { Command } from 'commander';
import fetch from 'node-fetch';
import fs from 'fs-extra';
import path from 'path';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// Function to extract slug from input (could be a URL or a direct slug)
function extractSlug(input) {
// Check if input is a URL
if (input.startsWith('http://') || input.startsWith('https://')) {
// Extract the slug from the URL (everything after the last slash)
const urlParts = input.split('/');
return urlParts[urlParts.length - 1];
}
// If not a URL, assume it's already a slug
return input;
}
const program = new Command();
program
.name('cursor-directory')
.description('CLI to interact with cursor.directory')
.version('1.0.0');
// Add 'rules' command with subcommands
const rulesCommand = program.command('rules')
.description('Manage cursor rules')
.action(() => {
// Display help for the rules command when it's used without a subcommand
rulesCommand.help();
});
// Add 'add' subcommand
rulesCommand.command('add')
.description('Add a cursor rule from cursor.directory')
.argument('<input>', 'Slug or URL of the cursor rule to fetch (e.g. "my-rule" or "https://cursor.directory/my-rule")')
.action(async (input) => {
try {
const slug = extractSlug(input);
console.log(`Fetching cursor rule with slug: ${slug}`);
// Fetch data directly from the specific API endpoint for this rule
const response = await fetch(`https://cursor.directory/api/${slug}`);
if (!response.ok) {
throw new Error(`Failed to fetch from API: ${response.statusText}`);
}
const json = await response.json();
// The data structure is different from the general API - it's directly in the data object
const rule = json.data;
if (!rule) {
throw new Error(`No rule found with slug: ${slug}`);
}
// Prepare the .cursor/rules directory
const rulesDir = path.join(process.cwd(), '.cursor', 'rules');
await fs.ensureDir(rulesDir);
// Prepare the file content with frontmatter
const fileContent = `---
description: ${rule.title}
globs:
alwaysApply: false
---
${rule.content.trim()}`;
// Write the file
const filePath = path.join(rulesDir, `${slug}.mdc`);
await fs.writeFile(filePath, fileContent);
console.log(`Successfully saved rule to: ${filePath}`);
} catch (error) {
console.error(`Error: ${error.message}`);
process.exit(1);
}
});
// Show help if no arguments are provided
if (process.argv.length <= 2) {
program.help();
}
program.parse(process.argv);