Thanks for taking the time to contribute. This doc covers everything you need to go from zero to pull request.
Never contributed to an open source project before? Numen is a good place to start. The codebase is a standard Laravel 12 app — if you've written Laravel before, you'll feel at home immediately.
Look for issues labeled good first issue — these are scoped to be approachable without deep knowledge of the pipeline internals.
When in doubt, open a discussion or comment on an issue before writing code. Saves everyone time.
- PHP 8.4+ with extensions:
pdo_sqlite,redis(or useQUEUE_CONNECTION=database) - Composer 2.x
- Node.js 18+ and npm
- Redis (optional — can use database queue driver for dev)
- An Anthropic API key (minimum), or OpenAI / Azure
# Fork the repo on GitHub, then clone your fork
git clone https://github.com/YOUR_USERNAME/numen.git
cd numen
# Add the upstream remote
git remote add upstream https://github.com/byte5labs/numen.git
# Install PHP dependencies
composer install
# Install JS dependencies
npm install
# Configure
cp .env.example .env
php artisan key:generateEdit .env — at minimum set your API key:
ANTHROPIC_API_KEY=sk-ant-your-key-here
# If you don't have Redis, use database queue:
QUEUE_CONNECTION=database# Database setup
touch database/database.sqlite
php artisan migrate
# If using database queue:
php artisan queue:table
php artisan migrate
# Seed demo data
php artisan db:seed --class=DemoSeeder
# Run the app (three terminals)
php artisan serve
php artisan queue:work
npm run devVisit http://localhost:8000. You're in.
php artisan testOr with coverage (requires Xdebug or PCOV):
php artisan test --coverageFor a specific test file:
php artisan test tests/Feature/ContentApiTest.phpWe use Laravel Pint for code formatting and Larastan (PHPStan level 5) for static analysis. Both are already in composer.json. The project currently has 134+ tests — all new behaviour requires tests.
# Check for style issues
./vendor/bin/pint --test
# Fix all style issues
./vendor/bin/pint
# Run static analysis
./vendor/bin/phpstan analysePint runs against the laravel preset. All three gates must pass before submitting a PR — CI enforces them and will fail if any reports errors:
./vendor/bin/phpstan analyse— PHPStan/Larastan level 5, zero errors./vendor/bin/pint --test— zero style issuesphp artisan test— all tests green
# Make sure your main is up to date
git checkout main
git pull upstream main
# Create a feature branch
git checkout -b feat/your-feature-name
# Or for bug fixes:
git checkout -b fix/what-you-are-fixingBranch naming convention:
feat/— new featuresfix/— bug fixesdocs/— documentation onlyrefactor/— code changes without behavior changetest/— test additions or fixeschore/— dependency updates, CI config
A few guidelines:
- Tests for new behavior. If you add a new pipeline stage type, new API endpoint, or provider — add a test.
- One thing per PR. Focused PRs get reviewed faster. Don't bundle unrelated changes.
- Don't break the API surface. The
/api/v1/*routes andContentResourceresponse shape are public contracts. Changes that break these need a deprecation path and a major version bump. - PHPDoc for public methods. Especially on
Agent,LLMProvider, and anything inapp/Services/AI/. - Use the LLM layer, not direct HTTP. AI calls go through
LLMManager(or theAgentbase class). Don't instantiate providers directly.
All three gates — PHPStan (level 5), Pint (code style), and Tests — must pass before opening a PR. CI enforces all three.
# Run tests
php artisan test
# Fix code style
./vendor/bin/pint
# Run static analysis (Larastan level 5)
./vendor/bin/phpstan analyse
# Make sure nothing is obviously broken
php artisan route:list
php artisan config:clearPush your branch and open a pull request against main on the upstream repo.
PR description should include:
- What — what does this change do?
- Why — why is this needed?
- How to test — steps to verify the change works
- Breaking changes — if any, call them out explicitly
Small PRs are reviewed faster. If your change is large, open a draft PR early and ask for feedback on the approach before writing all the code.
Include:
- PHP version (
php --version) - Laravel version (
php artisan --version) - Which AI provider you're using
- Steps to reproduce (minimal)
- Expected vs actual behavior
- Relevant log output (check
storage/logs/laravel.log)
Open an issue and describe:
- What problem you're trying to solve
- How you'd expect the feature to work
- Any alternatives you've considered
If it's a large feature, consider opening a discussion first.
We follow the Contributor Covenant. Short version: be respectful, be constructive, assume good intent.
Issues and PRs where people are dismissive or hostile get closed. This is a small project; we can afford to be strict about this.
app/
├── Agents/ # AI agents — extend Agent to add new personas
├── Pipelines/ # Pipeline execution engine
├── Services/AI/ # LLM layer: LLMManager, providers, cost tracking
├── Models/ # 16 Eloquent models
├── Jobs/ # Queue jobs (one per pipeline stage)
├── Events/ # Pipeline and content lifecycle events
└── Http/Controllers/
├── Api/ # Public + authenticated REST API
└── Admin/ # Inertia.js admin controllers
config/
└── numen.php # All Numen config — start here for any AI behavior
database/
├── migrations/ # Schema
└── seeders/ # DemoSeeder for local dev
tests/
├── Feature/ # HTTP + integration tests
└── Unit/ # Unit tests for services, agents
- Create
app/Agents/Types/YourAgent.phpextendingAgent - Implement
execute(AgentTask $task): AgentResult - Register in
AgentFactory(add a newmatcharm) - Add a pipeline stage that references your agent type
- Write a test
- Create
app/Services/AI/Providers/YourProvider.phpimplementingLLMProvider - Bind it in
AppServiceProvider - Register it in
LLMManager's provider map - Add env vars + config keys in
config/numen.php - Update
.env.example
Open an issue tagged question, or start a GitHub Discussion. We're a small team — response times vary, but we read everything.