Conditions let you skip evals, enrichments, and actions for sessions where they don’t apply. Claudeye supports two levels: a global condition that gates everything, and per-item conditions scoped to individual evals or enrichments.
Global condition
Set a global condition with app.condition(). If it returns false, every registered eval, enrichment, and action is skipped for that session.
// Skip all evals for empty sessions
app.condition(({ entries }) => entries.length > 0);
// Skip all evals for test projects
app.condition(({ projectName }) => !projectName.includes('test'));
// Only run for sessions with at least 5 turns
app.condition(({ stats }) => stats.turnCount >= 5);
Calling app.condition() multiple times replaces the previous condition. Only the last call is active.
Async conditions are supported:
app.condition(async ({ sessionId }) => {
// Check an external service, database, etc.
return sessionId !== 'skip-this-one';
});
Per-item conditions
Pass a condition option to individual evals, enrichments, or actions. If the condition returns false, only that item is skipped - others continue normally.
// Only run this eval for sessions with tool calls
app.eval('efficient-tools',
({ stats }) => ({
pass: stats.toolCallCount <= stats.turnCount * 2,
score: Math.max(0, 1 - stats.toolCallCount / (stats.turnCount * 4)),
}),
{ condition: ({ stats }) => stats.toolCallCount > 0 }
);
// Only compute model info when a model was used
app.enrich('model-info',
({ stats }) => ({
'Primary Model': stats.models[0] || 'unknown',
'Model Count': stats.models.length,
}),
{ condition: ({ stats }) => stats.models.length > 0 }
);
How global and per-item conditions stack
The global condition runs first. If it passes, per-item conditions are checked individually:
1. Global condition
├── false or throws → ALL items marked "skipped"
└── true → proceed
2. Per-item condition (for each eval/enrichment)
├── false → that item marked "skipped"
├── throws → that item marked "errored"
└── true → run the function
3. Function runs
├── returns result → recorded normally
└── throws → marked "errored", other items still run
UI behavior
| Status | Evals panel | Enrichments panel |
|---|
| Skipped | Grayed-out row with “skipped” label | Grayed-out row with “skipped” label |
| Condition error | Row with warning icon and error message | Row with warning icon and error message |
| Passed | Green check with score bar | Key-value pairs grouped by enricher |
| Failed | Red X with score bar | N/A |
Skipped items are counted separately in the summary bar (e.g. “2 passed, 1 skipped”).
app.queueCondition() - background queue gate
app.queueCondition() is a separate condition that only affects the background queue. It pre-filters sessions before they are enqueued for processing, but has no effect on UI-triggered runs.
// Only process sessions with more than 5 entries
app.queueCondition(({ entries }) => entries.length > 5);
// Cache the result per session (re-evaluate only when session changes)
app.queueCondition(({ stats }) => stats.turnCount >= 3, { cacheable: true });
// Time-dependent - must NOT be cached
app.queueCondition(() => {
const hour = new Date().getHours();
return hour >= 9 && hour < 17; // business hours only
});
cacheable option
| Value | Behavior |
|---|
false (default) | Re-evaluated every scan cycle. Use for time or external-state dependent logic. |
true | Result cached per session. Auto-invalidates when the session file or condition function changes. |
Comparison
| app.condition() | app.queueCondition() |
|---|
| Affects UI runs | Yes | No |
| Affects background scanner | No | Yes |
| Caching | No | Opt-in via { cacheable: true } |
Both can be active simultaneously. queueCondition is a pre-filter for the scanner; sessions that pass it are then subject to the normal app.condition() check when items execute.