Skip to content

feat: project rules with .claw/rules/ and multi-framework auto-import#2830

Open
TheArchitectit wants to merge 8 commits intoultraworkers:mainfrom
TheArchitectit:feat/project-rules
Open

feat: project rules with .claw/rules/ and multi-framework auto-import#2830
TheArchitectit wants to merge 8 commits intoultraworkers:mainfrom
TheArchitectit:feat/project-rules

Conversation

@TheArchitectit
Copy link
Copy Markdown

Summary

Adds a project rules system for loading instruction files into the system prompt, plus auto-import from other AI coding frameworks so users switching to claw-code don't have to duplicate their rules.

Problem this solves

No structured way to organize project rules

Before: rules could only go in CLAUDE.md or .claw/CLAUDE.md — single files. No way to organize rules by topic, no way to gitignore personal rules.

Fix: .claw/rules/ directory — drop any .md, .txt, or .mdc files, auto-loaded alphabetically. .claw/rules.local/ for personal rules that don't get committed.

Switching from Cursor/Copilot/Windsurf = duplicate all rules

Before: users coming from other AI coding tools had to manually copy their rules into CLAUDE.md.

Fix: claw-code auto-detects and imports rules from all major frameworks:

  • Cursor: .cursorrules, .cursor/rules/
  • GitHub Copilot: .github/copilot-instructions.md
  • Windsurf: .windsurfrules, .windsurfrules/
  • Aider: .aider.conf.yml instructions block
  • Pi (Plandex): .plandex/instructions.md, .plandex/plan.md
  • OpenCode: opencode.json instructions field
  • Crush: .crush/CLAUDE.md, .crush/rules/

No way to control which frameworks get imported

Fix: rulesImport config in settings.json:

  • "auto" (default) — import from all detected frameworks
  • "none" — only load .claw/rules/ and CLAUDE.md files
  • ["cursor", "copilot"] — import only from listed frameworks

How it works

All loaded files are deduplicated by content hash, so the same rule appearing in both .cursorrules and .claw/rules/cursor.md won't appear twice.

Example directory structure

project/
├── CLAUDE.md                          # Top-level project rules
├── .cursorrules                        # Auto-imported from Cursor
├── .claw/
│   ├── rules/
│   │   ├── 01-style.md                # Code style rules
│   │   ├── 02-testing.md              # Testing standards
│   │   └── 03-database.md            # Database conventions
│   ├── rules.local/
│   │   └── personal-preferences.md    # Personal rules (gitignored)
│   └── CLAUDE.md                       # Claw-specific overrides
└── .github/
    └── copilot-instructions.md         # Auto-imported from Copilot

Template support (.mdc files)

.claw/rules/ also loads .mdc (Markdown Context) files — the same format used by Cursor's rules.

Files changed

File What changed
runtime/src/prompt.rs discover_instruction_files() scans .claw/rules/, .claw/rules.local/, and 7 framework locations. Added push_rules_dir(), push_framework_imports(), read_aider_instructions(), read_opencode_instructions()
runtime/src/config.rs RulesImportConfig enum, rules_import field, accessor, parser
runtime/src/config_validate.rs rulesImport field validation
runtime/src/lib.rs Export RulesImportConfig

Test plan

  • cargo build --release — clean build
  • 513 runtime tests pass
  • Existing instruction file discovery tests still pass
  • Create .claw/rules/test.md and verify it appears in system prompt
  • Create .claw/rules.local/personal.md and verify it loads
  • Create .cursorrules and verify auto-import
  • Set "rulesImport": "none" and verify framework files skipped
  • Verify deduplication when same content exists in multiple locations

💘 Generated with Crush

TheArchitectit and others added 8 commits April 28, 2026 11:03
Adds a project rules system for loading instruction files into the
system prompt, plus auto-import from other AI coding frameworks.

## New rule locations (auto-loaded, sorted alphabetically)
- `.claw/rules/*.md` / `.claw/rules/*.txt` / `.claw/rules/*.mdc`
- `.claw/rules.local/*.md` — personal/local rules (gitignored)
- Existing: `CLAUDE.md`, `CLAUDE.local.md`, `.claw/CLAUDE.md`,
  `.claw/instructions.md`

## Auto-import from other frameworks
When users switch to claw-code from another tool, their existing
rules are automatically detected and loaded:
- Cursor: `.cursorrules`, `.cursor/rules/`
- GitHub Copilot: `.github/copilot-instructions.md`
- Windsurf: `.windsurfrules`, `.windsurfrules/`
- Aider: `.aider.conf.yml` instructions block
- Pi (Plandex): `.plandex/instructions.md`, `.plandex/plan.md`
- OpenCode: `opencode.json` instructions field
- Crush: `.crush/CLAUDE.md`, `.crush/rules/`

## Config option
`rulesImport` in settings.json controls framework auto-import:
- `"auto"` (default) — import from all detected frameworks
- `"none"` — only load .claw/rules/ and CLAUDE.md files
- `["cursor", "copilot"]` — import only from listed frameworks

```json
{
  "rulesImport": "auto"
}
```

💘 Generated with Crush

Assisted-by: GLM 5.1 FP8 via Crush <[email protected]>
Some OpenAI-compatible providers (e.g., GLM-5) omit the `id` field in
streaming and non-streaming responses. Adding #[serde(default)] allows
the parser to accept these responses instead of failing with
"missing field `id`".

Co-Authored-By: Claude Opus 4.7 <[email protected]>
Adds scripts/install.sh that builds the release binary and links it
to ~/.local/bin/claw. Run after code changes to update the CLI.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
When a provider returns HTML (e.g., error page, wrong endpoint) instead
of JSON in an SSE stream, provide a clear error message instead of
hanging or failing with a cryptic parse error.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
When a provider returns a JSON error (e.g., {"error":{"message":"..."}})
without SSE framing (no "data:" prefix), the SSE parser was silently
ignoring it and hanging. Now detects and surfaces these errors.

Also handles HTML responses that lack SSE framing.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
Some providers (GLM, DeepSeek) emit reasoning tokens in `reasoning_content`
or nested `thinking.content` fields instead of `content`. Added support
for these fields so reasoning models work correctly.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
The final streaming chunk from some providers contains only finish_reason
and usage, with no delta field. Made it optional to prevent parse errors.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
When preserve_recent_messages == 0, raw_keep_from equals messages.len(),
causing index out of bounds when accessing session.messages[k].

Added k >= session.messages.len() check to prevent panic.

Reason: Compaction with preserve_recent_messages=0 triggered OOB access
when checking for tool-use/tool-result pair preservation at boundary.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
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