This guide covers development setup, building, testing, and contributing to Zeri.
Zeri is built with Laravel Zero, a micro-framework for building console applications. Laravel Zero provides:
- Command structure and routing
- Service container and dependency injection
- Configuration management
- Testing framework (Pest)
- Build system with Box for PHAR creation
- Self-update capabilities
Understanding Laravel Zero concepts will help when developing new features.
- PHP 8.2 or higher
- Composer
- Git
# Clone the repository
git clone https://github.com/hadefication/zeri.git
cd zeri
# Install dependencies
composer install
# Initialize Zeri structure for AI context (recommended)
php application init claudeFor development, use the php application command instead of the built zeri binary:
# Run commands during development
php application init
php application generate claude
php application generate codex
php application add-spec "test-feature"
# After global installation, use:
zeri init
zeri generate claude
zeri generate codex
zeri add-spec "test-feature"./build.shThe build script:
- Optimizes the autoloader for production
- Builds the PHAR with Box
- Restores development autoloader
- Tests the executable
- Shows build statistics
php application app:buildThe executable will be created at builds/zeri.
The build process is configured in box.json:
{
"main": "application",
"output": "builds/zeri",
"directories": ["app", "bootstrap", "config", "stubs", "vendor"],
"files": ["composer.json"],
"compression": "GZ",
"compactors": [
"KevinGH\\Box\\Compactor\\Php",
"KevinGH\\Box\\Compactor\\Json"
]
}php application test
# Or using Pest directly
./vendor/bin/pesttests/Feature/- Feature tests for command functionalitytests/Unit/- Unit tests for individual components
app/
├── Commands/ # CLI commands
│ ├── InitCommand.php
│ ├── GenerateCommand.php
│ ├── AddSpecCommand.php
│ └── SelfUpdateCommand.php
└── Generators/ # AI file generators
├── BaseGenerator.php
├── ClaudeGenerator.php
├── CodexGenerator.php
├── GeminiGenerator.php
└── CursorGenerator.php
config/
├── app.php # Application configuration
├── commands.php # Available commands
└── self-update.php # Self-update configuration
stubs/ # Template files for generation
├── project.md.stub
├── development.md.stub
├── CLAUDE.md.stub
├── GEMINI.md.stub
├── cursor-zeri.mdc.stub
└── templates/
└── spec.md.stub
- InitCommand: Creates
.zeri/structure using stub files - AddSpecCommand: Creates specification files from templates
- GenerateCommand: Processes
.zeri/files through generators - Generators: Read source files and apply templates to create AI-specific outputs
Supported AI agents and their output files:
- Claude:
CLAUDE.md - Gemini:
GEMINI.md - Cursor:
.cursor/rules/zeri.mdc - Codex (OpenAI Codex CLI):
AGENTS.md
The application uses a two-level template system:
- Stubs (
stubs/) - Core templates for initial file creation - Templates (
.zeri/templates/) - User-customizable templates for specifications
Generators extend BaseGenerator and implement:
getOutputFileName(): Target file pathgenerate(): Main generation logicgetGeneratedFiles(): List of all files created (for multi-file generators)
IMPORTANT: Before implementing any new feature, you must create a specification using:
zeri add-spec "feature-name"This creates a structured specification file in .zeri/specs/ that should be filled out with requirements, technical design, and implementation details before coding begins.
Zeri currently supports generating context files for multiple AI agents:
claude→ generatesCLAUDE.mdgemini→ generatesGEMINI.mdcursor→ generates.cursor/rules/zeri.mdccodex→ generatesAGENTS.mdfor the OpenAI Codex CLI
Generate for a specific agent or all:
php application generate codex
php application generate all
# Or after install
zeri generate codex
zeri generate all- Create Specification:
zeri add-spec "feature-name" - Fill out specification in
.zeri/specs/feature-name.mdwith:- Requirements and acceptance criteria
- Technical design and architecture decisions
- Implementation plan and considerations
- Review specification with team/stakeholders if applicable
- Implement feature following the specification
- Mark TODO items as complete during implementation to track progress and manage AI usage limits
- Update specification with any changes made during implementation
- AI context automatically updates when .zeri files change
Important: Always mark TODO checkboxes (- [x]) as you complete each implementation step. This helps track progress and manage AI assistant usage limits effectively.
- Create specification first:
zeri add-spec "new-command" - Create command class in
app/Commands/ - Extend
LaravelZero\Framework\Commands\Command - Define
$signatureand$descriptionproperties - Implement
handle()method - Add to
config/commands.phpif needed (auto-discovery usually handles this)
Example:
<?php
namespace App\Commands;
use LaravelZero\Framework\Commands\Command;
class ExampleCommand extends Command
{
protected $signature = 'example {name} {--option}';
protected $description = 'Example command description';
public function handle()
{
$name = $this->argument('name');
$option = $this->option('option');
$this->info("Hello {$name}!");
return 0;
}
}- Create specification first:
zeri add-spec "new-ai-generator" - Create generator class in
app/Generators/ - Extend
BaseGenerator - Implement required methods
- Create corresponding stub file in
stubs/ - Update
GenerateCommand::getGenerators()
- Create
.stubfile instubs/ - Use
{{PLACEHOLDER}}format for replacements - Update generator to use
createFromStub()method - Handle newline conversion with
\nin placeholders
The zeri add-spec command generates lean, focused specification files with:
- Overview: Brief description of the feature
- Requirements: Essential functional requirements
- Implementation Notes: Technical considerations and dependencies
- TODO: Checkbox list for tracking implementation progress
The TODO section uses markdown checkboxes that can be marked as complete by AI assistants during implementation to track progress and manage usage limits effectively.
Usage: Mark items as complete (- [x]) as you implement each step. This provides clear progress tracking and helps manage AI assistant usage efficiently.
Understanding --force vs Automatic Updates:
- Normal behavior: AI files (CLAUDE.md, GEMINI.md, etc.) automatically reflect changes when you modify
.zeri/source files - Use
--forceonly when: You need to completely regenerate files from scratch (e.g., after template changes or corruption) - Don't use
--forceas part of normal development workflow - it's not needed for reflecting .zeri changes
Key Point: Once AI files are generated and you start working with an AI assistant, those files serve as a stable interface. The AI assistant should reference the structured .zeri/ files for the most current information.
php application generate claude -vvvDuring development, generated files are created in the current directory or specified path. Check:
CLAUDE.mdGEMINI.mdAGENTS.md(Codex).cursor/rules/zeri.mdc
Build fails with missing stubs:
- Ensure all stub files are included in
box.jsondirectories - Check
stubs/directory is being packaged
Self-update signature errors:
- Development uses custom
SelfUpdateCommandto avoid signing issues - Laravel Zero's built-in updater requires PHAR signing
- Production would need proper PHAR signing setup
We use the release.sh script to automate releases end‑to‑end.
- On branch
mainand working tree clean (script will commit pending changes). - Optional: GitHub CLI
ghinstalled and authenticated to auto‑create releases. - Make sure
release.shis executable:chmod +x release.sh.
# Interactive mode (choose patch/minor/major/custom)
./release.sh
# Auto‑increment
./release.sh patch # 1.7.0 → 1.7.1
./release.sh minor # 1.7.0 → 1.8.0
./release.sh major # 1.7.0 → 2.0.0
# Set an explicit version
./release.sh 1.8.5
# Preview actions without changing anything
./release.sh patch --dry-runThe script will:
- Run tests and code formatting.
- Update
config/app.phpversion automatically. - Build the PHAR via
./build.sh(outputs tobuilds/zeri). - Commit the version bump and create tag
vX.Y.Z. - Push
mainand the tag. - Create a GitHub release and attach
builds/zeri(skips ifghnot available).
After completion, verify with:
./builds/zeri --versionOnly if you cannot use release.sh:
- Update
config/app.phpversion. 2)./build.sh. 3) Verify./builds/zeri --version. 4) Commit:git add config/app.php && git commit -m "Bump version to vX.Y.Z". 5) Tag and push:git tag vX.Y.Z && git push origin main && git push origin vX.Y.Z. 6) Create GitHub release (attachbuilds/zeri).
This project uses Laravel Pint for code formatting:
./vendor/bin/pint- Fork the repository
- Create feature branch:
git checkout -b feature/new-feature - Create specification:
zeri add-spec "new-feature" - Fill out specification with requirements and design
- Make changes and add tests following the specification
- Run tests:
php application test - Format code:
./vendor/bin/pint - Build and test:
./build.sh && ./builds/zeri --version - AI context files automatically reflect changes to .zeri files
- Commit and push changes (including specification files)
- Create pull request with reference to specification
- Always create specifications before implementing features using
zeri add-spec - Follow PSR-12 coding standards
- Add tests for new functionality
- Update documentation for new features
- Keep commit messages clear and descriptive
- Ensure backward compatibility
- Include specification files in commits
- Reference specifications in pull requests
# Fix executable permissions
chmod +x builds/zeri
# Fix install permissions
sudo chown $(whoami) /usr/local/bin/zeriCheck PHP version for CLI:
php -v
composer show phpRegenerate autoloader:
composer dump-autoload --optimize- Laravel Zero Documentation - Framework documentation
- Laravel Zero GitHub - Framework source code
- Box Documentation - PHAR building tool
- Pest Documentation - Testing framework
For questions or issues, please open an issue on the GitHub repository.