Skip to content

Configuration Reference

FilePurpose
~/.karajan/kj.config.ymlMain configuration (or $KJ_HOME/kj.config.yml)
<project>/.karajan.ymlProject-level pricing overrides only
<project>/.karajan/roles/*.mdProject-level role instructions
<project>/.karajan/plugins/*.jsProject-level plugins

CLI flags override config file values. Config file values override defaults.


coder: claude # AI agent that writes code
reviewer: codex # AI agent that reviews code
review_mode: standard # Review strictness profile
max_iterations: 5 # Max coder-reviewer loop iterations
review_rules: ./review-rules.md # Path to custom review rules
coder_rules: ./coder-rules.md # Path to custom coder rules
base_branch: main # Git base branch for diffs
max_budget_usd: null # Max budget in USD (null = unlimited)
FieldTypeDefaultDescription
coderstringclaudeAgent CLI name: claude, codex, gemini, aider, or a custom plugin
reviewerstringcodexAgent CLI name for code review
review_modeenumstandardparanoid | strict | standard | relaxed | custom
max_iterationsnumber5Maximum coder-reviewer loop iterations (1-20)
review_rulesstring./review-rules.mdPath to reviewer instruction file
coder_rulesstring./coder-rules.mdPath to coder instruction file
base_branchstringmainGit branch used for diff comparison
max_budget_usdnumber | nullnullEstimated session budget cap in USD (based on API-equivalent pricing). null = unlimited

Override provider and model per role:

roles:
coder:
provider: claude
model: claude-opus-4-6
reviewer:
provider: codex
model: null
planner:
provider: null
model: null
refactorer:
provider: null
model: null
solomon:
provider: null
model: null
researcher:
provider: null
model: null
tester:
provider: null
model: null
security:
provider: null
model: null
triage:
provider: null
model: null
discover:
provider: null
model: null
hu-reviewer:
provider: null
model: null
architect:
provider: null
model: null
audit:
provider: null
model: null
impeccable:
provider: null
model: null
commiter:
provider: null
model: null
RolePurpose
coderWrites code and tests
reviewerReviews code for quality, security, correctness
plannerGenerates implementation plans before coding
refactorerRefactors code after approval
solomonResolves conflicts between coder and reviewer
researcherAnalyzes codebase before planning
testerAudits test quality after review
securityOWASP security audit
triageClassifies task complexity
discoverPre-execution gap detection
hu-reviewerUser story certification
architectSolution architecture design
auditRead-only codebase health audit
impeccableAutomated UI/UX design audit
commiterGit automation

fallback: the chain that runs when the first choice cannot

Section titled “fallback: the chain that runs when the first choice cannot”

Any role accepts a fallback, and a fallback accepts its own, so the chain is as long as you need it (five links, then kj warns and ignores the rest):

roles:
reviewer:
provider: codex
model: gpt-5.6-terra
fallback:
provider: codex # same provider, another model
model: gpt-5.6
max_wait_hours: 12
fallback:
provider: claude # or another provider entirely
model: null # null = that provider's default
FieldTypeDefaultDescription
providerstring—The agent this link uses. Required.
modelstring | nullnullThe model for this link. null asks for the provider’s own default.
max_wait_hoursnumber12On a quota wall, wait rather than switch when the cooldown is shorter than this. A retired model never waits: nothing will bring it back.
fallbackobjectnoneThe next link. Same shape, recursively.

Two things worth knowing, because they are not obvious:

  • The chain is taken in the order you wrote it, and the provider’s default model is appended as the last link when (and only when) you pinned a model. That step used to happen silently inside each agent, ahead of anything you had declared; since 4.33.0 it is the tail of your chain, where you can see it.
  • A link that repeats the primary is skipped, and so is one whose provider does not exist, with a warning naming it. Retrying the same provider and model is not progress, it only looks like it.

When the whole chain is exhausted, the error says what was tried and in what order, and kj remembers a model it watched a provider retire so the next run does not pay for the same dead call. It never edits your pin: it names the line for you to change.


Enable or disable optional roles:

pipeline:
planner:
enabled: false
refactorer:
enabled: false
solomon:
enabled: false
researcher:
enabled: false
tester:
enabled: false
security:
enabled: false
triage:
enabled: false
reviewer:
enabled: true
discover:
enabled: false
hu-reviewer:
enabled: false
architect:
enabled: false
audit:
enabled: false
impeccable:
enabled: false
commiter:
enabled: false

All optional roles are disabled by default. Enable them with --enable-<role> CLI flags or in config.


development:
methodology: tdd
require_test_changes: true
test_file_patterns:
- /tests/
- /__tests__/
- .test.
- .spec.
source_file_extensions:
- .js
- .jsx
- .ts
- .tsx
- .py
- .go
- .java
- .rb
- .php
- .cs
FieldTypeDefaultDescription
methodologyenumtddtdd (require tests first) or standard (tests optional)
require_test_changesbooleantrueWhen TDD, require test file changes alongside source changes
test_file_patternsstring[]See abovePatterns to identify test files
source_file_extensionsstring[]See aboveSource file extensions to monitor for TDD enforcement

coder_options:
model: null
auto_approve: true
FieldTypeDefaultDescription
modelstring | nullnullModel override for coder (e.g., claude-opus-4-6)
auto_approvebooleantrueAllow coder to approve its own output if reviewer approves

reviewer_options:
output_format: json
require_schema: true
model: null
deterministic: true
retries: 1
fallback_reviewer: codex
FieldTypeDefaultDescription
output_formatstringjsonReviewer output format (always JSON for structured review)
require_schemabooleantrueValidate reviewer output matches expected schema
modelstring | nullnullModel override for reviewer
deterministicbooleantrueUse deterministic mode for reproducible reviews
retriesnumber1Number of reviewer retries on parse error
fallback_reviewerstringcodexFallback provider if primary reviewer fails

sonarqube:
enabled: true
host: http://localhost:9000
external: false
container_name: karajan-sonarqube
network: karajan_sonar_net
token: null
project_key: null
admin_user: admin
admin_password: null
quality_gate: true
enforcement_profile: pragmatic
max_scan_retries: 3
gate_block_on:
- new_reliability_rating=E
- new_security_rating=E
- new_maintainability_rating=E
- new_coverage<80
- new_duplicated_lines_density>5
fail_on:
- BLOCKER
- CRITICAL
ignore_on:
- INFO
volumes:
data: karajan_sonar_data
logs: karajan_sonar_logs
extensions: karajan_sonar_extensions
timeouts:
healthcheck_seconds: 5
compose_up_ms: 300000
compose_control_ms: 120000
logs_ms: 30000
scanner_ms: 900000
coverage:
enabled: false
command: null
timeout_ms: 300000
block_on_failure: true
lcov_report_path: null
scanner:
sources: "src,public,lib"
exclusions: "**/node_modules/**,**/dist/**,**/build/**,**/*.min.js"
test_inclusions: "**/*.test.js,**/*.spec.js,**/tests/**,**/__tests__/**"
coverage_exclusions: "**/tests/**,**/__tests__/**,**/*.test.js,**/*.spec.js"
disabled_rules:
- "javascript:S1116"
- "javascript:S3776"
FieldTypeDefaultDescription
enabledbooleantrueEnable SonarQube scanning
hoststringhttp://localhost:9000SonarQube server URL
externalbooleanfalseIf true, assume an external SonarQube (don’t manage Docker)
tokenstring | nullnullAuthentication token. Prefer KJ_SONAR_TOKEN env var
quality_gatebooleantrueCheck quality gate status after scan
enforcement_profileenumpragmaticpragmatic (block on ERROR only) or paranoid (block on anything not OK)
max_scan_retriesnumber3Retry failed scans
SeverityMeaning
BLOCKERApp crash, data loss
CRITICALSecurity hole, logic error
MAJORQuality issue affecting function
MINORCode smell, inconsistency
INFOConvention, clarification

git:
auto_commit: false
auto_push: false
auto_pr: false
auto_rebase: true
branch_prefix: feat/
FieldTypeDefaultDescription
auto_commitbooleanfalseCommit all changes after approval
auto_pushbooleanfalsePush branch to origin after commit
auto_prbooleanfalseCreate pull request to base_branch
auto_rebasebooleantrueRebase on base_branch before pushing
branch_prefixstringfeat/Prefix for branch names (e.g., feat/, fix/)

The Git automation flow after approval: rebase (if enabled) → commit → push → PR.


session:
max_iteration_minutes: 15
max_total_minutes: 120
max_planner_minutes: 60
max_agent_silence_minutes: 20
fail_fast_repeats: 2
repeat_detection_threshold: 2
max_sonar_retries: 3
max_reviewer_retries: 3
max_tester_retries: 1
max_security_retries: 1
expiry_days: 30
FieldTypeDefaultDescription
max_iteration_minutesnumber15Time limit per coder-reviewer cycle
max_total_minutesnumber120Total session time limit
max_planner_minutesnumber60Hard runtime cap for planner-only execution (kj_plan/kj plan)
max_agent_silence_minutesnumber20Kill agent run if no output is received for this many minutes
fail_fast_repeatsnumber2Exit after N repeated identical failures
repeat_detection_thresholdnumber2Iterations before detecting repeating patterns
max_sonar_retriesnumber3Max SonarQube scan retries
max_reviewer_retriesnumber3Max reviewer retries on parse error
max_tester_retriesnumber1Max test audit retries
max_security_retriesnumber1Max security audit retries
expiry_daysnumber30Auto-cleanup sessions older than this

budget:
warn_threshold_pct: 80
currency: usd
exchange_rate_eur: 0.92
pricing:
claude:
input_per_million: 0.003
output_per_million: 0.015
FieldTypeDefaultDescription
warn_threshold_pctnumber80Warn when estimated spending reaches this % of max_budget_usd
currencyenumusdDisplay currency: usd or eur
exchange_rate_eurnumber0.92EUR to USD exchange rate
pricingobjectBuilt-inPer-agent pricing rates for estimation (input_per_million, output_per_million)

The pricing section can also be set in a project-level .karajan.yml file to override per-project estimation rates.


retry:
max_attempts: 3
initial_backoff_ms: 1000
max_backoff_ms: 30000
backoff_multiplier: 2
jitter_factor: 0.1
FieldTypeDefaultDescription
max_attemptsnumber3Max retry attempts for transient API errors
initial_backoff_msnumber1000Initial backoff delay (1 second)
max_backoff_msnumber30000Maximum backoff delay (30 seconds)
backoff_multipliernumber2Exponential backoff multiplier
jitter_factornumber0.1Random jitter as fraction of backoff (10%)

output:
report_dir: ./.reviews
log_level: info
FieldTypeDefaultDescription
report_dirstring./.reviewsDirectory for session reports and logs
log_levelenuminfoLogging level: debug | info | warn | error

Integration with Planning Game — an agile project management system (XP methodology) available as an MCP server.

planning_game:
enabled: false
project_id: null
codeveloper: null
FieldTypeDefaultDescription
enabledbooleanfalseEnable Planning Game MCP integration
project_idstring | nullnullPlanning Game project ID
codeveloperstring | nullnullDeveloper ID for codeveloper field

becaria:
enabled: false
review_event: becaria-review
comment_event: becaria-comment
comment_prefix: true
FieldTypeDefaultDescription
enabledbooleanfalseEnable BecarIA Gateway — publish pipeline results as PR comments/reviews via GitHub App
review_eventstringbecaria-reviewGitHub repository_dispatch event type for formal reviews (APPROVE/REQUEST_CHANGES)
comment_eventstringbecaria-commentGitHub repository_dispatch event type for agent comments
comment_prefixbooleantruePrefix comments with [Agent] (e.g., [Reviewer], [Sonar])

When enabled: true, Karajan automatically sets git.auto_commit, git.auto_push, and git.auto_pr to true. See Pipeline Flows for the full BecarIA architecture.


serena:
enabled: false
FieldTypeDefaultDescription
enabledbooleanfalseEnable Serena integration for codebase-aware context

model_selection:
enabled: true
tiers: {}
role_overrides: {}
FieldTypeDefaultDescription
enabledbooleantrueEnable smart model selection based on task complexity
tiersobject{}Named tiers with model assignments (e.g., fast, balanced, powerful)
role_overridesobject{}Per-role model overrides that bypass tier selection

Example with tiers:

model_selection:
enabled: true
tiers:
fast:
model: claude-sonnet-4-6
balanced:
model: claude-opus-4-6
role_overrides:
reviewer:
model: claude-opus-4-6

Disable with --no-smart-models CLI flag.


failFast:
repeatThreshold: 2
FieldTypeDefaultDescription
repeatThresholdnumber2Stop the pipeline after this many consecutive identical failures

This is separate from session.fail_fast_repeats — failFast applies to the orchestrator’s global repeat detection across all stages.


What kj release check verifies on top of the generic checks (manifest against CHANGELOG against tags, a privacy scan of the publishable files, the policy in force). Every item is the project’s own.

release_check:
items:
- name: the deployed landing shows the version as current
command: curl -sf https://example.com/docs/ | grep -q 'v{version}'
remedied_by: firebase deploy
- name: the footer carries the version
file_contains:
path: public/footer.html
pattern: v{version}
FieldTypeDescription
namestringHow the item is reported
commandstringPassed to sh -c; exit 0 is a pass. {version} is replaced by the manifest version
file_contains.pathstringFile to read, relative to the project
file_contains.patternstringSubstring that must be present; {version} is replaced too
remedied_bystringThe command that REPAIRS this item, if any

remedied_by exists because a red item must not block the one action that would turn it green. The landing check is the example: it wants the site deployed with the new version, and the deploy that does it was blocked by that very check. The words must appear in the command in order, so firebase deploy covers firebase --account a@b --project p deploy --only hosting:main.

The lifted item stays red in the report, because the fact has not changed, and the gate prints which one it lifted. Everything else still blocks, and a package publication is never excused: npm publish and gh release create are irreversible, whatever an item declares.


VariablePurposeDefault
KJ_HOMEOverride Karajan config directory~/.karajan
KJ_SONAR_TOKENSonarQube authentication tokenFrom config
KJ_SONAR_ADMIN_USERSonarQube admin usernameadmin
KJ_SONAR_ADMIN_PASSWORDSonarQube admin passwordFrom config
KJ_SONAR_PROJECT_KEYOverride SonarQube project keyFrom config
VISUAL / EDITOREditor for kj config --editvi

Environment variables take precedence over config file values for the fields they map to.


The review_mode setting controls how strictly the reviewer evaluates code:

  • Priority: Security → Correctness → Tests → Architecture → Style
  • Blocking: Security issues, logic errors, broken tests, file overwrites
  • Non-blocking: Style suggestions
  • Philosophy: Every change is suspect until proven safe
  • Priority: Security → Correctness → Tests → Data integrity → Architecture → Style
  • Blocking: All security checks, missing error handling, missing input validation, missing tests, entire file rewrites
  • Confidence threshold: Approve only if confidence > 0.85. Default to REJECTION
  • Priority: Security → Correctness → Tests → Architecture → Style
  • Blocking: All security issues, logic errors, insufficient test coverage, missing error handling for external calls
  • Confidence threshold: Reject if confidence < 0.80
  • Philosophy: Prefer approving with suggestions
  • Priority: Critical security → Clear bugs → Critical path tests
  • Blocking: Only critical security (secrets, SQL injection, XSS) and clear logic errors
  • Confidence threshold: Reject if confidence < 0.60

Uses the base reviewer.md file (project-local, global, or built-in) without a pre-defined profile. Full control via your review-rules.md file.


Role instructions are resolved in this order (first found wins):

  1. Project-local: <project>/.karajan/roles/{role}.md
  2. Global: ~/.karajan/roles/{role}.md
  3. Built-in: templates/roles/{role}.md (shipped with Karajan)

Review mode profiles follow the same pattern:

  1. .karajan/roles/reviewer-{mode}.md
  2. ~/.karajan/roles/reviewer-{mode}.md
  3. templates/roles/reviewer-{mode}.md

Plugins are loaded from all locations (not first-wins):

  1. <project>/.karajan/plugins/*.js
  2. ~/.karajan/plugins/*.js

~/.karajan/ # Global config ($KJ_HOME)
├── kj.config.yml # Main configuration
├── roles/ # Global role instructions
│ ├── coder.md
│ ├── reviewer.md
│ ├── reviewer-paranoid.md
│ └── ...
├── plugins/ # Global plugins
│ └── my-agent.js
├── sessions/ # Session logs
│ └── session-{id}/
└── docker-compose.sonar.yml # SonarQube Docker config
<project>/
├── .karajan/ # Project-level overrides
│ ├── roles/ # Project role instructions
│ │ └── reviewer.md
│ └── plugins/ # Project plugins
│ └── my-plugin.js
├── .karajan.yml # Project pricing overrides
├── coder-rules.md # Coder guidelines
└── review-rules.md # Review guidelines

review_mode: paranoid
development:
methodology: tdd
sonarqube:
enabled: true
enforcement_profile: paranoid
quality_gate: true
pipeline:
security:
enabled: true
tester:
enabled: true
max_iterations: 5
git:
auto_commit: false