<div align="center">

# rinco-pi-rule

**Let Pi detect your project stack and safely add matching ECC rules to `AGENTS.md` with one command.**

[![Pi Extension](https://img.shields.io/badge/Pi-extension-6f42c1?style=flat-square)](https://pi.dev) [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D20.6-339933?style=flat-square&logo=node.js&logoColor=white)](https://nodejs.org/) [![TypeScript](https://img.shields.io/badge/TypeScript-strict-3178C6?style=flat-square&logo=typescript&logoColor=white)](https://www.typescriptlang.org/) [![Tests](https://img.shields.io/badge/tests-Vitest-6E9F18?style=flat-square&logo=vitest&logoColor=white)](https://vitest.dev/) [![License](https://img.shields.io/badge/license-MIT-C7B8F5?style=flat-square)](LICENSE)

[Features](#features) · [Installation](#installation) · [Usage](#usage) · [Stack detection](#stack-detection) · [How it works](#how-it-works) · [Development](#development) · [Troubleshooting](#troubleshooting)

[简体中文](README.zh-CN.md)

</div>

`rinco-pi-rule` is an offline, deterministic [Pi](https://pi.dev) extension. Run `/rules:init` to scan the current project, detect Python, JavaScript/TypeScript, and React, then merge the matching [Everything Claude Code (ECC)](https://github.com/affaan-m/ECC) rules into the project-level `AGENTS.md`. Repeated runs replace only the managed block and preserve team-authored content.

## Features

- **Zero-config stack detection** — Selects rules from project markers, dependencies, and source extensions. No configuration file required.
- **Preserves manual rules** — Manages only its marked ECC block and leaves the rest of `AGENTS.md` untouched.
- **Offline and reproducible** — Vendors rules from a pinned ECC commit and makes no network request at runtime.
- **Safe writes** — Uses atomic replacement and stops on malformed markers, duplicate markers, or symbolic links.
- **No generic command collision** — Uses the namespaced `/rules:init` command instead of `/init`.
- **Deterministic output** — Rules are sorted by layer and filename, with commit-pinned GitHub URLs for every cross-reference.

## Installation

### Install from npm (recommended)

```bash
pi install npm:rinco-pi-rule
```

The published package is available on [npm](https://www.npmjs.com/package/rinco-pi-rule).

### Install from GitHub

```bash
pi install git:github.com/Rinisnotarobot/rinco-pi-rule
```

### Install from a local checkout

```bash
git clone https://github.com/Rinisnotarobot/rinco-pi-rule.git
cd rinco-pi-rule
pi install "$PWD"
```

Install for the current project only:

```bash
pi install -l "$PWD"
```

> [!IMPORTANT]
> Pi extensions run with your user permissions. Review the source before installing any third-party extension.

## Usage

### Requirements

| Dependency | Version |
| --- | --- |
| Node.js | `>=20.6.0` |
| `@earendil-works/pi-coding-agent` | Any compatible version (peer dependency) |

Start Pi in the target project and run:

```text
/rules:init
```

The extension scans the project, detects the stack, and atomically creates or updates the managed ECC rules block in `AGENTS.md`. Subsequent runs update only the content between the managed markers.

### Generated output

On the first run, the extension creates `AGENTS.md`. If the file already exists, it keeps the existing content and appends a managed block:

```markdown
# Team rules

This content is maintained by the team and will not be changed.

<!-- rinco-pi-rule:ecc:start -->
## ECC-derived Rules for Pi (managed)

...rules selected for the detected project stack...
<!-- rinco-pi-rule:ecc:end -->
```

Later `/rules:init` runs update only the content between those markers.

> [!WARNING]
> Do not duplicate the markers or remove only one of them. If markers are missing, reversed, or duplicated, the extension stops instead of risking damage to `AGENTS.md`.

## Stack detection

Rules are layered in a fixed `common → python → typescript → react` order. Later layers are more specific and take precedence when guidance conflicts.

<p>
  <img alt="common rules" src="https://img.shields.io/badge/common-always-555?style=flat-square">
  <img alt="Python rules" src="https://img.shields.io/badge/python-detected-3776ab?style=flat-square&amp;logo=python&amp;logoColor=white">
  <img alt="TypeScript rules" src="https://img.shields.io/badge/typescript-detected-3178c6?style=flat-square&amp;logo=typescript&amp;logoColor=white">
  <img alt="React rules" src="https://img.shields.io/badge/react-detected-149eca?style=flat-square&amp;logo=react&amp;logoColor=white">
</p>

| Rule layer | Selected when |
| --- | --- |
| `common` | Always |
| `python` | Python files or markers such as `.py`, `.pyi`, `pyproject.toml`, `requirements*.txt`, `setup.py`, or `uv.lock` exist |
| `typescript` | JS/TS source files, `package.json`, JS lockfiles, Deno configuration, or TypeScript configuration exist |
| `react` | React-family dependencies are declared in `package.json`, or `.jsx` / `.tsx` files exist |

React automatically includes the TypeScript layer, and JavaScript projects also use ECC's `typescript` rules. Mixed repositories, such as Python plus React, receive every matching layer.

The scanner ignores common dependency and generated directories:

```text
.git  node_modules  dist  build  coverage  .next  .turbo
.venv  venv  __pycache__  vendor  target  .cache
```

A scan processes at most 5,000 entries to avoid unbounded traversal in very large projects.

## How it works

```mermaid
flowchart LR
    command["/rules:init"] --> detect["Scan markers, dependencies, and source files"]
    detect --> layers["Select common / python / typescript / react"]
    layers --> snapshot["Load the vendored ECC snapshot"]
    snapshot --> adapt["Apply reviewed Pi overrides"]
    adapt --> transform["Remove frontmatter, scope headings, pin links"]
    transform --> merge["Merge the AGENTS.md managed block"]
    merge --> atomic["Write atomically"]
```

Rules are loaded from the extension's own `rules/ecc/` directory rather than the target project's working directory. Every upstream rule has a matching reviewed derivative under `rules/pi/`. The Pi rule set preserves applicable language and framework guidance while replacing harness-specific agents, hooks, skills, configuration, model, task, and automation assumptions with capability-driven native Pi workflows.

During generation, the extension:

1. Applies matching Pi-adapted overrides while preserving the original ECC snapshot.
2. Removes path frontmatter from ECC files.
3. Nests rule headings below the managed section.
4. Rewrites relative ECC links to commit-pinned GitHub URLs.
5. Sorts rules deterministically by layer and filename.
6. Preserves existing file permissions before the atomic rename.

### Safety and reproducibility

The upstream rules are pinned to ECC commit `623f2c0`. Original Markdown remains under `rules/ecc/`, with checksums in [`rules/ecc/SHA256SUMS`](rules/ecc/SHA256SUMS); reviewed derivatives live under `rules/pi/`. `/rules:init` performs no remote download and does not modify hand-written rules outside the managed markers.

To prevent accidental data loss, the extension refuses to proceed when:

- `AGENTS.md` is a symbolic link.
- `AGENTS.md` is not a regular file.
- Managed markers are incomplete, reversed, or duplicated.
- The command receives unsupported arguments.

## Project contents

| Path | Purpose |
| --- | --- |
| [`index.ts`](index.ts) | Pi extension entry point and `/rules:init` command registration |
| [`src/init.ts`](src/init.ts) | Atomic AGENTS.md merge with file mutation queue |
| [`src/detect-project.ts`](src/detect-project.ts) | Stack detection: markers, dependencies, and source extensions |
| [`src/agents-md.ts`](src/agents-md.ts) | Rule transformation, rendering, and managed block merging |
| [`src/rules.ts`](src/rules.ts) | ECC snapshot loading, Pi override selection, and layer ordering |
| [`rules/ecc/`](rules/ecc/) | Unmodified pinned ECC rule snapshots with SHA256 checksums |
| [`rules/pi/`](rules/pi/) | Reviewed Pi-adapted overrides keyed by the same relative paths |
| [`docs/CONTRIBUTING.md`](docs/CONTRIBUTING.md) | Local development, testing guidance, and pull request checklist |
| [`tests/`](tests/) | Vitest test suite for detection, merging, and extension behavior |

## Development

### Prerequisites

- [Node.js](https://nodejs.org/) 20.6 or later
- [Pi](https://pi.dev)

Install development dependencies:

```bash
npm install
```

### Available commands

<!-- AUTO-GENERATED: package-scripts:start -->
<!-- Source: package.json#scripts. Do not edit manually. -->

| Command | Description |
| --- | --- |
| `npm test` | Run the complete Vitest suite once. |
| `npm run test:watch` | Run Vitest in watch mode and retest when files change. |
| `npm run test:coverage` | Run all tests with V8 coverage (80% minimum threshold). |
| `npm run typecheck` | Run TypeScript type checking without emitting JavaScript. |
| `npm run check` | Run type checking, tests, and the package dry run. |
| `npm run pack:dry-run` | Inspect the publishable package with `npm pack --dry-run` without publishing it. |

<!-- AUTO-GENERATED: package-scripts:end -->

Run the test suite:

```bash
npm test
```

Watch for changes:

```bash
npm run test:watch
```

Verify tests, types, and package contents:

```bash
npm run check
```

Vitest covers the detection logic, managed block merging, rule transformations, and extension lifecycle. See [`docs/CONTRIBUTING.md`](docs/CONTRIBUTING.md) before contributing.

## Troubleshooting

### Can native Pi use the generated rules without any plugins?

Yes. Generating or updating the managed block with `/rules:init` requires this extension, but consuming it does not. Once `AGENTS.md` exists, native Pi loads it as a built-in context file. The mandatory workflows use Pi's core `read`, `write`, `edit`, and `bash` tools; skills, extensions, reviewers, task lists, browser tools, and sub-agents are optional enhancements with documented fallbacks.

This was verified with Pi `0.84.1` in an isolated configuration using `--no-extensions --no-skills --no-prompt-templates --no-themes`. Native Pi successfully loaded all 26 generated `common`, Python, TypeScript, and React rules from `AGENTS.md`. Keep the generated file in the repository if users should receive the rules without installing this extension. Without the extension, `/rules:init` itself is not available and rule updates must be generated elsewhere or applied manually.

### Will it overwrite my existing `AGENTS.md`?

No. If no managed block exists, the extension appends one. If a managed block exists, it replaces only that block. Everything outside the markers is preserved.

### Why not fetch the latest ECC rules at runtime?

A pinned snapshot enables offline use, stable tests, and reproducible output. It also prevents unreviewed upstream changes from silently altering project guidance.

### Why is `AGENTS.md` larger in React projects?

React projects receive the `common`, `typescript`, and `react` layers. The complete selected rules are intentionally embedded so Pi can load them directly as project context.

### Does `/rules:init --force` work?

No, and it is not needed. The command safely updates its managed block by default. Any extra argument produces a usage warning without writing a file.

### Can I select individual rule files?

Not currently. This version loads complete rule layers based on the detected project stack.

Third-party attribution is documented in [`THIRD-PARTY-NOTICES`](THIRD-PARTY-NOTICES), and the project license is available in [`LICENSE`](LICENSE).