Skip to content

Latest commit

 

History

History
1680 lines (1404 loc) · 79.2 KB

File metadata and controls

1680 lines (1404 loc) · 79.2 KB

Project Knowledge Base

Project Overview

AI Rules Sync (ais) is a CLI tool designed to synchronize agent rules from a centralized Git repository to local projects using symbolic links. It supports Cursor rules, Cursor commands, Cursor skills, Cursor subagents, Copilot instructions, Claude Code rules/skills/subagents/CLAUDE.md, Trae rules/skills, OpenCode agents/skills/commands/tools, Codex rules/skills/AGENTS.md, Gemini CLI commands/skills/agents/GEMINI.md, Windsurf rules/skills, Cline rules/skills, and universal AGENTS.md support, keeping projects up-to-date across teams.

A key feature is User Mode (--user / -u): use $HOME as project root to manage AI config files in ~/.claude/, ~/.gemini/, ~/.codex/, ~/.config/opencode/, etc. Entries are tracked in ~/.config/ai-rules-sync/user.json (or a user-configured custom path for dotfiles integration) and gitignore management is skipped automatically.

Core Concepts

  • Rules Repository: A Git repository containing rule definitions in official tool paths (.cursor/rules/, .cursor/commands/, .cursor/skills/, .cursor/agents/, .github/instructions/, .claude/skills/, .claude/agents/, .claude/ (for CLAUDE.md), .trae/rules/, .trae/skills/, .opencode/agents/, .opencode/skills/, .opencode/commands/, .opencode/tools/, .codex/rules/, .codex/ (for AGENTS.md), .agents/skills/, .gemini/commands/, .gemini/skills/, .gemini/agents/, .gemini/ (for GEMINI.md), .windsurf/rules/, .windsurf/skills/, .clinerules/, .cline/skills/, agents-md/).
  • Symbolic Links: Entries are linked from the local cache of the repo to project directories, avoiding file duplication and drift.
  • Dependency Tracking: Uses ai-rules-sync.json to track project dependencies (Cursor rules/commands/skills/subagents, Copilot instructions, Claude Code rules/skills/subagents/CLAUDE.md, Trae rules/skills, OpenCode agents/skills/commands/tools, Codex rules/skills/AGENTS.md, Gemini CLI commands/skills/agents/GEMINI.md, Windsurf rules/skills, Cline rules/skills, universal AGENTS.md).
  • Privacy: Supports private/local entries via ai-rules-sync.local.json and .git/info/exclude.
  • User Mode: --user / -u flag on add/remove/install commands. Sets projectPath = $HOME, stores dependencies in ~/.config/ai-rules-sync/user.json, skips gitignore management. Enables ais user install to restore all user-scope symlinks on a new machine.
  • User Config Path: Configurable via ais config user set <path> for dotfiles integration (e.g. ~/dotfiles/ai-rules-sync/user.json).

Architecture

  • Language: TypeScript (Node.js).
  • CLI Framework: Commander.js.
  • Config: Stored in ~/.config/ai-rules-sync/config.json (global) and project roots.
  • Git Operations: Uses execa to run git commands; stores repos in ~/.config/ai-rules-sync/repos/.
  • Symlink Layer: All symlink creation/deletion goes through linkany (via DotfileManager.doLink / doUnlink), providing atomic operations. No bare fs.ensureSymlink calls in dotany.
  • Plugin Architecture: Modular adapter system for different AI tools.
  • Modular CLI: Declarative command registration using adapters.

Directory Structure

src/
├── dotfile/                 # Generic dotfile abstraction library (tool-agnostic)
│   ├── types.ts             # All interfaces: SourceResolver, ManifestStore, etc.
│   ├── manager.ts           # DotfileManager — all symlink ops via linkany (atomic)
│   ├── composer.ts          # DotfileComposer — multi-manager apply/status
│   ├── sources/filesystem.ts # FileSystemSource (local dir, stow basis)
│   ├── manifest/json.ts     # JsonManifest (generic JSON, optional namespace)
│   └── index.ts             # dotfile.create() / dotfile.compose() entry point
├── plugin/                  # ai-rules-sync plugin implementations
│   ├── git-repo-source.ts   # GitRepoSource (RepoConfig | RepoResolverFn | null)
│   └── ai-rules-sync-manifest.ts # AiRulesSyncManifest (over ai-rules-sync.json)
├── adapters/                # Plugin architecture for different AI tools
│   ├── types.ts             # SyncAdapter interface
│   ├── base.ts              # createBaseAdapter factory function
│   ├── index.ts             # Registry and helper functions
│   ├── cursor-rules.ts      # Cursor rules adapter
│   ├── cursor-commands.ts   # Cursor commands adapter
│   ├── cursor-skills.ts     # Cursor skills adapter
│   ├── cursor-agents.ts     # Cursor agents adapter
│   ├── copilot-instructions.ts # Copilot instructions adapter
│   ├── claude-skills.ts     # Claude skills adapter
│   ├── claude-agents.ts     # Claude agents adapter
│   ├── claude-rules.ts      # Claude rules adapter (.claude/rules/)
│   ├── claude-md.ts         # Claude CLAUDE.md adapter (.claude/, global mode)
│   ├── trae-rules.ts        # Trae rules adapter
│   ├── trae-skills.ts       # Trae skills adapter
│   ├── opencode-agents.ts   # OpenCode agents adapter (file mode)
│   ├── opencode-skills.ts   # OpenCode skills adapter (directory mode)
│   ├── opencode-commands.ts # OpenCode commands adapter (file mode)
│   ├── opencode-tools.ts    # OpenCode tools adapter (file mode)
│   ├── codex-rules.ts       # Codex rules adapter (file mode)
│   ├── codex-skills.ts      # Codex skills adapter (directory mode)
│   ├── gemini-commands.ts   # Gemini CLI commands adapter (file mode)
│   ├── gemini-skills.ts     # Gemini CLI skills adapter (directory mode)
│   ├── gemini-agents.ts     # Gemini CLI agents adapter (file mode)
│   ├── windsurf-rules.ts    # Windsurf rules adapter (file mode)
│   ├── windsurf-skills.ts   # Windsurf skills adapter (directory mode)
│   ├── cline-rules.ts       # Cline rules adapter (file mode)
│   ├── cline-skills.ts      # Cline skills adapter (directory mode)
│   └── agents-md.ts         # Universal AGENTS.md adapter (file mode)
├── cli/                     # CLI registration layer
│   └── register.ts          # Declarative command registration (registerAdapterCommands)
├── commands/                # Command handlers
│   ├── handlers.ts          # Generic add/remove/import handlers
│   ├── helpers.ts           # Helper functions (getTargetRepo, parseConfigEntry, etc.)
│   ├── install.ts           # Generic install function
│   ├── add-all.ts           # Discover and install all entries from repository
│   ├── lifecycle.ts         # check/update/init lifecycle commands
│   └── index.ts             # Module exports
├── completion/              # Shell completion
│   └── scripts.ts           # Shell completion scripts (bash, zsh, fish)
├── config.ts                # Global config management
├── git.ts                   # Git operations
├── index.ts                 # CLI entry point (~560 lines)
├── link.ts                  # Re-exports from sync-engine
├── project-config.ts        # Project config management
├── sync-engine.ts           # Core linkEntry/unlinkEntry/importEntry functions
└── utils.ts                 # Utility functions

Additional root-level tooling:

  • docs/supported-tools.json - Single source of truth for Supported Tools table rows
  • scripts/sync-supported-tools.mjs - Regenerates README/README_ZH tool matrix from manifest

Adapter System

The sync engine uses a plugin-based architecture with unified operations:

SyncAdapter Interface:

interface SyncAdapter {
  // Core properties
  name: string;           // e.g. "cursor-rules"
  tool: string;           // e.g. "cursor"
  subtype: string;        // e.g. "rules", "commands"
  configPath: [string, string]; // e.g. ['cursor', 'rules']
  defaultSourceDir: string; // e.g. ".cursor/rules"
  targetDir: string;      // e.g. ".cursor/rules"
  mode: 'directory' | 'file' | 'hybrid';  // NEW: hybrid supports both
  fileSuffixes?: string[];                // For file mode
  hybridFileSuffixes?: string[];          // NEW: For hybrid mode

  // Optional resolution hooks
  resolveSource?(...): Promise<ResolvedSource>;
  resolveTargetName?(...): string;

  // Unified operations (provided by createBaseAdapter)
  addDependency(projectPath, name, repoUrl, alias?, isLocal?): Promise<void>;
  removeDependency(projectPath, alias): Promise<{removedFrom}>;
  link(options): Promise<LinkResult>;
  unlink(projectPath, alias): Promise<void>;
}

Key Benefits:

  • Unified Interface: All adapters provide the same add/remove/link/unlink operations
  • No Hardcoding: configPath allows generic functions to work with any adapter
  • Automatic Routing: findAdapterForAlias() finds the right adapter based on where alias is configured
  • Reduced Duplication: Single generic handler for all add/remove/install/import operations

Adapter Modes:

  • directory: Links entire directories (skills, agents)
  • file: Links individual files with suffix resolution (commands)
  • hybrid: Links both files and directories (cursor-rules with .mdc/.md support)

Helper Functions (base.ts):

// For single-suffix file adapters (e.g., cursor-commands, trae-rules)
createSingleSuffixResolver(suffix: string, entityName: string)

// For hybrid adapters supporting multiple suffixes (e.g., cursor-rules)
createMultiSuffixResolver(suffixes: string[], entityName: string)

// Ensures target name has proper suffix
createSuffixAwareTargetResolver(suffixes: string[])

Example Simplified Adapter (cursor-commands.ts):

export const cursorCommandsAdapter = createBaseAdapter({
  name: 'cursor-commands',
  tool: 'cursor',
  subtype: 'commands',
  configPath: ['cursor', 'commands'],
  defaultSourceDir: '.cursor/commands',
  targetDir: '.cursor/commands',
  mode: 'file',
  fileSuffixes: ['.md'],
  resolveSource: createSingleSuffixResolver('.md', 'Command'),
  resolveTargetName: createSuffixAwareTargetResolver(['.md'])
});

Modular CLI Architecture

The CLI uses a declarative registration approach:

Declarative Command Registration (src/cli/register.ts):

interface RegisterCommandsOptions {
  adapter: SyncAdapter;
  parentCommand: Command;
  programOpts: () => { target?: string };
}

function registerAdapterCommands(options: RegisterCommandsOptions): void {
  // Automatically registers: add, remove, install, import subcommands
}

Generic Command Handlers (src/commands/handlers.ts):

// All handlers work with any adapter
async function handleAdd(adapter, ctx, name, alias?): Promise<AddResult>
async function handleRemove(adapter, projectPath, alias, isUser?, options?): Promise<RemoveResult>
async function handleImport(adapter, ctx, name, options): Promise<void>

Generic Install Function (src/commands/install.ts):

// Replaces 7 duplicate install functions with one generic function
async function installEntriesForAdapter(adapter, projectPath): Promise<void>
async function installEntriesForTool(adapters[], projectPath): Promise<void>

Repository Lifecycle Commands (src/commands/lifecycle.ts):

  • checkRepositories(options): collects repo URLs from project/user config and compares local HEAD vs upstream (ahead/behind) using git fetch + git rev-list.
  • updateRepositories(options): updates repos (git pull via cloneOrUpdateRepo) and reapplies links from config.
  • initRulesRepository(options): scaffolds ai-rules-sync.json with adapter-driven sourceDir defaults and creates default source directories. Supports --only <tools...> and --exclude <tools...> to selectively initialize specific tools.

Helper Functions (src/commands/helpers.ts):

  • getTargetRepo(options): Resolve target repository from options or config
  • inferDefaultMode(projectPath): Auto-detect cursor/copilot mode from config
  • parseConfigEntry(key, value): Parse config entry to extract repoUrl, entryName, alias
  • resolveCopilotAliasFromConfig(input, keys): Resolve copilot alias with suffix handling

Sync Engine Functions

src/sync-engine.ts:

// Link from repo to project
async function linkEntry(adapter, options): Promise<LinkResult>

// Unlink from project
async function unlinkEntry(adapter, projectPath, alias): Promise<void>

// Import from project to repo (copy, commit, then create symlink)
async function importEntry(adapter, options): Promise<{imported, sourceName, targetName}>

Configuration Interfaces

SourceDirConfig (for rules repos):

interface SourceDirConfig {
  cursor?: {
    rules?: string;       // Default: ".cursor/rules"
    commands?: string;    // Default: ".cursor/commands"
    skills?: string;      // Default: ".cursor/skills"
    agents?: string;      // Default: ".cursor/agents"
  };
  copilot?: {
    instructions?: string; // Default: ".github/instructions"
  };
  claude?: {
    skills?: string;      // Default: ".claude/skills"
    agents?: string;      // Default: ".claude/agents"
    rules?: string;       // Default: ".claude/rules"
    md?: string;          // Default: ".claude"
  };
  trae?: {
    rules?: string;       // Default: ".trae/rules"
    skills?: string;      // Default: ".trae/skills"
  };
  opencode?: {
    agents?: string;      // Default: ".opencode/agents"
    skills?: string;      // Default: ".opencode/skills"
    commands?: string;    // Default: ".opencode/commands"
    tools?: string;       // Default: ".opencode/tools"
  };
  codex?: {
    rules?: string;       // Default: ".codex/rules"
    skills?: string;      // Default: ".agents/skills"
  };
  gemini?: {
    commands?: string;    // Default: ".gemini/commands"
    skills?: string;      // Default: ".gemini/skills"
    agents?: string;      // Default: ".gemini/agents"
  };
  warp?: {
    skills?: string;      // Default: ".agents/skills"
  };
  windsurf?: {
    rules?: string;       // Default: ".windsurf/rules"
    skills?: string;      // Default: ".windsurf/skills"
  };
  cline?: {
    rules?: string;       // Default: ".clinerules"
    skills?: string;      // Default: ".cline/skills"
  };
  agentsMd?: {
    file?: string;        // Default: "." (repository root)
  };
}

ProjectConfig (unified configuration):

interface ProjectConfig {
  // For rules repos: global path prefix
  rootPath?: string;
  // For rules repos: source directory configuration
  sourceDir?: SourceDirConfig;
  // For projects: dependency records
  cursor?: {
    rules?: Record<string, RuleEntry>;
    commands?: Record<string, RuleEntry>;
    skills?: Record<string, RuleEntry>;
    agents?: Record<string, RuleEntry>;
  };
  copilot?: {
    instructions?: Record<string, RuleEntry>;
  };
  claude?: {
    skills?: Record<string, RuleEntry>;
    agents?: Record<string, RuleEntry>;
    rules?: Record<string, RuleEntry>;
    md?: Record<string, RuleEntry>;
  };
  trae?: {
    rules?: Record<string, RuleEntry>;
    skills?: Record<string, RuleEntry>;
  };
  opencode?: {
    agents?: Record<string, RuleEntry>;
    skills?: Record<string, RuleEntry>;
    commands?: Record<string, RuleEntry>;
    tools?: Record<string, RuleEntry>;
  };
  codex?: {
    rules?: Record<string, RuleEntry>;
    skills?: Record<string, RuleEntry>;
  };
  gemini?: {
    commands?: Record<string, RuleEntry>;
    skills?: Record<string, RuleEntry>;
    agents?: Record<string, RuleEntry>;
  };
  warp?: {
    skills?: Record<string, RuleEntry>;
  };
  windsurf?: {
    rules?: Record<string, RuleEntry>;
    skills?: Record<string, RuleEntry>;
  };
  cline?: {
    rules?: Record<string, RuleEntry>;
    skills?: Record<string, RuleEntry>;
  };
  // Universal AGENTS.md support (tool-agnostic)
  agentsMd?: Record<string, RuleEntry>;
}

Helper Functions

  • getAdapter(tool, subtype): Get adapter by tool/subtype, throws if not found
  • getDefaultAdapter(tool): Get the first adapter for a tool
  • getToolAdapters(tool): Get all adapters for a tool
  • findAdapterForAlias(config, alias): Find which adapter manages a specific alias
  • addDependencyGeneric(projectPath, configPath, name, repoUrl, alias?, isLocal?): Generic dependency add
  • removeDependencyGeneric(projectPath, configPath, alias): Generic dependency remove

Feature Summary

1. Repository Management

  • Use: ais use <url|name> - Configure or switch the active rules repository.
  • List: ais ls (alias: ais list) - Show configured repositories and the active one.
  • Status: ais status - Show repository availability and project config summary.
  • Search: ais search [query] - Search available entries in the current repository.
  • Git Proxy: ais git <args...> - Run git commands directly in the active rules repository context.
  • Script-friendly output: Query commands support --json (list/ls, status, search, config repo list/ls, config repo show).
  • Safe previews: --dry-run supported for destructive commands (remove/rm, import).

2. Cursor Rule Synchronization

  • Syntax: ais cursor add <rule_name> [alias] or ais cursor rules add <rule_name> [alias]
  • Links <repo>/.cursor/rules/<rule_name> to .cursor/rules/<alias>.
  • Mode: Hybrid - supports both files (.mdc, .md) and directories.
  • Options: -t <repo>, --local (-l)

3. Cursor Command Synchronization

  • Syntax: ais cursor commands add <command_name> [alias]
  • Links <repo>/.cursor/commands/<command_name> to .cursor/commands/<alias>.
  • Supports .md files.

4. Copilot Instruction Synchronization

  • Syntax: ais copilot add <name> [alias]
  • Links <repo>/.github/instructions/<name> to .github/instructions/<alias>.
  • Supports .md and .instructions.md suffixes with conflict detection.

5. Cursor Skill Synchronization

  • Syntax: ais cursor skills add <skillName> [alias]
  • Links <repo>/.cursor/skills/<skillName> to .cursor/skills/<alias>.
  • Directory-based synchronization.

6. Cursor Agent Synchronization

  • Syntax: ais cursor agents add <agentName> [alias]
  • Links <repo>/.cursor/agents/<agentName> to .cursor/agents/<alias>.
  • Directory-based synchronization for Cursor subagents (Markdown files with YAML frontmatter).

7. Claude Code Skill Synchronization

  • Syntax: ais claude skills add <skillName> [alias]
  • Links <repo>/.claude/skills/<skillName> to .claude/skills/<alias>.
  • Directory-based synchronization.

8. Claude Code Subagent Synchronization

  • Syntax: ais claude agents add <agentName> [alias]
  • Links <repo>/.claude/agents/<agentName> to .claude/agents/<alias>.
  • Directory-based synchronization.

8b. Claude Code Rule Synchronization

  • Syntax: ais claude rules add <ruleName> [alias]
  • Links <repo>/.claude/rules/<ruleName> to .claude/rules/<alias>.
  • File-based synchronization for Claude Code project rules.
  • Supports .md suffix.

8c. Claude Code CLAUDE.md Synchronization

  • Syntax: ais claude md add <name> [alias]
  • Links <repo>/.claude/<name>.md to .claude/<name>.md.
  • File-based synchronization for CLAUDE.md-style configuration files.
  • Supports .md suffix; resolves CLAUDECLAUDE.md automatically.
  • User Mode: ais claude md add CLAUDE --user links to ~/.claude/CLAUDE.md.
  • sourceDir object format: Use common/AGENTS.md as CLAUDE.md source (one file, multiple targets):
    { "sourceDir": { "claude": { "md": { "dir": "common", "sourceFile": "AGENTS.md", "targetFile": "CLAUDE.md" } } } }
    Enables syncing the same file to both AGENTS.md (via agentsMd) and CLAUDE.md (via claude-md).

9. Trae Rule Synchronization

  • Syntax: ais trae rules add <ruleName> [alias]
  • Links <repo>/.trae/rules/<ruleName> to .trae/rules/<alias>.
  • File-based synchronization for Trae AI rules.

10. Trae Skill Synchronization

  • Syntax: ais trae skills add <skillName> [alias]
  • Links <repo>/.trae/skills/<skillName> to .trae/skills/<alias>.
  • Directory-based synchronization for Trae AI skills.

11. Universal AGENTS.md Synchronization

  • Syntax: ais agents-md add <name> [alias]
  • Links AGENTS.md from repository to AGENTS.md (project root).
  • Tool-agnostic: Follows the agents.md standard making agent definitions available to any AI coding tool that supports this format.
  • Flexible path resolution supports multiple patterns:
    • Root level: ., AGENTS, AGENTS.mdrepo/AGENTS.md
    • Directory: frontendrepo/frontend/AGENTS.md
    • Nested path: docs/teamrepo/docs/team/AGENTS.md
    • Explicit file: backend/AGENTS.mdrepo/backend/AGENTS.md
  • File-based synchronization with .md suffix.
  • Config structure: Uses flat agentsMd record (not nested like other tools)

12. OpenCode Synchronization

OpenCode AI is supported with four different entry types:

12.1. OpenCode Agent Synchronization

  • Syntax: ais opencode agents add <agentName> [alias]
  • Links <repo>/.opencode/agents/<agentName> to .opencode/agents/<alias>.
  • File-based synchronization with .md suffix for OpenCode AI agents.

12.2. OpenCode Skill Synchronization

  • Syntax: ais opencode skills add <skillName> [alias]
  • Links <repo>/.opencode/skills/<skillName> to .opencode/skills/<alias>.
  • Directory-based synchronization for OpenCode AI skills (SKILL.md inside).

12.3. OpenCode Command Synchronization

  • Syntax: ais opencode commands add <commandName> [alias]
  • Links <repo>/.opencode/commands/<commandName> to .opencode/commands/<alias>.
  • File-based synchronization with .md suffix for OpenCode AI commands.

12.4. OpenCode Tools Synchronization

  • Syntax: ais opencode tools add <toolName> [alias]
  • Links <repo>/.opencode/tools/<toolName> to .opencode/tools/<alias>.
  • File-based synchronization with .ts/.js suffixes for OpenCode AI tools.

13. Codex Synchronization

OpenAI Codex is supported with two entry types:

13.1. Codex Rule Synchronization

  • Syntax: ais codex rules add <ruleName> [alias]
  • Links <repo>/.codex/rules/<ruleName> to .codex/rules/<alias>.
  • File-based synchronization with .rules suffix for Codex rules (Starlark syntax).
  • Purpose: Control which commands can run outside sandbox.

13.2. Codex Skill Synchronization

  • Syntax: ais codex skills add <skillName> [alias]
  • Links <repo>/.agents/skills/<skillName> to .agents/skills/<alias>.
  • Directory-based synchronization for Codex skills (SKILL.md inside).
  • Note: Uses non-standard .agents/skills directory (not .codex/skills) per Codex documentation.

14. Gemini CLI Synchronization

Gemini CLI (https://geminicli.com/) is supported with three entry types:

14.1. Gemini Command Synchronization

  • Syntax: ais gemini commands add <commandName> [alias]
  • Links <repo>/.gemini/commands/<commandName> to .gemini/commands/<alias>.
  • File-based synchronization with .toml suffix for Gemini CLI commands.
  • Purpose: Reusable prompts with argument substitution.

14.2. Gemini Skill Synchronization

  • Syntax: ais gemini skills add <skillName> [alias]
  • Links <repo>/.gemini/skills/<skillName> to .gemini/skills/<alias>.
  • Directory-based synchronization for Gemini CLI skills (SKILL.md inside).
  • Purpose: Specialized expertise for specific tasks.

14.3. Gemini Subagent Synchronization

  • Syntax: ais gemini agents add <agentName> [alias]
  • Links <repo>/.gemini/agents/<agentName> to .gemini/agents/<alias>.
  • File-based synchronization with .md suffix for Gemini CLI subagents (Markdown with YAML frontmatter).
  • Purpose: Specialized subagents with defined capabilities.

14.4. Windsurf Rule Synchronization

  • Syntax: ais windsurf add <ruleName> [alias]
  • Links <repo>/.windsurf/rules/<ruleName> to .windsurf/rules/<alias>.
  • File-based synchronization with .md suffix for Windsurf workspace rules.

14.5. Windsurf Skill Synchronization

  • Syntax: ais windsurf skills add <skillName> [alias]
  • Links <repo>/.windsurf/skills/<skillName> to .windsurf/skills/<alias>.
  • Directory-based synchronization for Windsurf Cascade skills (SKILL.md inside each skill folder).

14.6. Cline Rule Synchronization

  • Syntax: ais cline add <ruleName> [alias]
  • Links <repo>/.clinerules/<ruleName> to .clinerules/<alias>.
  • File-based synchronization with .md/.txt suffixes for Cline rules.

14.7. Cline Skill Synchronization

  • Syntax: ais cline skills add <skillName> [alias]
  • Links <repo>/.cline/skills/<skillName> to .cline/skills/<alias>.
  • Directory-based synchronization for Cline skills (SKILL.md inside each skill folder).

15. Import Command

  • Syntax: ais import <tool> <subtype> <name> or ais <tool> <subtype> import <name>
  • Copies entry from project to rules repository, commits, and creates symlink back.
  • Options:
    • -m, --message <message>: Custom commit message
    • -f, --force: Overwrite if entry exists in repo
    • -p, --push: Push to remote after commit
    • -l, --local: Add to local config
  • Examples:
    ais import cursor rules my-rule
    ais cursor rules import my-rule --push
    ais import copilot instructions my-instruction -m "Add new instruction"

16. Installation

  • ais cursor install - Install all Cursor rules, commands, skills, and agents.
  • ais copilot install - Install all Copilot instructions.
  • ais claude install - Install all Claude Code skills, agents, rules, and CLAUDE.md files.
  • ais trae install - Install all Trae rules and skills.
  • ais opencode install - Install all OpenCode agents, skills, commands, and tools.
  • ais codex install - Install all Codex rules and skills.
  • ais gemini install - Install all Gemini CLI commands, skills, and subagents.
  • ais windsurf install - Install all Windsurf rules and skills.
  • ais cline install - Install all Cline rules and skills.
  • ais agents-md install - Install AGENTS.md files.
  • ais install - Install everything (smart dispatch).
  • ais install --user / ais user install - Install all user-scope AI config files from ~/.config/ai-rules-sync/user.json.

17. Bulk Discovery and Installation (add-all)

The add-all command automatically discovers and installs all available entries from the rules repository by scanning the filesystem, unlike install which reads from config files.

Core Implementation (src/commands/add-all.ts):

  • discoverEntriesForAdapter() - Scans repository directory for a single adapter
  • discoverAllEntries() - Discovers across all/filtered adapters
  • installDiscoveredEntries() - Batch installs discovered entries
  • handleAddAll() - Main orchestrator

Command Hierarchy:

  • Top-level: ais add-all - All tools, supports --tools and --adapters filters
  • Tool-level: ais cursor add-all, ais copilot add-all, etc. - Filters to specific tool
  • Subtype-level: ais cursor rules add-all, ais cursor commands add-all, etc. - Filters to specific adapter

Discovery Algorithm:

  1. Get source directory from repo config using getRepoSourceConfig() and getSourceDir()
  2. Scan filesystem with fs.readdir() filtering hidden files (starting with .)
  3. Apply adapter mode filters:
    • file mode: Include files matching fileSuffixes (e.g., .md)
    • directory mode: Include only directories
    • hybrid mode: Include files matching hybridFileSuffixes AND directories
  4. Extract entry names by stripping suffixes for files
  5. Check existing config to mark already-configured entries

Options:

  • --dry-run - Preview without making changes
  • --force - Overwrite existing entries (re-link and update config)
  • --interactive - Prompt for each entry using readline
  • --local - Store in ai-rules-sync.local.json
  • --skip-existing - Skip entries already in config (default behavior)
  • --quiet - Minimal output
  • --tools <tools> - Filter by comma-separated tool names (top-level only)
  • --adapters <adapters> - Filter by comma-separated adapter names (top-level only)

Examples:

# Preview all Cursor rules
ais cursor rules add-all --dry-run

# Install all Cursor entries (rules, commands, skills, agents)
ais cursor add-all

# Install all entries from all tools
ais add-all

# Install only from specific tools
ais add-all --tools cursor,copilot

# Interactive confirmation
ais cursor add-all --interactive

# Install as private entries
ais cursor rules add-all --local

Output Format:

Discovering entries from repository...
  cursor-rules: 5 entries
  cursor-commands: 3 entries
Total: 8 entries discovered

Installing entries:
[1/8] cursor-rules/react → .cursor/rules/react ✓
[2/8] cursor-rules/testing → .cursor/rules/testing ✓
[3/8] cursor-commands/deploy → .cursor/commands/deploy ⊘ (already configured)
...

Summary:
  Installed: 7
  Skipped: 1 (already configured)
  Errors: 0

Integration:

  • Uses existing adapter system and addDependency()/link() methods
  • Works with all adapter modes (file/directory/hybrid)
  • Respects repository source directory configuration
  • Compatible with ais install (discovered entries are added to config)

18. Custom Source Directories for Third-Party Repositories

Problem: Third-party rules repositories may not have ai-rules-sync.json or use non-standard directory structures (e.g., rules/cursor/ instead of .cursor/rules).

Solution: 4-layer priority system for custom source directory configuration:

CLI Parameters > Global Config > Repository Config > Adapter Defaults

Implementation (src/cli/source-dir-parser.ts, src/commands/config.ts):

  • CLI parameter parsing with context-aware simple format and explicit dot notation
  • Global config persistence in ~/.config/ai-rules-sync/config.json
  • Enhanced getSourceDir() with globalOverride parameter
  • Config management commands for persistent configuration

CLI Parameter Formats:

# Simple format (context-aware - when tool/subtype is clear)
ais cursor rules add-all -s custom/rules
ais cursor add-all -s rules=custom/rules -s commands=custom/cmds

# Dot notation (explicit - requires full tool.subtype)
ais add-all -s cursor.rules=custom/rules -s cursor.commands=custom/cmds

# Multiple overrides (can repeat -s flag)
ais add-all \
  -s cursor.rules=rules/cursor \
  -s cursor.commands=commands \
  -s claude.skills=claude/skills

Global Configuration Commands:

# Set custom source directory (persistent)
ais config repo set-source <repoName> <tool.subtype> <path>
ais config repo set-source third-party cursor.rules custom/rules

# View repository configuration
ais config repo show <repoName>

# Clear source directory
ais config repo clear-source <repoName> [tool.subtype]

# List all repositories
ais config repo list

Configuration Structure:

// Global config (~/.config/ai-rules-sync/config.json)
{
  "currentRepo": "third-party-rules",
  "repos": {
    "third-party-rules": {
      "name": "third-party-rules",
      "url": "https://github.com/someone/rules",
      "path": "/Users/user/.config/ai-rules-sync/repos/third-party-rules",
      "sourceDir": {
        "cursor": {
          "rules": "rules/cursor",
          "commands": "commands/cursor"
        },
        "claude": {
          "skills": "claude/skills"
        }
      }
    }
  }
}

sourceDir value formats:

  • String (legacy): "claude": { "md": ".claude" } — source directory path
  • Object (file mode): "claude": { "md": { "dir": "common", "sourceFile": "AGENTS.md", "targetFile": "CLAUDE.md" } } — use a different source file and target filename (e.g. map common/AGENTS.md.claude/CLAUDE.md)
  • Object (directory mode): "cursor": { "rules": { "dir": "common", "sourceDir": "shared-rules", "targetName": "cursor-rules" } } — use a different source subdirectory and target symlink name (e.g. map common/shared-rules.cursor/rules/cursor-rules)

Wildcard (*) fallback:

  • Use * as tool key to define shared config when tool-specific config is missing
  • Example: "*": { "skills": "common/skills" } — cursor.skills, copilot.skills, etc. all resolve to common/skills when not explicitly defined
  • Applies to both sourceDir (rules repo) and dependency records (project config)
  • Tool-specific config takes precedence; remove falls back to * when entry is in wildcard config

Priority Resolution in getSourceDir():

  1. CLI override (highest priority) - -s parameter, no rootPath prefix
  2. Global config - From RepoConfig.sourceDir, no rootPath prefix
  3. Repository config - From repo's ai-rules-sync.json, with rootPath prefix
  4. Adapter default (lowest priority) - Hardcoded in adapter definition

Use Cases:

  • One-time exploration: Use CLI parameter to test repositories
  • Regular use: Configure once with config repo set-source, use normally
  • Override: CLI parameter overrides even global config

add-all Integration:

All add-all commands support -s/--source-dir option:

  • Top-level: ais add-all -s tool.subtype=path
  • Tool-level: ais cursor add-all -s rules=path
  • Subtype-level: ais cursor rules add-all -s custom/rules

Files Involved:

  • src/config.ts - Extended RepoConfig with sourceDir field
  • src/project-config.ts - Enhanced getSourceDir() with 4-layer priority
  • src/commands/add-all.ts - Added sourceDirOverrides parameter
  • src/cli/source-dir-parser.ts - Parameter parsing logic
  • src/commands/config.ts - Config management commands
  • src/cli/register.ts - Added -s option to adapter commands
  • src/index.ts - Added -s option and config commands

Example Workflow:

# Discover what a third-party repo has (preview)
ais cursor rules add-all -s custom/rules --dry-run

# Configure for regular use
ais config repo set-source my-third-party cursor.rules custom/rules
ais config repo set-source my-third-party cursor.commands custom/commands

# Use normally (sourceDir automatically applied)
ais cursor add-all

# Override temporarily
ais cursor rules add-all -s experimental/rules

19. User Mode (Personal AI Config Files)

User Mode allows managing personal AI config files (~/.claude/CLAUDE.md, ~/.cursor/rules/, etc.) with version control and cross-machine sync. Aligns with Claude Code's official terminology: user scope = ~/.claude/, project scope = .claude/.

How it works:

  • --user / -u flag sets projectPath = $HOME and stores dependencies in ~/.config/ai-rules-sync/user.json instead of a project's ai-rules-sync.json
  • Gitignore management is skipped automatically (home dir is not a git repo)
  • Symlinks are created at absolute paths (e.g., ~/.claude/CLAUDE.md)

Commands:

# Add entries to user config
ais claude md add CLAUDE --user       # ~/.claude/CLAUDE.md
ais cursor rules add my-style --user  # ~/.cursor/rules/my-style.mdc
ais claude rules add general --user   # ~/.claude/rules/general.md

# Install all user entries (restore on new machine)
ais user install
ais install --user   # equivalent

# Remove from user config
ais claude md remove CLAUDE --user

User Config Path Management: By default, user-scope dependencies are stored in ~/.config/ai-rules-sync/user.json. For dotfiles integration (to track user.json in git), the path can be customized:

# View current user config path
ais config user show

# Set custom path (e.g., inside dotfiles git repo)
ais config user set ~/dotfiles/ai-rules-sync/user.json

# Reset to default
ais config user reset

Multi-machine Workflow:

# Machine A: initial setup
ais use git@github.com:me/my-rules.git
ais config user set ~/dotfiles/ai-rules-sync/user.json
ais claude md add CLAUDE --user
ais cursor rules add my-style --user

# Machine B: restore all user-scope symlinks
ais use git@github.com:me/my-rules.git
ais config user set ~/dotfiles/ai-rules-sync/user.json  # if using dotfiles
ais user install

user.json format — same as ai-rules-sync.json:

{
  "claude": {
    "md": { "CLAUDE": "https://github.com/me/my-rules.git" },
    "rules": { "general": "https://github.com/me/my-rules.git" }
  },
  "cursor": {
    "rules": { "my-style": "https://github.com/me/my-rules.git" }
  }
}

Migration: On first use after upgrading, AIS automatically renames global.jsonuser.json and globalConfigPathuserConfigPath in config.json.

Config Fields:

  • Config.userConfigPath?: string - Custom path for user.json (stored in config.json; replaces deprecated globalConfigPath)
  • SyncOptions.skipIgnore?: boolean - Skip gitignore management (set automatically in user mode)

Functions:

  • getUserConfigPath() - Returns custom or default user.json path (replaces getGlobalConfigPath())
  • getUserProjectConfig() - Reads user.json as ProjectConfig (replaces getGlobalProjectConfig())
  • saveUserProjectConfig() - Writes to user.json (replaces saveGlobalProjectConfig())
  • addUserDependency() - Adds entry to user.json (in project-config.ts; replaces addGlobalDependency())
  • removeUserDependency() - Removes entry from user.json (in project-config.ts; replaces removeGlobalDependency())
  • installUserEntriesForAdapter() - Installs all user entries for one adapter (replaces installGlobalEntriesForAdapter())
  • installAllUserEntries() - Installs user entries for all adapters (replaces installAllGlobalEntries())

20. Configuration Files

Rules Repository Config (ai-rules-sync.json in the rules repo):

{
  "rootPath": "src",
  "sourceDir": {
    "cursor": {
      "rules": ".cursor/rules",
      "commands": ".cursor/commands",
      "skills": ".cursor/skills",
      "agents": ".cursor/agents"
    },
    "copilot": {
      "instructions": ".github/instructions"
    },
    "claude": {
      "skills": ".claude/skills",
      "agents": ".claude/agents",
      "rules": ".claude/rules",
      "md": ".claude"
    },
    "trae": {
      "rules": ".trae/rules",
      "skills": ".trae/skills"
    },
    "opencode": {
      "agents": ".opencode/agents",
      "skills": ".opencode/skills",
      "commands": ".opencode/commands",
      "tools": ".opencode/tools"
    },
    "codex": {
      "rules": ".codex/rules",
      "skills": ".agents/skills"
    },
    "gemini": {
      "commands": ".gemini/commands",
      "skills": ".gemini/skills",
      "agents": ".gemini/agents"
    },
    "agentsMd": {
      "file": "."
    }
  }
}

Project Config (ai-rules-sync.json in user projects):

{
  "cursor": {
    "rules": { "react": "https://..." },
    "commands": { "deploy-docs": "https://..." },
    "skills": { "code-review": "https://..." },
    "agents": { "code-analyzer": "https://..." }
  },
  "copilot": {
    "instructions": { "general": "https://..." }
  },
  "claude": {
    "skills": { "my-skill": "https://..." },
    "agents": { "debugger": "https://..." },
    "rules": { "general": "https://..." },
    "md": { "CLAUDE": "https://..." }
  },
  "trae": {
    "rules": { "project-rules": "https://..." },
    "skills": { "new-adapter": "https://..." }
  },
  "opencode": {
    "agents": { "code-reviewer": "https://..." },
    "skills": { "refactor-helper": "https://..." },
    "commands": { "build-optimizer": "https://..." },
    "tools": { "project-analyzer": "https://..." }
  },
  "codex": {
    "rules": { "sandbox-rules": "https://..." },
    "skills": { "code-assistant": "https://..." }
  },
  "gemini": {
    "commands": { "deploy-command": "https://..." },
    "skills": { "code-review-skill": "https://..." },
    "agents": { "refactor-agent": "https://..." }
  },
  "agentsMd": {
    "root": {
      "url": "https://...",
      "rule": "AGENTS.md"
    },
    "frontend": {
      "url": "https://...",
      "rule": "frontend/AGENTS.md"
    }
  }
}
  • ai-rules-sync.local.json: Private dependencies (merged, takes precedence).
  • Config files: Only ai-rules-sync.json and ai-rules-sync.local.json are supported.

21. Shell Completion

  • Auto-Install: On first run, AIS prompts to install shell completion automatically.
  • Manual Install: ais completion install - Installs completion to shell config file.
  • Script Output: ais completion [bash|zsh|fish] - Outputs raw completion script.
  • Detection: Automatically detects shell type from $SHELL environment variable.
  • Generation Model: Completion scripts are generated from shared metadata in src/completion/scripts.ts (bash/zsh/fish stay in sync).

22. Supported Tools Documentation Generation

  • Single Source: Supported tools matrix is defined in docs/supported-tools.json.
  • Sync Command: npm run docs:sync-tools regenerates table blocks in both README.md and README_ZH.md.
  • Update Boundaries: Table content is replaced between <!-- SUPPORTED_TOOLS_TABLE:START --> and <!-- SUPPORTED_TOOLS_TABLE:END -->.

Adapter Reference Table

Adapter Tool Subtype Mode Source Dir File Suffixes Reference
cursor-rules cursor rules hybrid .cursor/rules .mdc, .md Cursor Rules
cursor-commands cursor commands file .cursor/commands .md Cursor Commands
cursor-skills cursor skills directory .cursor/skills - Cursor Skills
cursor-agents cursor subagents directory .cursor/agents - Cursor subagents
copilot-instructions copilot instructions file .github/instructions .instructions.md, .md Copilot Instructions
claude-skills claude skills directory .claude/skills - Claude Code Skills
claude-agents claude subagents directory .claude/agents - Claude Code Subagents
Adapter Tool Subtype Mode Source Dir Target Dir (project) User-level Target
--------- ------ --------- ------ ------------ ---------------------- -------------------
cursor-rules cursor rules hybrid .cursor/rules .cursor/rules -
cursor-commands cursor commands file .cursor/commands .cursor/commands -
cursor-skills cursor skills directory .cursor/skills .cursor/skills -
cursor-agents cursor subagents directory .cursor/agents .cursor/agents -
copilot-instructions copilot instructions file .github/instructions .github/instructions -
claude-skills claude skills directory .claude/skills .claude/skills -
claude-agents claude subagents directory .claude/agents .claude/agents -
claude-rules claude rules file .claude/rules .claude/rules -
claude-md claude md file .claude .claude -
trae-rules trae rules file .trae/rules .trae/rules -
trae-skills trae skills directory .trae/skills .trae/skills -
agents-md agents-md file file . (root) . -
opencode-agents opencode agents file .opencode/agents .opencode/agents .config/opencode/agents
opencode-skills opencode skills directory .opencode/skills .opencode/skills .config/opencode/skills
opencode-commands opencode commands file .opencode/commands .opencode/commands .config/opencode/commands
opencode-tools opencode tools file .opencode/tools .opencode/tools .config/opencode/tools
codex-rules codex rules file .codex/rules .codex/rules -
codex-skills codex skills directory .agents/skills .agents/skills -
codex-md codex md file .codex .codex -
gemini-commands gemini commands file .gemini/commands .gemini/commands -
gemini-skills gemini skills directory .gemini/skills .gemini/skills -
gemini-agents gemini agents file .gemini/agents .gemini/agents -
gemini-md gemini md file .gemini .gemini -
windsurf-rules windsurf rules file .windsurf/rules .windsurf/rules -
windsurf-skills windsurf skills directory .windsurf/skills .windsurf/skills -
cline-rules cline rules file .clinerules .clinerules -
cline-skills cline skills directory .cline/skills .cline/skills -

User-level Target column: When --user is used, symlinks land at ~/<userTargetDir> instead of ~/<targetDir>. A - means the tool has no dedicated XDG/user path — user mode just uses ~/<targetDir> (which for claude-md means ~/.claude/CLAUDE.md, for gemini-md means ~/.gemini/GEMINI.md, etc.).

Development Guidelines

  • TypeScript: Strict mode enabled.
  • Testing: Vitest for unit tests.
  • Style: Functional programming style preferred.
  • Adding New AI Tools:
    1. Create adapter in src/adapters/<tool>.ts (use createBaseAdapter; add userTargetDir if tool has a different XDG user-level path)
    2. Register in src/adapters/index.ts (constructor + findAdapterForAlias)
    3. Add CLI commands in src/index.ts using registerAdapterCommands()
    4. Update ProjectConfig, SourceDirConfig, RepoSourceConfig, mergeCombined, and getSourceDir in src/project-config.ts
  • userTargetDir: Set this on an adapter when the tool's official user-level filesystem path differs from its project-level path (e.g., OpenCode uses ~/.config/opencode/ not ~/.opencode/). Leave unset when ~/<targetDir> is already the correct user path.

Choosing Adapter Mode

  • Use directory mode for tools that organize entries as folders (skills, agents)
  • Use file mode for tools with single files and consistent suffix (commands with .md)
  • Use hybrid mode when entries can be either files or directories (cursor-rules)

Recent Changes

sourceDir Object Format for One-Source-Multi-Target (2026-03)

Enables using the same file (e.g. common/AGENTS.md) for both AGENTS.md and CLAUDE.md sync.

Problem Solved:

  • Rules repo had common/AGENTS.md that should sync to project root as AGENTS.md (via agentsMd) and to .claude/CLAUDE.md (via claude-md)
  • Previously required duplicate files or manual symlinks

New sourceDir Object Format (file mode):

"claude": {
  "md": { "dir": "common", "sourceFile": "AGENTS.md", "targetFile": "CLAUDE.md" }
}
  • dir: Source directory (replaces default .claude)
  • sourceFile: Filename to use as source (e.g. AGENTS.md instead of CLAUDE.md)
  • targetFile: Symlink filename in target (e.g. CLAUDE.md)

Extended for directory/hybrid mode (2026-03):

"cursor": {
  "rules": { "dir": "common", "sourceDir": "shared-rules", "targetName": "cursor-rules" }
}
  • sourceDir: Source subdirectory to use (e.g. common/shared-rules instead of common/<name>)
  • targetName: Symlink directory name in target (e.g. cursor-rules)

Implementation:

  • src/project-config.ts - Added SourceDirValue type, getSourceFileOverride(), getTargetFileOverride(), getSourceDirOverride(), getTargetNameOverride(), extended buildRepoSourceFromNestedStrings and getSourceDir() for object format
  • src/adapters/claude-md.ts - Custom resolveSource that uses sourceFileOverride when set
  • src/adapters/base.ts - createMultiSuffixResolver accepts sourceDirOverride for hybrid/directory mode
  • src/adapters/types.ts - Extended resolveSource signature with optional options.sourceFileOverride and options.sourceDirOverride
  • src/dotany/types.ts - Added targetName to ResolvedSource for target override
  • src/plugin/git-repo-source.ts - Pass overrides to resolveSource, support sourceDirOverride/targetNameOverride for directory-only adapters
  • src/sync-engine.ts - Pass overrides to adapter.resolveSource, use targetFileOverride/targetNameOverride for target name
  • src/dotany/manager.ts - Use resolved.targetName when present

Command UX Enhancements (2026-03)

  • Added Linux-style aliases while keeping backward compatibility:
    • ais listais ls
    • ais removeais rm
    • Adapter subcommands also support rm (for example ais cursor rules rm react).
  • Added query commands:
    • ais status for repository/project snapshot output
    • ais search [query] to discover available entries in the active repository
  • Added machine-readable query output with --json:
    • ais list/ls --json
    • ais status --json
    • ais search --json
    • ais config repo list/ls --json
    • ais config repo show <repo> --json
  • Added --dry-run support for destructive operations:
    • remove/rm commands
    • import commands
  • Updated shell completion metadata to include aliases and new query commands across bash/zsh/fish.

Windsurf & Cline Support (2026-02)

  • Added Windsurf support: rules (.windsurf/rules, .md) and skills (.windsurf/skills) with full CLI/completion integration
  • Added Cline support: rules (.clinerules, .md/.txt) and skills (.cline/skills) with full CLI/completion integration
  • Refactored project-config source directory resolution to table-driven logic for both legacy-string detection and getSourceDir()
  • Refactored shell completion generation to metadata-driven script builders for bash/zsh/fish
  • Added reusable adapter contract test helper (src/__tests__/helpers/adapter-contract.ts) to reduce duplicated adapter tests
  • Added single-source Supported Tools manifest (docs/supported-tools.json) and sync script (npm run docs:sync-tools) for README parity
  • Added User Mode (--user / -u): manage personal AI config files (~/.claude/CLAUDE.md, etc.) with version control; ais user install restores all symlinks on new machines
  • Added claude-md adapter: sync CLAUDE.md-style files; ais claude md add CLAUDE --user
  • Added User Config Path: ais config user set <path> for dotfiles integration
  • Added Gemini CLI support: commands (.toml), skills (directory), subagents (.md)
  • Added OpenAI Codex support: rules (.rules, Starlark), skills (.agents/skills/)
  • Standardized user-scope flags on --user / -u (legacy --global / -g aliases removed)

Proper User-Level Sync for All Tools + gemini-md / codex-md Adapters (2026-02)

Added full user-level support for Gemini CLI and Codex, fixed OpenCode XDG paths.

Problem Solved:

  • --user mode set projectPath = $HOME but used the same targetDir for all adapters — causing OpenCode user-level files to land in ~/.opencode/... instead of the official XDG path ~/.config/opencode/...
  • No adapter existed for ~/.gemini/GEMINI.md (Gemini CLI's user-level context file)
  • No adapter existed for ~/.codex/AGENTS.md (Codex CLI's user-level instructions file)
  • getSourceDir() had no branch for gemini or codex.md, returning the adapter default instead of any repo-configured path

Features Implemented:

  1. userTargetDir on Adapter Interface:

    • New optional field userTargetDir?: string on SyncAdapter and AdapterConfig
    • When options.skipIgnore === true (user mode) AND adapter has userTargetDir, sync-engine.ts uses it as the symlink destination instead of targetDir
    • OpenCode adapters now carry userTargetDir pointing to XDG paths
  2. OpenCode XDG Path Fix:

    • opencode-commands: userTargetDir = '.config/opencode/commands'~/.config/opencode/commands/
    • opencode-agents: userTargetDir = '.config/opencode/agents'~/.config/opencode/agents/
    • opencode-skills: userTargetDir = '.config/opencode/skills'~/.config/opencode/skills/
    • opencode-tools: userTargetDir = '.config/opencode/tools'~/.config/opencode/tools/
  3. gemini-md Adapter (new):

    • Manages ~/.gemini/GEMINI.md (or project-level .gemini/GEMINI.md)
    • File mode, .md suffix; resolves GEMINIGEMINI.md
    • CLI: ais gemini md [add|remove|install|import]
    • User mode: ais gemini md add GEMINI --user → symlink at ~/.gemini/GEMINI.md
  4. codex-md Adapter (new):

    • Manages ~/.codex/AGENTS.md (or project-level .codex/AGENTS.md)
    • File mode, .md suffix; resolves AGENTSAGENTS.md
    • CLI: ais codex md [add|remove|install|import]
    • User mode: ais codex md add AGENTS --user → symlink at ~/.codex/AGENTS.md
  5. Configuration Updates:

    • ProjectConfig.gemini now includes md?: Record<string, RuleEntry>
    • ProjectConfig.codex now includes md?: Record<string, RuleEntry>
    • Same additions to SourceDirConfig and RepoSourceConfig
    • mergeCombined() now merges gemini.md, codex.md, and the previously missing gemini.* fields
    • getSourceDir() now handles gemini.* (all subtypes) and codex.md
    • findAdapterForAlias() updated for gemini.md and codex.md
  6. _complete / userCmd Updates:

    • gemini-md and codex-md added to shell completion type list
    • ais user description now mentions ~/.gemini/GEMINI.md and ~/.codex/AGENTS.md

Implementation:

  • src/adapters/types.ts — Added userTargetDir?: string to SyncAdapter
  • src/adapters/base.ts — Added userTargetDir?: string to AdapterConfig, pass-through in createBaseAdapter
  • src/sync-engine.ts — Apply adapter.userTargetDir when options.skipIgnore === true
  • src/adapters/opencode-{commands,agents,skills,tools}.ts — Added userTargetDir
  • src/adapters/gemini-md.ts — New adapter
  • src/adapters/codex-md.ts — New adapter
  • src/adapters/index.ts — Registered new adapters, updated findAdapterForAlias
  • src/project-config.ts — Extended types, mergeCombined, getSourceDir
  • src/index.ts — Added ais gemini md and ais codex md subcommands

Files Changed: 9 modified + 2 new adapters, all tests passing (269/269)


User Mode & claude-md Adapter (2026-02)

Added User Mode for managing personal AI config files (~/.claude/CLAUDE.md, etc.):

Problem Solved:

  • Personal AI config files like ~/.claude/CLAUDE.md had no version control or cross-machine sync
  • Each machine required manual setup of global AI tool configurations

Features Implemented:

  1. User Mode (--user / -u flag):

    • All add/remove/install commands accept --user flag
    • Sets projectPath = $HOME automatically
    • Stores dependencies in ~/.config/ai-rules-sync/user.json
    • Skips gitignore management (home dir isn't a git repo)
  2. claude-md Adapter:

    • New adapter for CLAUDE.md-style files (.claude/<name>.md)
    • File mode with .md suffix; resolves CLAUDECLAUDE.md
    • CLI: ais claude md [add|remove|install|import]
    • User mode usage: ais claude md add CLAUDE --user
  3. One-click User Install:

    • ais user install / ais install --user
    • Reads all entries from user.json and recreates symlinks (perfect for new machine setup)
  4. User Config Path Management:

    • ais config user show - View current user.json path
    • ais config user set <path> - Set custom path (for dotfiles integration)
    • ais config user reset - Reset to default path
    • Stored as userConfigPath in ~/.config/ai-rules-sync/config.json
  5. claude-rules Adapter (formalized):

    • Adapter for .claude/rules/ files (.md suffix)
    • CLI: ais claude rules [add|remove|install|import]
  6. skipIgnore in SyncOptions:

    • New optional field prevents gitignore management in user mode
    • Set automatically when --user is used
  7. Automatic Migration:

    • On first use, auto-renames global.jsonuser.json in the config directory
    • Auto-renames globalConfigPathuserConfigPath in config.json

Implementation:

  • src/adapters/claude-md.ts - New claude-md adapter
  • src/config.ts - Added userConfigPath, getUserConfigPath(), getUserProjectConfig(), saveUserProjectConfig() (replacing global* equivalents)
  • src/project-config.ts - Added claude.md and claude.rules to config interfaces; added addUserDependency(), removeUserDependency()
  • src/adapters/types.ts - Added skipIgnore?: boolean to SyncOptions
  • src/sync-engine.ts - Respect skipIgnore in linkEntry()
  • src/adapters/index.ts - Registered claudeMdAdapter
  • src/commands/handlers.ts - Added user? and skipIgnore? to CommandContext; user path for handleAdd/handleRemove
  • src/commands/install.ts - Added installUserEntriesForAdapter(), installAllUserEntries()
  • src/commands/config.ts - Added handleUserConfigShow/Set/Reset()
  • src/cli/register.ts - Added -u, --user flag to add/remove/install commands
  • src/index.ts - Added ais claude md subgroup, ais user install, ais config user commands

Files Changed: 11 modified/new, all tests passing (206/206)

OpenAI Codex Support (2026-02)

Added complete support for OpenAI Codex project-level rules and skills:

Problem Solved:

  • Teams using Codex needed to share rules and skills across projects
  • No centralized way to distribute Codex configurations
  • Manual copying led to drift and inconsistency

Features Implemented:

  1. Codex Rules Adapter:

    • File mode with .rules suffix
    • Source: .codex/rules/
    • Syntax: ais codex rules add <ruleName> [alias]
    • Purpose: Control which commands can run outside sandbox using Starlark syntax
  2. Codex Skills Adapter:

    • Directory mode (SKILL.md + optional scripts/assets)
    • Source: .agents/skills/ (non-standard location per Codex docs)
    • Syntax: ais codex skills add <skillName> [alias]
    • Purpose: Task-specific capabilities that extend Codex
  3. CLI Commands:

    • ais codex install - Install all Codex rules and skills
    • ais codex add-all - Discover and add all entries from repository
    • ais codex import <name> - Import from project to repository (auto-detects subtype)
    • ais codex rules [add|remove|install|import] - Rules management
    • ais codex skills [add|remove|install|import] - Skills management
  4. Configuration Support:

    • Extended SourceDirConfig with codex.rules and codex.skills
    • Extended ProjectConfig with codex.rules and codex.skills records
    • Full support for custom source directories via -s option
    • Backward compatible with existing configs
  5. Shell Completion:

    • Added Codex to bash, zsh, and fish completion scripts
    • Dynamic completion for rule/skill names via ais _complete codex-rules|codex-skills
    • Context-aware completions for all subcommands
  6. Mode Detection:

    • Added 'codex' to DefaultMode type
    • ais install smart dispatch includes Codex
    • Auto-detect Codex-only projects

Implementation:

  • src/adapters/codex-rules.ts - Rules adapter (file mode, .rules suffix)
  • src/adapters/codex-skills.ts - Skills adapter (directory mode, .agents/skills)
  • src/adapters/index.ts - Registered adapters and added to findAdapterForAlias
  • src/project-config.ts - Extended configuration interfaces and helpers
  • src/commands/helpers.ts - Added 'codex' mode type and inference
  • src/index.ts - Full CLI command hierarchy with install/add-all/import
  • src/completion/scripts.ts - Shell completion for all three shells
  • tests/codex-adapters.test.ts - Complete test coverage (9 tests)

Files Changed: 9 new/modified, all tests passing (126/126)

Benefits:

  • Centralized Codex configuration management
  • Team-wide consistency for sandbox rules
  • Easy sharing of skills across projects
  • Follows same pattern as other supported tools

Custom Source Directories for Third-Party Repositories (2026-01)

Added 4-layer priority system for custom source directory configuration:

Problem Solved:

  • Third-party repositories without ai-rules-sync.json were unusable
  • Repositories with non-standard directory structures (e.g., rules/cursor/ instead of .cursor/rules) required forking
  • No way to override source directories without modifying the repository

Solution - 4-Layer Priority:

CLI Parameters > Global Config > Repository Config > Adapter Defaults

Features Implemented:

  1. CLI Parameters (-s/--source-dir):

    • Simple format: ais cursor rules add-all -s custom/rules
    • Dot notation: ais add-all -s cursor.rules=custom/rules
    • Supports multiple -s flags
    • Context-aware parsing (infers tool/subtype from command)
  2. Global Configuration Commands:

    • ais config repo set-source <name> <tool.subtype> <path> - Persist custom sourceDir
    • ais config repo show <name> - View repository configuration
    • ais config repo clear-source <name> [tool.subtype] - Remove custom sourceDir
    • ais config repo list - List all repositories with sourceDir
  3. Enhanced Architecture:

    • Extended RepoConfig interface with sourceDir?: SourceDirConfig
    • Enhanced getSourceDir() with globalOverride parameter (4-layer priority logic)
    • All add-all commands support -s option (top-level, tool-level, subtype-level)
    • Custom parser with simple and dot notation format support
  4. Configuration Persistence:

    • Global config stored in ~/.config/ai-rules-sync/config.json
    • Per-repository sourceDir configuration
    • CLI overrides have highest priority (temporary)
    • Global config persists across sessions

Use Cases:

  • Exploration: ais cursor rules add-all -s custom/rules --dry-run
  • Persistent: ais config repo set-source my-repo cursor.rules custom/rules
  • Override: CLI parameter overrides saved configuration

Files Changed:

  • src/config.ts - Added sourceDir to RepoConfig interface
  • src/project-config.ts - Enhanced getSourceDir() with priority logic
  • src/commands/add-all.ts - Added sourceDirOverrides parameter throughout
  • src/cli/source-dir-parser.ts - New parameter parsing module
  • src/commands/config.ts - New config management commands
  • src/cli/register.ts - Added -s option to all adapter commands
  • src/index.ts - Added -s to all add-all commands + config command group
  • README.md - Added comprehensive documentation section

Benefits:

  • Works with any repository (no ai-rules-sync.json required)
  • Flexible (CLI for quick tests, config for persistent use)
  • Non-destructive (doesn't modify third-party repositories)
  • User-friendly (smart context detection in simple format)

Configuration Directory Migration (2026-01)

Changed global configuration location to follow XDG Base Directory specification:

  • Old: ~/.ai-rules-sync/
  • New: ~/.config/ai-rules-sync/

Impact:

  • Global config file: ~/.config/ai-rules-sync/config.json
  • Repository cache: ~/.config/ai-rules-sync/repos/
  • No automatic migration provided - users must manually move files if needed
  • Aligns with Linux/macOS standards for configuration file placement

Files Changed:

  • src/config.ts - Updated CONFIG_DIR constant
  • tests/config.test.ts - Updated test fixtures
  • Documentation updated to reflect new paths

Init Command Tool Filtering (2026-03)

Added --only and --exclude options to ais init for selective tool initialization:

Problem Solved:

  • ais init generated config and directories for all 14+ supported tools, which is overwhelming for users who only use a few tools.

Features Implemented:

  1. --only <tools...>: Only include specified tools in the generated config and directories.

    • Example: ais init --only cursor claude — only initializes Cursor and Claude sections.
  2. --exclude <tools...>: Exclude specified tools from initialization.

    • Example: ais init --exclude trae opencode gemini — initializes everything except those tools.
  3. Mutual exclusivity: --only takes precedence if both are provided.

  4. Scope: Both options affect sourceDir config generation and source directory creation.

Implementation:

  • src/commands/lifecycle.ts — Added only/exclude to InitOptions; added getFilteredAdapters() helper; updated initRulesRepository() and buildTemplateSourceDirConfig() to use filtered adapters.
  • src/index.ts — Added --only and --exclude CLI options to the init command.
  • src/__tests__/lifecycle-init.test.ts — Added 3 new tests for --only, --exclude, and directory filtering.

Files Changed: 3 modified, all tests passing


Automated Release Pipeline (npm + Homebrew) (2026-03)

Added end-to-end release automation via GitHub Actions:

  1. release.yml:

    • Triggered on push to main (and workflow_dispatch)
    • Uses changesets/action to create/update release PRs and publish npm automatically
    • Publishes downstream outputs (published, published_version) for dependent jobs
  2. update-homebrew.yml (refactored):

    • Converted to reusable workflow (workflow_call) and manual rerun (workflow_dispatch)
    • Accepts explicit version input (no registry race on version lookup)
    • Computes npm tarball SHA256 and updates Formula/ais.rb in this repository

Distribution Impact:

  • Homebrew tap uses explicit repository URL:
    • brew tap lbb00/ai-rules-sync https://github.com/lbb00/ai-rules-sync
    • brew install ais
  • npm remains the source artifact for Homebrew formula updates

OpenCode AI Support (2026-01)

Added complete support for OpenCode AI (https://opencode.ai) with 5 component types:

  • Rules (.opencode/rules/) - File mode with .md suffix
  • Agents (.opencode/agents/) - Directory mode
  • Skills (.opencode/skills/) - Directory mode
  • Commands (.opencode/commands/) - Directory mode
  • Custom-tools (.opencode/custom-tools/) - Directory mode

Implementation:

  • Created 5 new adapters following existing patterns
  • Extended ProjectConfig and SourceDirConfig interfaces
  • Added CLI commands: ais opencode [rules|agents|skills|commands|custom-tools] [add|remove|install|import]
  • Updated shell completion scripts (bash, zsh, fish)
  • Added _complete command support for all OpenCode types
  • Updated mode inference to recognize OpenCode projects

Files Changed:

  • src/adapters/opencode-rules.ts - New adapter (file mode, .md)
  • src/adapters/opencode-agents.ts - New adapter (directory mode)
  • src/adapters/opencode-skills.ts - New adapter (directory mode)
  • src/adapters/opencode-commands.ts - New adapter (directory mode)
  • src/adapters/opencode-custom-tools.ts - New adapter (directory mode)
  • src/adapters/index.ts - Registered all 5 OpenCode adapters
  • src/project-config.ts - Extended configuration interfaces
  • src/commands/helpers.ts - Added 'opencode' mode type
  • src/index.ts - Added OpenCode CLI commands and completion
  • src/completion/scripts.ts - Added OpenCode to all shell completions
  • README.md - Documented OpenCode support
  • KNOWLEDGE_BASE.md - Updated architecture and feature documentation

OpenCode Adapters Fix & Universal AGENTS.md Support (2026-01)

Fixed OpenCode adapter modes to match official OpenCode documentation:

  • Removed opencode-rules adapter (OpenCode doesn't have a rules type)
  • Fixed opencode-agents - Changed from directory to file mode with .md suffix
  • Fixed opencode-commands - Changed from directory to file mode with .md suffix
  • Renamed opencode-custom-toolsopencode-tools - Changed to file mode with .ts/.js suffixes
  • Kept opencode-skills - Remains directory mode (contains SKILL.md inside)

Added Universal AGENTS.md Support:

  • New adapter: agents-md - Tool-agnostic support for the agents.md standard
  • Syncs AGENTS.md files from repository to project root
  • Makes agent definitions available to any AI coding tool supporting the agents.md format
  • Mode: File mode with .md suffix
  • Target: Project root (.)

Configuration Changes:

  • Removed opencode.rules from all config interfaces
  • Renamed opencode['custom-tools']opencode.tools
  • Added new top-level agentsMd configuration section
  • Updated SourceDirConfig and ProjectConfig interfaces

CLI Changes:

  • Added new top-level command group: ais agents-md [add|remove|install|import]
  • Removed ais opencode rules subcommand
  • Changed ais opencode custom-toolsais opencode tools
  • Updated all error messages and help text

Implementation:

  • src/adapters/agents-md.ts - New universal adapter
  • src/adapters/opencode-rules.ts - Deleted
  • src/adapters/opencode-custom-tools.ts - Renamed to opencode-tools.ts
  • src/adapters/opencode-agents.ts - Fixed to file mode
  • src/adapters/opencode-commands.ts - Fixed to file mode
  • src/adapters/opencode-tools.ts - Updated to file mode with .ts/.js
  • src/adapters/index.ts - Updated registry
  • src/project-config.ts - Updated all config interfaces
  • src/commands/helpers.ts - Added 'agents-md' mode
  • src/index.ts - Updated CLI commands and completion
  • src/completion/scripts.ts - Updated all shell completions
  • README.md & README_ZH.md - Documented changes with reference links
  • KNOWLEDGE_BASE.md - Updated architecture documentation

Reference Links Added: All documentation now includes links to official tool documentation for easy reference.

AGENTS.md Adapter Redesign (2026-01)

Redesigned agents-md adapter for flexible AGENTS.md location:

Problem Solved:

  • Old adapter required AGENTS.md files in fixed agents-md/ directory
  • Didn't align with agents.md standard allowing files anywhere in repo
  • Limited name resolution didn't support path-based lookup

New Design:

  • Changed default source directory: agents-md. (repository root)
  • Flexible path resolution supports 4 patterns:
    1. Explicit file path: frontend/AGENTS.mdrepo/frontend/AGENTS.md
    2. Directory path: docs/teamrepo/docs/team/AGENTS.md (auto-appends /AGENTS.md)
    3. Simple name: frontend → tries repo/frontend/AGENTS.md, then repo/AGENTS.md
    4. Root level: . or AGENTSrepo/AGENTS.md
  • Case insensitive: Supports both AGENTS.md and agents.md variants
  • Custom config management: Uses flat agentsMd structure instead of nested like other tools

Configuration Changes:

// Old (rules repo)
{ "sourceDir": { "agentsMd": { "file": "agents-md" } } }

// New (rules repo) - supports any directory
{ "sourceDir": { "agentsMd": { "file": "." } } }

// Project config - flat structure with flexible paths
{
  "agentsMd": {
    "root": { "url": "...", "rule": "AGENTS.md" },
    "frontend": { "url": "...", "rule": "frontend/AGENTS.md" },
    "platform": { "url": "...", "rule": "docs/teams/platform/AGENTS.md" }
  }
}

Implementation Details:

  • Custom resolveSource with multi-pattern path resolution
  • Custom addDependency/removeDependency for flat config structure
  • Fixed alias handling in handleAdd to prioritize user-provided aliases
  • Validates that only AGENTS.md files are supported (rejects other .md files)

Migration:

  • No breaking changes: Old configs continue to work
  • Existing agents-md/AGENTS.md will still be found
  • Users can gradually migrate to new flexible structure
  • New projects can organize AGENTS.md files by directory (frontend/, backend/, etc.)

Files Changed:

  • src/adapters/agents-md.ts - Complete rewrite with flexible resolution
  • src/project-config.ts - Updated default comment and config handling
  • src/commands/handlers.ts - Fixed alias handling for all adapters
  • KNOWLEDGE_BASE.md, README.md, README_ZH.md - Documentation updates

Custom Target Directories (2026-01)

Added support for custom target directories per entry:

Feature Overview:

  • Users can now specify custom target directories for each synced entry
  • Allows flexible organization beyond default tool directories
  • Perfect for documentation projects, monorepos, and custom team structures
  • Supports aliasing same rule to multiple locations

Implementation:

  • Entry-level configuration: Each config entry can specify targetDir field
  • CLI option: Added -d, --target-dir <dir> to all add commands
  • Priority resolution: options.targetDir > config entry targetDir > adapter default
  • Conflict detection: Prevents overwriting when adding same rule to different locations without alias
  • Suffix handling: Properly resolves file suffixes when removing aliased entries

Configuration Examples:

{
  "cursor": {
    "rules": {
      // Default target directory (.cursor/rules/)
      "standard-rule": "https://github.com/company/rules",

      // Custom target directory
      "docs-rule": {
        "url": "https://github.com/company/rules",
        "targetDir": "docs/ai/rules"
      },

      // Same rule to multiple locations (requires alias)
      "frontend-auth": {
        "url": "https://github.com/company/rules",
        "rule": "auth-rules",
        "targetDir": "packages/frontend/.cursor/rules"
      },
      "backend-auth": {
        "url": "https://github.com/company/rules",
        "rule": "auth-rules",
        "targetDir": "packages/backend/.cursor/rules"
      }
    }
  }
}

CLI Usage:

# Add rule to custom directory
ais cursor add my-rule -d docs/ai/rules

# Add same rule to multiple locations (requires alias)
ais cursor add auth-rules frontend-auth -d packages/frontend/.cursor/rules
ais cursor add auth-rules backend-auth -d packages/backend/.cursor/rules

# Remove specific location (uses alias as config key)
ais cursor remove frontend-auth

# Install respects custom targetDir from config
ais cursor install

Key Behaviors:

  • No alias needed for first-time adds or when targeting different source files
  • Alias required when adding same source file to different location (prevents config key conflicts)
  • Backward compatible: Entries without targetDir use adapter default
  • Config format: Uses simple string when no custom targetDir; object format when specified
  • Install support: install command reads and respects targetDir from config

Files Changed:

  • src/project-config.ts - Extended RuleEntry type, added getTargetDir() and getEntryConfig()
  • src/sync-engine.ts - Dynamic target directory resolution in linkEntry(), unlinkEntry(), importEntry()
  • src/adapters/types.ts - Extended SyncOptions and addDependency signature
  • src/adapters/base.ts - Pass targetDir through to config functions
  • src/adapters/agents-md.ts - Updated custom addDependency() for targetDir support
  • src/commands/handlers.ts - Added AddOptions with conflict detection
  • src/commands/install.ts - Extract and pass targetDir during installation
  • src/cli/register.ts - Added -d, --target-dir option to adapter commands
  • src/index.ts - Added -d, --target-dir to hardcoded cursor/copilot commands
  • All tests passing (105/105)

Gemini CLI Support (2026-02)

Added complete support for Gemini CLI (https://geminicli.com/) with three entry types:

Problem Solved:

  • Teams using Gemini CLI needed to share commands, skills, and agents across projects
  • No centralized way to distribute Gemini CLI configurations
  • Manual copying led to drift and inconsistency

Features Implemented:

  1. Gemini Commands Adapter:

    • File mode with .toml suffix (native Gemini CLI format)
    • Source: .gemini/commands/
    • Syntax: ais gemini commands add <commandName> [alias]
    • Purpose: Reusable prompts with argument substitution
  2. Gemini Skills Adapter:

    • Directory mode (SKILL.md + optional assets)
    • Source: .gemini/skills/
    • Syntax: ais gemini skills add <skillName> [alias]
    • Purpose: Specialized expertise for specific tasks
  3. Gemini Agents Adapter:

    • File mode with .md suffix (Markdown with YAML frontmatter)
    • Source: .gemini/agents/
    • Syntax: ais gemini agents add <agentName> [alias]
    • Purpose: Specialized agents with defined capabilities
  4. CLI Commands:

    • ais gemini install - Install all Gemini commands, skills, and agents
    • ais gemini add-all - Discover and add all entries from repository
    • ais gemini import <name> - Import from project to repository (auto-detects subtype)
    • ais gemini commands [add|remove|install|import] - Commands management
    • ais gemini skills [add|remove|install|import] - Skills management
    • ais gemini agents [add|remove|install|import] - Agents management
  5. Configuration Support:

    • Extended SourceDirConfig with gemini.commands, gemini.skills, and gemini.agents
    • Extended ProjectConfig with gemini.commands, gemini.skills, and gemini.agents records
    • Full support for custom source directories via -s option
    • Backward compatible with existing configs
  6. Shell Completion:

    • Added Gemini CLI to bash, zsh, and fish completion scripts
    • Dynamic completion for command/skill/agent names via ais _complete gemini-commands|gemini-skills|gemini-agents
    • Context-aware completions for all subcommands
  7. Mode Detection:

    • Added 'gemini' to DefaultMode type
    • ais install smart dispatch includes Gemini CLI
    • Auto-detect Gemini-only projects

Implementation:

  • src/adapters/gemini-commands.ts - Commands adapter (file mode, .toml suffix)
  • src/adapters/gemini-skills.ts - Skills adapter (directory mode)
  • src/adapters/gemini-agents.ts - Agents adapter (file mode, .md suffix)
  • src/adapters/index.ts - Registered adapters and added to findAdapterForAlias
  • src/project-config.ts - Extended configuration interfaces and helpers
  • src/commands/helpers.ts - Added 'gemini' mode type and inference
  • src/index.ts - Full CLI command hierarchy with install/add-all/import
  • src/completion/scripts.ts - Shell completion for all three shells
  • src/__tests__/gemini-commands.test.ts - Commands adapter tests (5 tests)
  • src/__tests__/gemini-skills.test.ts - Skills adapter tests (5 tests)
  • src/__tests__/gemini-agents.test.ts - Agents adapter tests (5 tests)
  • README.md, README_ZH.md - Documentation updates

Files Changed: 15 new/modified, all tests passing (166/166)

Benefits:

  • Centralized Gemini CLI configuration management
  • Team-wide consistency for commands, skills, and agents
  • Easy sharing of configurations across projects
  • Native TOML support for commands
  • Follows same pattern as other supported tools (Cursor, OpenCode, Codex)