npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

opencode-rules

v0.6.2

Published

OpenCode plugin that discovers and injects markdown rules into system prompts

Readme

opencode-rules

npm version npm downloads

A lightweight OpenCode plugin that discovers and injects markdown rule files into AI agent system prompts, enabling flexible behavior customization without per-project configuration.

Overview

opencode-rules automatically loads rule files from standard directories and integrates them into AI agent prompts, allowing you to:

  • Define global coding standards that apply across all projects
  • Create project-specific rules for team collaboration
  • Apply conditional rules based on file patterns, prompt keywords, available tools, model, agent, branch, OS, CI, and more
  • Control matching behavior with match: any (default) or match: all
  • Maintain zero-configuration workflow with sensible defaults

This approach allows you to dynamically include rules automatically like style guides for specific languages, guidance on specific actions, etc. Unlike skills, which are called on by the agent, rules use a simple matching approach.

Note: The name opencode-rules is to be concise about what this plugin does. It is in no way affiliated with Anomaly Co. or the official OpenCode project.

Features

  • Dual-format support: Load rules from both .md and .mdc files
  • Conditional rules: Apply rules based on file paths, prompt keywords, or available tools
  • Runtime filtering: Filter rules by model, agent, command, project type, git branch, OS, and CI
  • Branch glob patterns: Match branches using glob patterns (e.g., feature/*, release/**)
  • Matching modes: Use match: any (default) for OR logic or match: all for AND logic
  • Keyword matching: Apply rules when the user's prompt contains specific keywords
  • Tool-based rules: Apply rules only when specific MCP tools are available
  • Global and project-level rules: Define rules at both system and project scopes
  • Context-aware injection: Rules filtered by extracted file paths and user prompts
  • Zero-configuration: Works out of the box with XDG Base Directory specification
  • TypeScript-first: Built with TypeScript for type safety and developer experience
  • Performance optimized: Efficient file discovery and minimal startup overhead
  • TUI sidebar: Real-time sidebar in the OpenCode TUI showing rule status with active/inactive indicators

Quick Start

Installation

opencode plugin opencode-rules@latest --global

Add the plugin to your opencode config:

{
  "$schema": "https://opencode.ai/config.json",
  "plugin": ["opencode-rules@latest"]
}

To enable the TUI sidebar, add the same plugin entry to your TUI config:

// ~/.config/opencode/tui.json
{
  "plugin": ["opencode-rules@latest"]
}

Create Your First Rule

  1. Create the global rules directory:

    mkdir -p ~/.config/opencode/rules
  2. Add a simple rule file:

    cat > ~/.config/opencode/rules/coding-standards.md << 'EOF'
    # Coding Standards
    
    - Use meaningful variable names
    - Follow the project's code style guide
    - Write self-documenting code
    EOF

That's it! The rule will now be automatically injected into all AI agent prompts.

How It Works

  1. Discovery: Scan global and project directories for .md and .mdc files (at plugin init)
  2. Parsing: Extract metadata from files with YAML front matter
  3. Tool Execution: tool.execute.before hook captures file paths before tools run
  4. Message Flow: chat.message hook updates user prompt as messages arrive
  5. Initial Seeding: experimental.chat.messages.transform extracts context from message history once
  6. Rule Filtering: experimental.chat.system.transform evaluates rules based on context and injects into system prompt
  7. State Persistence: After filtering, matched rule paths are written to ~/.opencode/state/opencode-rules/{sessionId}.json for TUI consumption
  8. Compaction Persistence: experimental.session.compacting preserves context during session compression

Performance

  • Rule discovery performed once at plugin initialization
  • Rule content cached with mtime-based invalidation for fast re-reads
  • Incremental session state tracking (set of paths, not message rescanning)
  • Per-session state pruned after 100 concurrent sessions to prevent memory growth
  • Efficient glob matching with minimatch
  • Tool-based path capture is non-blocking with minimal overhead
  • Session context cleaned up when exceeded (LRU eviction)
  • Minimal memory footprint with efficient state management

Configuration

Rule Discovery Locations

Rules are automatically discovered from these directories (including all subdirectories):

  1. Global rules: $OPENCODE_CONFIG_DIR/rules/ if set, otherwise $XDG_CONFIG_HOME/opencode/rules/ (typically ~/.config/opencode/rules/)
  2. Project rules: .opencode/rules/ (in your project root)

Both directories are scanned recursively, allowing you to organize rules into subdirectories.

Supported File Formats

  • .md - Standard markdown files with optional metadata
  • .mdc - Markdown files with optional metadata

Metadata Format

Both .md and .mdc files support optional YAML metadata for conditional rule application:

---
globs:
  - 'src/**/*.ts'
  - 'lib/**/*.js'
keywords:
  - 'refactoring'
  - 'cleanup'
tools:
  - 'mcp_websearch'
  - 'mcp_lsp'
model:
  - gpt-5.3-codex
  - claude-sonnet-4
agent:
  - programmer
command:
  - /plan
  - /review
project:
  - node
  - monorepo
branch:
  - main
  - feature/*
os:
  - linux
  - darwin
ci: false
# Matching mode
match: any
---

Supported Fields

  • globs (optional): Array of glob patterns for file-based matching
    • Rule applies when any file in context matches a pattern
  • keywords (optional): Array of keywords for prompt-based matching
    • Rule applies when the user's prompt contains any keyword
    • Case-insensitive, word-boundary matching (e.g., "test" matches "testing")
    • Does NOT match mid-word (e.g., "test" does NOT match "contest")
  • tools (optional): Array of tool IDs for tool-availability matching
    • Rule applies when any listed tool is available to the agent
    • Uses exact string matching against tool IDs (e.g., mcp_websearch, mcp_bash)
    • Enable debug logging (OPENCODE_RULES_DEBUG=1) to see available tool IDs
  • model (optional): Array of model IDs to match against the current LLM
    • Example: ['gpt-5.3-codex', 'claude-sonnet-4']
  • agent (optional): Array of agent types to match
    • Example: ['programmer', 'planner']
  • command (optional): Array of slash commands to match
    • Example: ['/plan', '/review']
  • project (optional): Array of project type tags to match
    • Detected automatically from marker files (e.g., package.json -> node)
    • Supported tags: node, python, go, rust, monorepo, browser-extension
  • branch (optional): Array of git branch patterns to match
    • Supports exact names and glob patterns (e.g., feature/*, release/**)
    • Uses minimatch for glob matching
  • os (optional): Array of operating systems to match
    • Values: linux, darwin, win32
  • ci (optional): Boolean to match CI environment
    • true matches when running in CI, false matches when not in CI
  • match (optional): Matching mode for multiple conditions
    • any (default): Rule applies if ANY declared condition matches
    • all: Rule applies only if ALL declared conditions match

Note: When a runtime context value is unavailable (e.g., not in a git repository), that dimension is treated as a non-match.

Matching Behavior

  • No metadata: Rule applies unconditionally (always included)
  • Only globs: Rule applies when any context file matches
  • Only keywords: Rule applies when the user's prompt contains any keyword
  • Only tools: Rule applies when any listed tool is available
  • Multiple conditions with match: any (default): Rule applies when ANY condition matches (OR logic across all fields)
  • Multiple conditions with match: all: Rule applies only when ALL declared conditions match

Glob Pattern Reference

The plugin uses minimatch for pattern matching:

| Pattern | Matches | | ----------------------------- | ----------------------------------------------- | | src/**/*.ts | All TypeScript files in src and subdirectories | | **/*.test.ts | All test files at any depth | | src/components/**/*.tsx | React components in components directory | | *.json | JSON files in root directory only | | lib/{utils,helpers}/**/*.js | JavaScript files in specific lib subdirectories |

Included Skill: crafting-rules

This repository includes a crafting-rules/ skill that teaches AI agents how to create well-formatted rules. The skill provides:

  • Rule format reference - Frontmatter fields (globs, keywords, tools, model, agent, command, project, branch, os, ci, match) and markdown body structure
  • Matching strategy guidance - When to use globs vs keywords vs runtime filters vs combinations
  • Pattern extraction workflow - How to identify repeated conversation patterns that should become rules
  • Keyword safety guidelines - Denylist of overly broad keywords to avoid, allowlist of safe alternatives, and an audit checklist

To use the skill, copy skills/crafting-rules/ to ~/.config/opencode/skills/ or reference it directly. The skill triggers when users ask to create rules, codify preferences, or persist guidance across sessions.

Usage Examples

For real-world examples, see the .opencode/rules/ directory in this repository.

Basic Rule File

Create ~/.config/opencode/rules/naming-convention.md:

# Naming Convention Rules

- Use camelCase for variables and functions
- Use PascalCase for classes and interfaces
- Use UPPER_SNAKE_CASE for constants
- Prefix private properties with underscore

Conditional Rule with Metadata

Create ~/.config/opencode/rules/typescript.mdc:

---
globs:
  - '**/*.ts'
  - '**/*.tsx'
---

# TypeScript Best Practices

- Always use `const` and `let`, avoid `var`
- Use interfaces for object types
- Add type annotations for function parameters
- Avoid `any` type without justification
- Enable strict mode in tsconfig.json

This rule only applies when processing TypeScript files.

Keyword-Based Rule

Create ~/.config/opencode/rules/testing.mdc:

---
keywords:
  - 'testing'
  - 'unit test'
  - 'jest'
  - 'vitest'
---

# Testing Best Practices

- Write tests before implementing features (TDD)
- Use descriptive test names that explain the expected behavior
- Mock external dependencies
- Aim for high test coverage on critical paths

This rule applies when the user's prompt mentions testing-related terms.

Tool-Based Rule

Create ~/.config/opencode/rules/websearch.mdc:

---
tools:
  - 'mcp_websearch'
  - 'mcp_codesearch'
---

# Web Search Best Practices

- Always verify search results with multiple sources
- Prefer official documentation over third-party tutorials
- Check publication dates for time-sensitive information

This rule only applies when the websearch or codesearch MCP tools are available.

NOTE: Due to limitations on how opencode provides tools via the SDK, individual MCP tools cannot be matched. Only built-in tools, plugin tools, and whole MCPs can be matched.

Combined Globs and Keywords Rule

Create ~/.config/opencode/rules/test-files.mdc:

---
globs:
  - '**/*.test.ts'
  - '**/*.spec.ts'
keywords:
  - 'testing'
---

# Test File Standards

- Use `describe` blocks to group related tests
- Use `it` or `test` with clear descriptions
- Follow AAA pattern: Arrange, Act, Assert

This rule applies when EITHER a test file is in context OR the user mentions testing (OR logic).

Combined Tools with Other Conditions

Create ~/.config/opencode/rules/lsp-typescript.mdc:

---
tools:
  - 'mcp_lsp'
globs:
  - '**/*.ts'
keywords:
  - 'type checking'
---

# LSP-Enabled TypeScript Development

- Use LSP hover to check inferred types
- Navigate to definitions using goToDefinition
- Find all references before refactoring

This rule applies when the LSP tool is available OR TypeScript files are in context OR the user mentions type checking.

Runtime Environment Filtering

Create ~/.config/opencode/rules/feature-branch-dev.mdc:

---
model:
  - gpt-5.3-codex
  - claude-sonnet-4
agent:
  - programmer
branch:
  - feature/*
os:
  - linux
  - darwin
ci: false
match: all
---

# Feature Branch Development

When working on feature branches locally:

- Create atomic commits with clear messages
- Run tests before pushing
- Keep changes focused and reviewable

This rule uses match: all and only applies when ALL conditions are met: specific model, programmer agent, feature branch, Unix OS, and not in CI.

Organized Rules with Subdirectories

You can organize rules into subdirectories for better management. Rules are discovered recursively from all subdirectories:

~/.config/opencode/rules/
├── coding-standards.md        # Always applied
├── typescript/
│   ├── general.md             # TypeScript general rules
│   └── react.mdc              # React-specific rules (conditional)
├── testing/
│   └── vitest.md              # Testing guidelines
└── security/
    └── api-keys.md            # Security rules

Hidden directories (starting with .) are automatically excluded from discovery.

Project-Specific Rules

Create .opencode/rules/react-components.mdc in your project:

---
globs:
  - 'src/components/**/*.tsx'
---

# React Component Guidelines

- Use functional components with hooks
- Export components as named exports
- Include PropTypes or TypeScript interfaces
- Use React.memo for expensive components
- Co-locate styles with components

Development

Project Structure (Abridged)

The following shows the key source modules. Additional test files (*.test.ts) and type-checking utilities exist but are omitted for brevity.

opencode-rules/
├── src/
│   ├── index.ts              # Main plugin entry point and exports
│   ├── runtime.ts            # OpenCodeRulesRuntime class (hook orchestration)
│   ├── runtime-context.ts    # Context-building helpers (filter context, project detection)
│   ├── runtime-chat.ts       # Chat message handling and text extraction
│   ├── rule-discovery.ts     # Rule file scanning and discovery
│   ├── rule-metadata.ts      # YAML frontmatter parsing
│   ├── rule-filter.ts        # Rule filtering logic (globs, keywords, tools, runtime)
│   ├── message-paths.ts      # Path extraction from messages
│   ├── message-context.ts    # User prompt extraction from message parts
│   ├── session-store.ts      # Per-session state management
│   ├── project-fingerprint.ts # Project type detection (Node.js, Python, etc.)
│   ├── mcp-tools.ts          # MCP tool ID extraction
│   ├── git-branch.ts         # Git branch detection
│   ├── active-rules-state.ts # Persists matched rules per session for TUI
│   ├── debug.ts              # Debug logging utilities
│   ├── utils.ts              # Re-export facade for backwards compatibility
│   ├── test-fixtures.ts      # Shared test fixtures and builders
│   └── *.test.ts             # Unit/integration tests (11 test files)
├── tui/
│   ├── index.tsx             # TUI entrypoint, exports { id, tui }
│   ├── slots/
│   │   └── sidebar-content.tsx # Sidebar widget component
│   ├── data/
│   │   ├── rules.ts          # Rule discovery + formatting for sidebar
│   │   └── rules.test.ts     # Data layer tests
│   └── types/
│       └── opencode-plugin-tui.d.ts  # Vendored type shim
├── docs/
│   └── rules.md              # Detailed usage documentation
├── openspec/                 # Project specifications and proposals
└── dist/                     # Compiled JavaScript output

Key Module Responsibilities

The following highlights the primary runtime modules:

  • runtime.ts - Orchestrates hooks (tool.execute.before, chat.message, experimental.chat.*)
  • runtime-context.ts - Builds RuleFilterContext from session state and environment
  • runtime-chat.ts - Extracts text from chat message parts for keyword matching
  • rule-discovery.ts - Recursively scans directories for .md/.mdc rule files
  • rule-metadata.ts - Parses YAML frontmatter into typed RuleMetadata
  • rule-filter.ts - Evaluates rules against context (globs, keywords, tools, runtime filters); returns FilterResult with formattedRules and matchedPaths
  • message-paths.ts - Extracts file paths from tool invocation arguments and message text
  • message-context.ts - Extracts user prompt text, slash commands, and session IDs from message parts
  • session-store.ts - Manages per-session state with LRU eviction
  • project-fingerprint.ts - Detects project type from marker files (e.g., package.json)
  • mcp-tools.ts - Maps connected MCP clients to tool IDs for tools condition matching
  • git-branch.ts - Resolves current git branch for branch condition matching
  • active-rules-state.ts - Persists which rules matched per session to ~/.opencode/state/opencode-rules/{sessionId}.json for TUI consumption (atomic writes, per-session queuing)
  • utils.ts - Thin facade re-exporting from decomposed modules

TUI Sidebar

The plugin registers a sidebar_content slot in the OpenCode TUI, displaying all discovered rules (global and project-local) with their active state and metadata.

Requirements: @opencode-ai/plugin ^1.3.7 with TUI support.

What it shows:

  • Collapsible "Project" and "Global" sections grouping rules by scope
  • Active/inactive status indicators (green bullet for active, muted for inactive) based on persisted state from the current session
  • Condition summary for conditional rules ("always active" for unconditional ones)
  • Expandable detail panel with all metadata fields (globs, keywords, tools, model, agent, command, project, branch, os, ci, match)
  • Loading, error, and empty states

Behavior:

  • Active rules are sorted to the top within each section
  • Subscribes to message.updated and session.status events for real-time refresh (150ms debounce, filtered by session ID)
  • Active state is read from ~/.opencode/state/opencode-rules/{sessionId}.json, written by the server plugin after each rule evaluation

Build and Test

# Install dependencies
bun install

# Run tests in watch mode
bun run test

# Run tests once
bun run test:run

# Build the project
bun run build

# Watch for changes and rebuild
bun run dev

# Format code
bun run format

# Lint code
bun run lint

Tech Stack

  • TypeScript - Type-safe development
  • @opencode-ai/plugin - OpenCode plugin framework
  • Vitest - Fast unit testing
  • Prettier - Code formatting
  • ESLint - Linting and code quality

Architecture

This plugin uses OpenCode's hook system for incremental, stateful rule injection:

Hook-Based Approach

  1. tool.execute.before - Authoritative path capture from tool execution

    • Fires before each tool runs (read, edit, write, glob, grep, etc.)
    • Captures filePath or path arguments authoritative from the tool definition
    • Updates session state with normalized, verified context paths
    • Provides real-time context as tools are executed
  2. chat.message - Incremental user prompt capture

    • Fires as each user message arrives
    • Extracts and stores the latest user prompt text
    • Enables keyword-based rule matching across the conversation flow
  3. experimental.chat.messages.transform - One-time seeding fallback

    • Fires before the first LLM call only (skipped on subsequent turns)
    • Seeds session state from full message history if needed
    • Provides fallback context extraction from all visible messages
    • Ensures rules apply even if initial context wasn't captured by tool hooks
  4. experimental.chat.system.transform - Rule injection and filtering

    • Fires before each LLM system prompt is constructed
    • Receives full runtime filter context: model, agent, command, project type, git branch, OS, and CI environment
    • Reads discovered rule files and filters based on:
      • Extracted file paths from session state (globs)
      • Latest user prompt (keywords)
      • Available tool IDs (tools)
      • Runtime environment (model, agent, command, project, branch, OS, CI)
    • Command is inferred from the leading slash token (first token) of the latest user prompt
    • Appends formatted rules to the system prompt
  5. experimental.session.compacting - Compaction context preservation

    • Fires when a session is compacted (summarized)
    • Injects current context paths into the compaction context
    • Prevents rules from being lost during session compression

Experimental API Notice

This plugin depends on experimental OpenCode APIs:

  • experimental.chat.messages.transform (fallback seeding)
  • experimental.chat.system.transform (rule injection)
  • experimental.session.compacting (compaction context)

These APIs may change in future OpenCode versions. Check OpenCode release notes when upgrading.

Debug Logging

To enable debug logging, set the OPENCODE_RULES_DEBUG environment variable:

OPENCODE_RULES_DEBUG=1 opencode

This will log information about:

  • Rule discovery (files found)
  • Cache hits/misses
  • Rule filtering (which rules are included/skipped)
  • Available tool IDs (useful for writing tools conditions)

Troubleshooting

Rules Not Appearing

  1. Verify directories exist: ~/.config/opencode/rules/ and/or .opencode/rules/
  2. Check file extensions are .md or .mdc
  3. Ensure files with metadata have properly formatted YAML
  4. Enable debug logging (OPENCODE_RULES_DEBUG=1) to see which rules are being matched

Common Issues

  • Missing directories: Plugin gracefully handles missing directories
  • Invalid YAML: Metadata parsing errors are logged but don't crash the plugin
  • Pattern mismatches: Use relative paths from project root for glob patterns

Contributing

We welcome contributions! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Ensure all tests pass: bun run test:run
  5. Format code: bun run format
  6. Submit a pull request

Development Guidelines

  • Follow existing code style (Prettier configuration)
  • Add comprehensive tests for new features
  • Update documentation for API changes
  • Use TypeScript for all new code

See Also