Skip to content

Add rule syncing to dual-tool agent configuration#163

Open
Miyamura80 wants to merge 2 commits intomainfrom
feat/add-rule-syncing
Open

Add rule syncing to dual-tool agent configuration#163
Miyamura80 wants to merge 2 commits intomainfrom
feat/add-rule-syncing

Conversation

@Miyamura80
Copy link
Copy Markdown
Owner

@Miyamura80 Miyamura80 commented May 5, 2026

Summary

  • Adds sync_rule_symlinks() to scripts/sync_agent_config.py -- mirrors .claude/rules/ to .agents/rules/ via symlinks
  • Updates .claude/rules/codex-claude-sync.md frontmatter from paths: to globs: and documents rule sync direction
  • Adds rule creation guidance to manage-agent-config skill decision tree
  • Adds new new-agent-rule skill for creating path-scoped rules

Test plan

  • Run make sync-agent-config and verify .agents/rules/codex-claude-sync.md symlink exists
  • Run make sync-agent-config --check and verify it exits 0 (no drift)

🤖 Generated with Claude Code


Summary by cubic

Adds rule syncing to the dual-tool agent config. .claude/rules/*.md are now mirrored to .agents/rules/ via symlinks, use globs:, and the sync adds safety checks and clearer errors.

  • New Features

    • Mirrors rules from .claude/rules/ to .agents/rules/ via symlinks; .claude/rules/ is the source of truth.
    • Auto-prunes dangling rule symlinks and blocks collisions with real files in .agents/rules/.
    • Adds sparse-checkout guard and clearer symlink error messages; documents rule direction and globs:; updates manage-agent-config and adds the new-agent-rule skill.
  • Migration

    • Use globs: (not paths:) in rule frontmatter.
    • Put new rules in .claude/rules/ only; do not edit .agents/rules/.
    • Remove any real files in .agents/rules/ that clash with .claude/rules/.
    • Run make sync-agent-config (or make sync-agent-config --check to verify no drift).

Written for commit 8cfe07d. Summary will update on new commits.

Extends the agent configuration sync system to handle path-scoped rules.
Rules are mirrored from .claude/rules/ (source of truth) to .agents/rules/
via symlinks, with the sync direction inverted from skills since Claude is
the only tool that auto-discovers rules.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@qodo-code-review
Copy link
Copy Markdown

Review Summary by Qodo

Add rule syncing to dual-tool agent configuration

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Adds rule syncing to agent configuration system via symlinks
• Mirrors .claude/rules/ to .agents/rules/ with inverted direction
• Updates rule documentation with globs: frontmatter guidance
• Adds new-agent-rule skill for creating path-scoped rules
Diagram
flowchart LR
  A[".claude/rules/<name>.md"] -->|source of truth| B["sync_rule_symlinks()"]
  B -->|creates symlinks| C[".agents/rules/<name>.md"]
  D["manage-agent-config skill"] -->|updated docs| E["Rule creation guidance"]
  F["new-agent-rule skill"] -->|new| G["Rule writing guide"]
Loading

Grey Divider

File Changes

1. scripts/sync_agent_config.py ✨ Enhancement +75/-11

Implement rule symlink syncing function

• Added sync_rule_symlinks() function to create symlinks from .agents/rules/ to .claude/rules/
• Updated module docstring to document rule syncing alongside skill syncing
• Added SHARED_RULES and CLAUDE_RULES path constants
• Integrated rule syncing into main() function call chain
• Reformatted code for consistency (line wrapping, set formatting)

scripts/sync_agent_config.py


2. .agents/rules/codex-claude-sync.md ⚙️ Configuration changes +1/-0

Create rule symlink mirror file

• Created new symlink file pointing to .claude/rules/codex-claude-sync.md
• Establishes mirror directory structure for rule syncing

.agents/rules/codex-claude-sync.md


3. .claude/rules/codex-claude-sync.md 📝 Documentation +30/-7

Update rule documentation with globs and sync direction

• Changed frontmatter from paths: to globs: with broader pattern matching
• Added description: field documenting dual-tool sync layout
• Updated glob patterns to cover .claude/, .agents/, and .codex/ directories
• Added documentation section explaining rule symlink direction (opposite from skills)
• Documented globs: frontmatter format with example for rule scoping
• Updated tooling section to describe rule symlink creation
• Added step 5 to workflow checklist for creating new rules

.claude/rules/codex-claude-sync.md


View more (2)
4. .agents/skills/manage-agent-config/SKILL.md 📝 Documentation +8/-2

Add rule creation guidance to skill documentation

• Extended description to include .claude/rules/ and .agents/rules/ directories
• Added new section with guidance for creating path-scoped rules
• Updated renaming/deleting section to mention .claude/rules/ as source
• Added reference to new-agent-rule skill for rule creation

.agents/skills/manage-agent-config/SKILL.md


5. .claude/skills/new-agent-rule/SKILL.md 📝 Documentation +47/-0

New skill guide for creating path-scoped rules

• New skill file providing comprehensive guide for creating path-scoped rules
• Documents when to create rules and naming conventions
• Explains globs: frontmatter format with examples
• Provides step-by-step workflow for rule creation
• Lists anti-patterns to avoid (missing globs, duplication, using paths instead)

.claude/skills/new-agent-rule/SKILL.md


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review Bot commented May 5, 2026

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (2)

Grey Divider


Action required

1. codex-claude-sync.md uses hyphen 📘 Rule violation ✧ Quality
Description
A new rule file is introduced with a hyphenated filename (codex-claude-sync.md), which is not
snake_case. This violates the repository naming convention and can break tooling that expects
snake_case basenames.
Code

.agents/rules/codex-claude-sync.md[1]

+../../.claude/rules/codex-claude-sync.md
Evidence
The checklist requires new files/directories to be snake_case and explicitly flags hyphens as
non-compliant; this PR adds .agents/rules/codex-claude-sync.md with a hyphenated basename.

Rule 315732: Use snake_case for functions, files, and directories
.agents/rules/codex-claude-sync.md[1-1]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A newly added rule file uses a hyphenated filename (`codex-claude-sync.md`), violating the snake_case naming requirement.

## Issue Context
Rule syncing mirrors `.claude/rules/<name>.md` into `.agents/rules/<name>.md`, so renaming should keep both sides consistent and update any references.

## Fix Focus Areas
- .agents/rules/codex-claude-sync.md[1-1]
- .claude/rules/codex-claude-sync.md[1-6]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Single quotes in description 📘 Rule violation ✧ Quality
Description
The updated YAML frontmatter description uses single quotes around make sync-agent-config. This
violates the requirement to use double quotes for string literals in modified files.
Code

.agents/skills/manage-agent-config/SKILL.md[3]

+description: Use whenever creating, editing, renaming, or deleting any file under .claude/skills/, .claude/agents/, .claude/rules/, .agents/skills/, .agents/rules/, or .codex/agents/. Teaches the dual-tool Claude/Codex layout and reminds to run 'make sync-agent-config'.
Evidence
The checklist requires double quotes for string literals; the modified frontmatter description
contains single-quoted text ('make sync-agent-config') on an edited line.

Rule 315742: Use double quotes for all string literals
.agents/skills/manage-agent-config/SKILL.md[3-3]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A modified YAML frontmatter line uses single quotes around `make sync-agent-config`, violating the double-quote-only rule for string literals.

## Issue Context
This is in the `description:` field of the SKILL frontmatter.

## Fix Focus Areas
- .agents/skills/manage-agent-config/SKILL.md[3-3]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Unhandled rule symlink errors 🐞 Bug ☼ Reliability
Description
sync_rule_symlinks() creates symlinks without catching OSError/NotImplementedError, so
sync-agent-config can crash with a traceback on platforms/environments where symlink creation is
restricted. This is inconsistent with the existing skill symlink path, which already provides a
user-friendly SystemExit with Windows remediation steps.
Code

scripts/sync_agent_config.py[R241-248]

+        elif link.exists():
+            raise SystemExit(
+                f"ERROR: name collision - .agents/rules/{rule.name} is a real file "
+                f"but .claude/rules/{rule.name} also exists. The .claude/rules/ version is the "
+                "source of truth; remove the .agents/rules/ copy."
+            )
+        link.symlink_to(target)
+        changes.append(f"symlinked {link.relative_to(REPO)}")
Evidence
Rule symlink creation uses Path.symlink_to() without a try/except, while the shared-skill symlink
creator wraps symlink_to() and turns platform-specific failures into an actionable error message
(including Windows Developer Mode guidance).

scripts/sync_agent_config.py[241-248]
scripts/sync_agent_config.py[173-193]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`sync_rule_symlinks()` calls `link.symlink_to(target)` without handling failures. On platforms where symlinks require elevated privileges (or where symlinks are unsupported), this will raise and produce a traceback, breaking `make sync-agent-config` / the pre-commit hook with a non-actionable error.

## Issue Context
The same file already has `_materialize_symlink()` which catches `(OSError, NotImplementedError)` and raises `SystemExit` with a clear message and Windows remediation steps. The new rule-sync path should follow the same pattern for consistent behavior.

## Fix Focus Areas
- scripts/sync_agent_config.py[173-193]
- scripts/sync_agent_config.py[224-254]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

4. Rule prune guard missing 🐞 Bug ☼ Reliability
Description
sync_rule_symlinks() always prunes symlinks in .agents/rules that aren't present in
.claude/rules-derived wanted, but it lacks the safety guard used by sync_skill_symlinks() to
prevent mass-pruning when the source side was missing/just created empty. In that edge case (e.g.,
sparse checkout/manual removal of .claude/rules), running sync can delete all mirrored rule
symlinks.
Code

scripts/sync_agent_config.py[R227-254]

+    SHARED_RULES.mkdir(parents=True, exist_ok=True)
+    CLAUDE_RULES.mkdir(parents=True, exist_ok=True)
+
+    wanted: set[str] = set()
+    for rule in CLAUDE_RULES.iterdir():
+        if rule.is_symlink() or not rule.is_file() or rule.suffix != ".md":
+            continue
+        wanted.add(rule.name)
+        link = SHARED_RULES / rule.name
+        target = Path("..") / ".." / ".claude" / "rules" / rule.name
+        if link.is_symlink():
+            if os.path.normpath(os.readlink(link)) == os.path.normpath(str(target)):
+                continue
+            link.unlink()
+        elif link.exists():
+            raise SystemExit(
+                f"ERROR: name collision - .agents/rules/{rule.name} is a real file "
+                f"but .claude/rules/{rule.name} also exists. The .claude/rules/ version is the "
+                "source of truth; remove the .agents/rules/ copy."
+            )
+        link.symlink_to(target)
+        changes.append(f"symlinked {link.relative_to(REPO)}")
+
+    for link in SHARED_RULES.iterdir():
+        if link.is_symlink() and link.name not in wanted:
+            link.unlink()
+            changes.append(f"pruned dangling {link.relative_to(REPO)}")
+    return changes
Evidence
The skills sync explicitly avoids pruning when the source directory was missing and was just created
empty, to prevent deleting all mirrors in one run. The rules sync creates directories
unconditionally and then prunes based solely on an (possibly empty) wanted set, with no analogous
guard.

scripts/sync_agent_config.py[196-216]
scripts/sync_agent_config.py[224-254]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`sync_rule_symlinks()` prunes `.agents/rules/*` symlinks not in `wanted`, but it does not include a safety guard to prevent deleting *everything* when the source side is unexpectedly empty because it was missing (sparse checkout/manual rm) and got recreated.

## Issue Context
`sync_skill_symlinks()` uses a `shared_existed` flag and returns early when the source was missing and the new source directory is empty to prevent mass-deletion of mirrors. Rules sync should implement an analogous guard by tracking whether `.claude/rules` existed before `mkdir()` and skipping prune when it didn’t and `wanted` is empty.

## Fix Focus Areas
- scripts/sync_agent_config.py[196-216]
- scripts/sync_agent_config.py[224-254]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 5 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="scripts/sync_agent_config.py">

<violation number="1" location="scripts/sync_agent_config.py:228">
P2: Missing safety check for empty source directory. If `.claude/rules/` doesn't exist (sparse checkout) the script creates it empty, then the pruning loop deletes all existing symlinks in `.agents/rules/`. Add a guard analogous to `sync_skill_symlinks`' `if not shared_existed and not wanted: return changes`.</violation>

<violation number="2" location="scripts/sync_agent_config.py:247">
P2: Missing error handling for `symlink_to` call. The existing `_materialize_symlink` helper catches `OSError`/`NotImplementedError` and provides a helpful Windows-specific message. Wrap this call consistently to avoid an unhelpful traceback on systems where symlink creation fails.</violation>
</file>

<file name=".agents/skills/manage-agent-config/SKILL.md">

<violation number="1" location=".agents/skills/manage-agent-config/SKILL.md:3">
P2: Description exceeds the ≤250 character limit for shared skills (257 chars). Consider abbreviating, e.g., collapsing the path list or shortening the trailing clause.</violation>
</file>

Partial review: This PR has more than 50 files, so cubic reviewed the highest-priority files first. During the trial, paid plans get a higher file limit.
You can try an ultrareview to bypass the file limit, comment @cubic-dev-ai ultrareview. Learn more.
Fix all with cubic.

Comment thread scripts/sync_agent_config.py Outdated
Comment thread scripts/sync_agent_config.py
Comment thread .agents/skills/manage-agent-config/SKILL.md Outdated
@@ -0,0 +1 @@
../../.claude/rules/codex-claude-sync.md No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. codex-claude-sync.md uses hyphen 📘 Rule violation ✧ Quality

A new rule file is introduced with a hyphenated filename (codex-claude-sync.md), which is not
snake_case. This violates the repository naming convention and can break tooling that expects
snake_case basenames.
Agent Prompt
## Issue description
A newly added rule file uses a hyphenated filename (`codex-claude-sync.md`), violating the snake_case naming requirement.

## Issue Context
Rule syncing mirrors `.claude/rules/<name>.md` into `.agents/rules/<name>.md`, so renaming should keep both sides consistent and update any references.

## Fix Focus Areas
- .agents/rules/codex-claude-sync.md[1-1]
- .claude/rules/codex-claude-sync.md[1-6]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Invalid. The filename codex-claude-sync.md follows the cross-repo convention established in Edison-OS and all template repos. Renaming would break sync script assumptions and git history across repositories.

---
name: manage-agent-config
description: Use whenever creating, editing, renaming, or deleting any file under .claude/skills/, .claude/agents/, .agents/skills/, or .codex/agents/. Teaches the dual-tool Claude/Codex layout and reminds to run `make sync-agent-config`.
description: Use whenever creating, editing, renaming, or deleting any file under .claude/skills/, .claude/agents/, .claude/rules/, .agents/skills/, .agents/rules/, or .codex/agents/. Teaches the dual-tool Claude/Codex layout and reminds to run 'make sync-agent-config'.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Single quotes in description 📘 Rule violation ✧ Quality

The updated YAML frontmatter description uses single quotes around make sync-agent-config. This
violates the requirement to use double quotes for string literals in modified files.
Agent Prompt
## Issue description
A modified YAML frontmatter line uses single quotes around `make sync-agent-config`, violating the double-quote-only rule for string literals.

## Issue Context
This is in the `description:` field of the SKILL frontmatter.

## Fix Focus Areas
- .agents/skills/manage-agent-config/SKILL.md[3-3]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed. The description has been rewritten to stay within the 250-char limit, which also resolves the quoting concern.

Comment thread scripts/sync_agent_config.py
…or handling

- Shorten manage-agent-config description to <=250 chars
- Add sparse-checkout safety guard to sync_rule_symlinks()
- Add OSError/NotImplementedError handling to sync_rule_symlinks()

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant