Skip to content

Configuration

ai-rules-sync.json serves two different roles depending on where it is placed:

LocationPathRoleKey Fields
Rules Repository (provider)./ai-rules-sync.json (repo root)Defines how rules are organized in the repoversion, sourceDir, rootPath
Project (consumer)./ai-rules-sync.json (project root)Records which rules to sync from which reposversion, tool.subtype entries

Additional config files:

FilePathPurpose
ai-rules-sync.local.jsonProject rootPrivate rules (not committed, auto-added to .gitignore)
user.json~/.config/ai-rules-sync/user.jsonUser-level config (applies to all projects)

TIP

Most users never edit these files directly — the CLI (ais add, ais rm, etc.) manages them. Edit manually only for advanced cases: aliases, custom targetDir, or custom sourceDir in rules repos.

Schema Version

All config files include a version field for forward compatibility:

json
{
  "version": 1
}

AIS automatically migrates legacy configs (without version) on read.


Rules Repository Config (Provider)

Placed in the rules repository root. Tells AIS where to find rules within this repo.

When to customize: Only needed when your rules are not in the default locations (e.g., .cursor/rules, .claude/skills). Run ais init to create a repo with default structure — no custom config required.

Basic Structure

json
{
  "version": 1,
  "rootPath": "src",
  "sourceDir": {
    "<tool>": {
      "<subtype>": "<path>"
    }
  }
}

Fields

FieldTypeDescription
versionnumberConfig schema version (currently 1)
rootPathstring?Optional path prefix applied to all source directories
sourceDirobjectMaps tool → subtype → source path

Example

json
{
  "version": 1,
  "rootPath": "src",
  "sourceDir": {
    "cursor": {
      "rules": ".cursor/rules",
      "commands": ".cursor/commands",
      "skills": ".cursor/skills",
      "agents": ".cursor/agents"
    },
    "copilot": {
      "instructions": ".github/instructions"
    },
    "claude": {
      "skills": ".claude/skills",
      "rules": ".claude/rules",
      "md": ".claude"
    }
  }
}

With rootPath: "src", the actual path for Cursor rules resolves to src/.cursor/rules.

Wildcard (*) Fallback

Use * as a tool key to define shared config that applies to all tools when tool-specific config is missing. Useful for subtypes like skills that are identical across Cursor, Copilot, Claude, etc.

json
{
  "version": 1,
  "rootPath": "src",
  "sourceDir": {
    "*": {
      "skills": "common/skills"
    },
    "cursor": {
      "rules": ".cursor/rules"
    }
  }
}
  • cursor.skills, copilot.skills, claude.skills, etc. all resolve to common/skills when not explicitly defined
  • Tool-specific config (e.g. cursor.rules) takes precedence over *

Source Path Modes

Source paths can be a simple string or an object with a mode discriminant for advanced mapping:

Simple String

json
"rules": ".cursor/rules"

File Mode

Map a specific source file to a different target filename:

json
"claude": {
  "md": {
    "mode": "file",
    "dir": "common",
    "sourceFile": "AGENTS.md",
    "targetFile": "CLAUDE.md"
  }
}

This maps common/AGENTS.md in the repo → CLAUDE.md in the project.

Directory Mode

Map a source directory to a different target directory name:

json
"cursor": {
  "rules": {
    "mode": "directory",
    "dir": "common",
    "sourceDir": "shared-rules",
    "targetName": "cursor-rules"
  }
}

This maps common/shared-rules/ in the repo → .cursor/rules/cursor-rules/ in the project.


Project Config (Consumer)

Placed in the project root. Records dependencies on rules from remote repositories.

Basic Structure

json
{
  "version": 1,
  "<tool>": {
    "<subtype>": {
      "<entry-name>": "<repo-url>" | { "url": "...", ... }
    }
  }
}

Wildcard (*) Fallback

Use * as a tool key to define shared dependencies that apply to all tools when tool-specific config is missing:

json
{
  "version": 1,
  "*": {
    "skills": {
      "shared-skill": "https://example.com/skills.git"
    }
  },
  "cursor": {
    "rules": {
      "my-rule": "https://example.com/rules.git"
    }
  }
}
  • cursor skills, copilot skills, etc. all see shared-skill when their own skills section is empty
  • Tool-specific entries take precedence; add/remove uses the adapter's config path, with fallback to * for remove

Example

json
{
  "version": 1,
  "cursor": {
    "rules": {
      "react": "https://github.com/user/repo.git",
      "react-v2": {
        "url": "https://github.com/user/another-repo.git",
        "rule": "react"
      }
    },
    "commands": { "deploy-docs": "https://github.com/user/repo.git" },
    "skills":   { "code-review": "https://github.com/user/repo.git" },
    "agents":   { "code-analyzer": "https://github.com/user/repo.git" }
  },
  "claude": {
    "rules":  { "general": "https://github.com/user/repo.git" },
    "skills": { "code-review": "https://github.com/user/repo.git" },
    "agents": { "debugger": "https://github.com/user/repo.git" },
    "md":     { "CLAUDE": "https://github.com/user/repo.git" }
  },
  "agentsMd": {
    "file": { "AGENTS": "https://github.com/user/repo.git" }
  }
}

All tools (copilot, trae, opencode, codex, gemini, warp, windsurf, cline) follow the same tool → subtype → entries structure.

Entry Formats

FormatWhen to useExample
StringSame name in project and repo"react": "https://github.com/user/repo.git"
Object with ruleDifferent local name (alias)"react-v2": { "url": "...", "rule": "react" }
Object with targetDirCustom symlink location"docs-rule": { "url": "...", "targetDir": "docs/ai/rules" }

Simple string — just the repo URL

json
"react": "https://github.com/user/repo.git"

Object with alias — different name in project vs repo

json
"react-v2": {
  "url": "https://github.com/user/repo.git",
  "rule": "react"
}

react-v2 is the local name; react is the name in the rules repo.

Object with custom target directory

json
"docs-rule": {
  "url": "https://github.com/user/repo.git",
  "targetDir": "docs/ai/rules"
}

Override where the symlink is placed in the project.


Local/Private Rules

Use ai-rules-sync.local.json for rules you don't want to commit:

bash
ais cursor add company-secrets --local
  • Same structure as ai-rules-sync.json
  • Automatically added to .gitignore
  • Merges with main config (local takes precedence on conflict)

User-Level Config (user.json)

Global rules applied to all projects. Stored at ~/.config/ai-rules-sync/user.json.

Same tool → subtype → entries structure:

json
{
  "version": 1,
  "claude": {
    "md": { "CLAUDE": "https://github.com/me/my-rules.git" }
  },
  "gemini": {
    "md": { "GEMINI": "https://github.com/me/my-rules.git" }
  }
}

Manage the user config path:

bash
ais config user show
ais config user set ~/dotfiles/ai-rules-sync/user.json
ais config user reset

Config Priority

When multiple configs exist, they merge with this priority (highest first):

  1. ai-rules-sync.local.json — private, per-project
  2. ai-rules-sync.json — shared, per-project
  3. user.json — global, per-user

Released under the Unlicense.