Overview
pyrig’s most powerful feature is its multi-package inheritance architecture. You can create a personal pyrig package with your own standards, add it as a dependency to any project, and havepyrig init automatically apply everything — configs, tools, CLI commands, and builders.
This guide shows you how to:
- Create a personal pyrig package
- Override default behaviors using the
.Ipattern - Understand dependency chain discovery
- Package and distribute your extensions
Understanding the .I Pattern
The .I pattern is pyrig’s mechanism for automatic subclass discovery and instantiation. It stands for Instance and provides access to the final (leaf) implementation in the dependency chain.
How It Works
Every extensible class in pyrig inherits fromDependencySubclass, which provides:
ToolName.I, pyrig:
- Discovers all packages that depend on pyrig
- Searches for
ToolNamesubclasses in<package>.rig.tools - Validates that exactly one leaf subclass exists
- Returns an instance of that subclass
Example: Using .I
Creating a Personal pyrig Package
A personal pyrig package lets you standardize your workflow across all projects.Step 1: Initialize Your Package
Step 2: Create the Extension Structure
Create the required directory structure:Step 3: Override a Tool
Createmy_pyrig/rig/tools/linter.py:
Linter.I with your package installed, it will use your implementation!
Step 4: Add a Custom Config
Createmy_pyrig/rig/configs/company_config.py:
pyrig init or pyrig mkroot runs, this config will be automatically discovered and validated!
Step 5: Add a Custom CLI Command
Createmy_pyrig/rig/cli/subcommands/deploy.py:
Dependency Chain Discovery
pyrig usesDependencyGraph to discover all packages in the dependency chain. Here’s how it works:
Discovery Algorithm
- Build Dependency Graph: Parse all installed packages and their dependencies
- Find Dependents: Identify all packages that depend on
pyrig - Topological Sort: Order packages from base (pyrig) to leaves (your project)
- Discover Subclasses: For each package, search
<package>.rig.<category>for subclasses
Example Chain
my-project calls Linter.I:
- Searches
pyrig.rig.tools.linter→ finds baseLinter - Searches
my_pyrig.rig.tools.linter→ finds yourLinter(overrides base) - Searches
my_project.rig.tools.linter→ if exists, overrides yours - Returns the final (leaf) implementation
The .L Property
The .L property (Leaf) returns the class, not an instance:
Overriding Default Behaviors
Override Tool Commands
Extend or modify any tool’s behavior:Override Config Defaults
Change default configuration values:Override Badge URLs
Customize README badges:Override Dev Dependencies
Change which dependencies are added for a tool:Package Structure Best Practices
Minimal Package
For simple overrides:Full-Featured Package
For comprehensive standards:Testing Your Extensions
Test that your overrides work correctly:Using Your Package
In New Projects
In Existing Projects
Advanced Patterns
Conditional Overrides
Apply different behaviors based on context:Shared Utilities
Create utilities for all your projects:Multi-Layer Inheritance
Create organization, team, and project layers:Next Steps
- Creating Custom Tools - Deep dive into tool creation
- Packaging Guide - Learn about the uv_build backend
- Config Architecture - Understanding config system
- Tool Architecture - Understanding tool system