Skip to content

feat(project-rules): add path-scoped project rules plugin (CLAUDE.md + .zcode/rules) - #143

Open
dominiclafleur wants to merge 1 commit into
zai-org:mainfrom
dominiclafleur:feat/project-rules
Open

dominiclafleur wants to merge 1 commit into
zai-org:mainfrom
dominiclafleur:feat/project-rules

Conversation

@dominiclafleur

Copy link
Copy Markdown

Plugin type

  • UI Plugin (MCP App with ui.surfaces)
  • Standard plugin

What it does

ZCode only auto-loads AGENTS.md (apps/zcode-cli/packages/adapters/src/context/index.ts, DEFAULT_PRIORITY_FILES). This plugin gives migrating and multi-tool users their per-path instructions back:

  • .zcode/rules/*.md rule files with optional frontmatter paths: globs (supports *, **, ?, {a,b}, gitignore-style bare patterns, Cursor-style globs: key). A rule is injected as model-visible context when a Read/Edit/Write call touches a matching file, once per session per content.
  • CLAUDE.md from the project root on SessionStart when no AGENTS.md exists.

Community context: this is a hooks-based stopgap answering open requests zai-org/feedback#209 (path-scoped rules), #156 (rules auto-loading / Claude Code migration), and #931 (project instruction discovery) while native support is evaluated; #209 itself notes hooks are a compromise for rule text, so if/when native support lands this plugin can retire.

Components

  • Hooks: SessionStart + PreToolUse (Read|Edit|Write) via hooks/hooks.json, node runtime, zero npm dependencies.

Side effects and safety

  • Reads only .zcode/rules/*.md and root CLAUDE.md/AGENTS.md existence; writes only its own state file. Security-hardened after adversarial review: symlinks resolving outside the project are skipped (exfiltration repro tested), linear glob matcher (no regex blowup; differential-tested on 500k random inputs), lock files verified by inode before unlink (undeletable-lock spin repro tested), per-user state dir with 0600 temp writes, 1 MiB stdin cap, per-file/aggregate byte budgets, 30 KB stdout cap under the hook limit.
  • Never blocks, rewrites, or denies a tool call; always exits 0.

Testing

  • ZCode runtime: installed and enabled in ZCode desktop 3.16.3 via local marketplace (plugins marketplace add <dir> + plugins install project-rules@project-rules-marketplace); hooks take effect on new sessions per the frozen hook-snapshot rule; hook-level e2e verified directly (SessionStart injection; PreToolUse injection with matching glob and dedupe).
  • 45 tests (node test/test.mjs, no framework) including the two exploit repros, lock races, malformed state, caps, and EN/CN README-vs-code consistency checks. Marketplace validate.py passes (53 plugins). Note: build_dist.py currently fails on clean main as well (excalidraw: incomplete build; run pnpm build first), unrelated to this addition.

Licensing

MIT. No third-party code.

…+ .zcode/rules)

Community plugin answering feedback#209, zai-org#156, #931 while native support
is evaluated. Hooks-based stopgap: SessionStart injects CLAUDE.md (when no
AGENTS.md exists) and path-less rules; PreToolUse (Read/Edit/Write)
injects .zcode/rules/*.md whose frontmatter paths globs match the touched
file, once per session per content. No dependencies. Security-hardened
(out-of-project symlinks skipped, linear glob matcher, inode-verified
locks, per-user 0600 state, stdin and byte budgets); 45 tests including
exploit repros. Standard plugin (no UI surfaces).
@panda920

Copy link
Copy Markdown
Collaborator

✅ Internal validation passed. A ZCode maintainer will review the change next; after acceptance, release checks run separately and this PR is closed automatically.

This branch has not been deployed

No deployments
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.

2 participants