npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

cursor-windsurf-convert

v0.2.0

Published

Convert cursor rules to windsurf rules and vice versa

Readme

cursor-windsurf-convert ("cuws")

Surf your AI rules from Cursor to Windsurf (and back) faster than you can say cat | cuws. 🏄‍♂️⛵

CI License NPM Version NPM Downloads

AboutWhy cuws?Key FeaturesQuick StartInstallationUsageAPIDevelopingContributingRoadmapFAQ


📖 About

cuws is a tiny but mighty Node.js CLI + library that losslessly converts rule files between Cursor (.cursor/rules/*.mdc) and Windsurf (.windsurf/rules/*.md) formats. Pipe it, script it, or call it from TypeScript—either way your rules arrive on the right shore untouched.

Windsurf shipped file‑based rules on 7 May 2025. This project exists so you can ride that wave today.


🤔 Why cuws?

  • Zero friction – stream via stdin/stdout or give it paths.
  • Bidirectional – Cursor ➜ Windsurf and Windsurf ➜ Cursor.
  • Fast – converts a 1 kB rule in < 50 ms. Blink and you’ll miss it.
  • Lossless metadata mapping – front‑matter stays intact, content unchanged.
  • CI‑ready – deterministic, non‑interactive, exit codes you can trust.
  • Tiny footprint – minimal runtime dependencies (gray-matter, commander, fast-glob for CLI).

✨ Key Features

| Feature | Description | | ------------------------------- | ----------------------------------------------------------------------------------- | | 🔄 Bidirectional conversion | cuws detects the source format or let you force it. | | 📂 Directory mode | Convert whole trees while mirroring structure (requires output directory specified). | | 🏗️ TypeScript API | Import convertString(), convertFile(), or convertDirectory() in your scripts. | | 🪝 Streaming first | Works perfectly in Unix pipes & GitHub Actions. | | 🐚 Single‑file binary | ES module with hashbang—no compilation required. |


🚀 Quick Start

The easiest way to use cuws without a global installation is with npx:

# Convert a single file (Cursor ➜ Windsurf) using npx
npx cursor-windsurf-convert -i .cursor/rules/auth.mdc -o .windsurf/rules/auth.md

# Pipe via stdin/stdout using npx
git show HEAD:my-rule.mdc | npx cursor-windsurf-convert --reverse > my-rule-cursor.mdc

# Convert all Cursor rules from '.cursor/rules' to Windsurf rules in '.windsurf/rules'
npx cursor-windsurf-convert -d .cursor/rules -o .windsurf/rules

# Convert all Windsurf rules from '.windsurf/rules' back to Cursor in '.cursor/rules-backup'
npx cursor-windsurf-convert -d .windsurf/rules -o .cursor/rules-backup --reverse

Alternatively, if you prefer a global installation for frequent use:

# Global install (optional)
npm install -g cursor-windsurf-convert
# Then use 'cuws' directly:
# cuws -i .cursor/rules/another.mdc -o .windsurf/rules/another.md

📦 Installation

While npx cursor-windsurf-convert ... is recommended for quick, one-off uses (see Quick Start), you can also install cuws:

As a project dependency:

# Using pnpm
pnpm add -D cursor-windsurf-convert

# Using yarn
yarn add -D cursor-windsurf-convert

# Using npm
npm install -D cursor-windsurf-convert

Then you can run it via pnpm cuws ... (if using pnpm) or add it to your package.json scripts.

Globally (for frequent use):

npm install -g cursor-windsurf-convert
# Now you can use 'cuws' directly anywhere:
# cuws --help

Node ≥ 18 required (tested on 18 & 20).


💻 Usage

CLI

cuws [options]

| Flag | Default | Description | | --------------------- | ----------- | --------------------------------------------------------------------------- | | -i, --input <path> | - | Path to source file or - for stdin. Conflicts with -d. | | -o, --output <path> | - | Path to dest file (with -i) or output directory (required with -d). | | -r, --reverse | false | Convert from Windsurf (.md) to Cursor (.mdc). | | --force <format> | | Override auto-detection (cursor or windsurf). | | -d, --dir <path> | | Recursively convert directory. Requires -o for output. Conflicts with -i. | | --dry-run | false | Print planned actions, don’t write files. | | --verbose | false | Extra logging. |

Programmatic API

import {
  convertString,
  convertFile,
  convertDirectory,
} from 'cursor-windsurf-convert';

// Convert a string
const cursorRuleContent = '...'; // content of a .mdc file
const windsurfRuleContent = convertString(cursorRuleContent, 'cw');

// Convert a single file
async function exampleConvertFile() {
  const outputPath = await convertFile('path/to/source.mdc', 'path/to/output.md');
  console.log(`Converted file written to: ${outputPath}`);
}

// Convert a directory
async function exampleConvertDirectory() {
  const results = await convertDirectory('path/to/source-dir', 'path/to/output-dir');
  results.forEach(result => {
    console.log(`${result.sourcePath} -> ${result.destinationPath} (${result.status})`);
  });
}

See API docs for full typings.


🛠️ Developing

  1. Clone & install deps:

    git clone https://github.com/YOUR_ORG/cursor-windsurf-convert.git
    cd cursor-windsurf-convert && pnpm install
  2. Link the CLI for local testing:

    pnpm run build # if you transpile
    pnpm link --global   # exposes `cuws` in PATH
  3. Run tests:

    pnpm test

package.json bin field

{
  "name": "cursor-windsurf-convert",
  "version": "1.0.0",
  "bin": {
    "cuws": "dist/cli.mjs"
  },
  ...
}

The CLI file must start with #!/usr/bin/env node and be chmod +x.


🤝 Contributing

PRs welcome! Check the open issues or open a new one. Also see CONTRIBUTING.md for details.


🏄 Roadmap

  • [x] One‑file conversion
  • [x] Directory batch mode

❓ FAQ

| Q | A | | ---------------------------------- | ---------------------------------------------- | | Does it change my markdown body? | Nope. Only the YAML/MD header is mapped. | | Can I embed this in my own tool? | Absolutely—import the TS API. | | What if I get YAML errors? | cuws uses a strict YAML parser. See YAML Parsing Strictness below. |


YAML Parsing Strictness

cuws uses a strict YAML parser for the front-matter in rule files. This ensures that conversions are accurate and that your rule files adhere to valid YAML syntax. If you encounter errors related to YAML parsing (often error code E03), please check the following common pitfalls:

  • Missing Colons: Ensure every key-value pair has a colon separating the key and the value.
    • Incorrect: alwaysApply true
    • Correct: alwaysApply: true
  • Missing Values: Ensure that if a key has a colon, it also has a value following it.
    • Incorrect: description: (with nothing after the colon)
    • Correct: description: My rule description or remove the line if description is not needed.
  • Indentation: YAML is sensitive to indentation. Ensure that your indentation is consistent and correctly represents the structure of your metadata.
  • Special Characters in Unquoted Strings: If your string values contain special characters (e.g., :, {, }, [, ], ,, &, *, #, ?, |, -, <, >, =, !, %, @, `), they might need to be quoted.
    • Example: title: My Rule: A Detailed Look should be title: 'My Rule: A Detailed Look' or title: "My Rule: A Detailed Look".
    • cuws attempts to auto-quote problematic globs values during parsing, but other fields might require manual quoting if they contain special characters that could be misinterpreted by the YAML parser.

The error messages provided by cuws for YAML parsing issues will typically include the line number and a snippet from the original parser to help you locate the problem.


📄 License

MIT © 2025 Gordon Mickel


If this saves you time, drop a star!