Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ cascade projects trigger-set <project-id> --agent splitting --event pm:label-add

## Claude Code Engine

CASCADE supports using Claude Code SDK as an alternative agent engine. Configure per-project via the CLI or dashboard:
CASCADE uses the Claude Code SDK as the default agent engine. Configure per-project via the CLI or dashboard:

```bash
# Set Claude Code as the default engine for a project
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ For the full setup walkthrough — projects, credentials, webhooks, and triggers
- **Dual-persona GitHub model** — Separate implementer and reviewer bot accounts to prevent feedback loops
- **Web dashboard + CLI** — Monitor runs, manage projects, configure triggers
- **Extensible trigger system** — Add new events without touching core logic
- **Pluggable agent engines** — `llmist` (default), `claude-code`, `codex`, and `opencode` built-in; easy to extend
- **Pluggable agent engines** — `claude-code` (default), `llmist`, `codex`, and `opencode` built-in; easy to extend
- **Credential encryption** — AES-256-GCM encryption for all stored secrets
- **Agent resilience** — Built-in rate limiting, exponential-backoff retry, and context compaction

Expand Down Expand Up @@ -140,7 +140,7 @@ All project-level credentials (GitHub tokens, PM keys, LLM API keys) are stored

**Trigger system** — Events from Trello, JIRA, and GitHub webhooks are matched against registered `TriggerHandler` instances. Triggers are configured per-project in the database.

**Agent engines** — Agents run through a shared execution lifecycle with a pluggable engine registry. Default engine is `llmist` (supports OpenRouter, Anthropic, OpenAI). Alternatives: `claude-code` (Claude Code SDK), `codex` (OpenAI Codex CLI), `opencode` (OpenCode server).
**Agent engines** — Agents run through a shared execution lifecycle with a pluggable engine registry. Default engine is `claude-code` (Anthropic Claude Code SDK). Alternatives: `llmist` (supports OpenRouter, Anthropic, OpenAI), `codex` (OpenAI Codex CLI), `opencode` (OpenCode server).

**Credential management** — All secrets are stored in the `project_credentials` table, scoped to a project. Optional AES-256-GCM encryption via `CREDENTIAL_MASTER_KEY`.

Expand Down
2 changes: 1 addition & 1 deletion config/projects.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
"branchPrefix": "feature/",

"agentEngine": {
"default": "llmist",
"default": "claude-code",
"overrides": {
"implementation": "claude-code",
"respond-to-review": "claude-code",
Expand Down
10 changes: 5 additions & 5 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ node bin/cascade.js projects credentials-set my-project \

Which credentials you need depends on which agent engine you plan to use. You can always add more later.

#### LLMist engine (default)
#### LLMist engine

LLMist supports OpenRouter, Anthropic, and OpenAI. Store the key for whichever provider you prefer:

Expand All @@ -159,7 +159,7 @@ node bin/cascade.js projects credentials-set my-project \
--name "OpenAI"
```

#### Claude Code engine
#### Claude Code engine (default)

Requires either an Anthropic API key or a Claude Max subscription token:

Expand Down Expand Up @@ -207,12 +207,12 @@ You can also manage all of this through the dashboard UI: **Projects** > select

## 7. Choose Agent Engine

Cascade supports multiple agent engines. The default is **LLMist** — change it if you want to use a different engine.
Cascade supports multiple agent engines. The default is **Claude Code** — change it if you want to use a different engine.

| Engine | Description |
|--------|-------------|
| `llmist` | LLMist SDK with Cascade gadgets (default) |
| `claude-code` | Anthropic Claude Code SDK |
| `claude-code` | Anthropic Claude Code SDK (default) |
| `llmist` | LLMist SDK with Cascade gadgets |
| `codex` | OpenAI Codex CLI |
| `opencode` | OpenCode headless agent |

Expand Down
2 changes: 1 addition & 1 deletion src/agents/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { logger } from '../utils/logging.js';
* Engine resolution order:
* 1. Project-level agent type override
* 2. Project-level default engine
* 3. Fallback: 'llmist'
* 3. Fallback: 'claude-code'
*
* All engines — including llmist — go through the shared adapter
* (executeWithEngine), which handles repo setup, lifecycle, progress
Expand Down
2 changes: 1 addition & 1 deletion src/backends/catalog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,8 @@ export const OPENCODE_ENGINE_DEFINITION: AgentEngineDefinition = {
};

export const DEFAULT_ENGINE_CATALOG: AgentEngineDefinition[] = [
LLMIST_ENGINE_DEFINITION,
CLAUDE_CODE_ENGINE_DEFINITION,
LLMIST_ENGINE_DEFINITION,
CODEX_ENGINE_DEFINITION,
OPENCODE_ENGINE_DEFINITION,
];
4 changes: 2 additions & 2 deletions src/backends/resolution.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import type { ProjectConfig } from '../types/index.js';

export const DEFAULT_ENGINE = 'llmist';
export const DEFAULT_ENGINE = 'claude-code';

/**
* Resolve which engine name to use for a given agent type.
*
* Resolution order (most specific wins):
* 1. Project-level agent type override: project.agentEngine.overrides[agentType]
* 2. Project-level default: project.agentEngine.default
* 3. Hardcoded fallback: DEFAULT_ENGINE ('llmist')
* 3. Hardcoded fallback: DEFAULT_ENGINE ('claude-code')
*/
export function resolveEngineName(agentType: string, project: ProjectConfig): string {
return (
Expand Down
2 changes: 1 addition & 1 deletion src/config/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const PROJECT_DEFAULTS = {
progressModel: 'openrouter:google/gemini-2.5-flash-lite',
progressIntervalMinutes: 5,
workItemBudgetUsd: 5,
agentEngine: 'llmist',
agentEngine: 'claude-code',
} as const;

const AgentEngineConfigSchema = z.object({
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/api/routers/projects.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,7 @@ describe('projectsRouter', () => {
expect(PROJECT_DEFAULTS.progressModel).toBe('openrouter:google/gemini-2.5-flash-lite');
expect(PROJECT_DEFAULTS.progressIntervalMinutes).toBe(5);
expect(PROJECT_DEFAULTS.workItemBudgetUsd).toBe(5);
expect(PROJECT_DEFAULTS.agentEngine).toBe('llmist');
expect(PROJECT_DEFAULTS.agentEngine).toBe('claude-code');
});

it('CLAUDE_CODE_SETTING_DEFAULTS match the resolver fallback values', () => {
Expand Down
6 changes: 3 additions & 3 deletions tests/unit/backends/catalog.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ describe('DEFAULT_ENGINE_CATALOG', () => {
}
});

it('is ordered: llmist, claude-code, codex, opencode', () => {
expect(DEFAULT_ENGINE_CATALOG[0].id).toBe('llmist');
expect(DEFAULT_ENGINE_CATALOG[1].id).toBe('claude-code');
it('is ordered: claude-code, llmist, codex, opencode', () => {
expect(DEFAULT_ENGINE_CATALOG[0].id).toBe('claude-code');
expect(DEFAULT_ENGINE_CATALOG[1].id).toBe('llmist');
expect(DEFAULT_ENGINE_CATALOG[2].id).toBe('codex');
expect(DEFAULT_ENGINE_CATALOG[3].id).toBe('opencode');
});
Expand Down
8 changes: 4 additions & 4 deletions tests/unit/backends/resolution.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@ describe('resolveEngineName', () => {
expect(resolveEngineName('implementation', project)).toBe('custom-backend');
});

it('returns "llmist" when no project config', () => {
it('returns "claude-code" when no project config', () => {
const project = makeProject(); // no agentEngine
expect(resolveEngineName('implementation', project)).toBe('llmist');
expect(resolveEngineName('implementation', project)).toBe('claude-code');
});

it('returns "llmist" when nothing configured', () => {
it('returns "claude-code" when nothing configured', () => {
const project = makeProject(); // no agentEngine
expect(resolveEngineName('implementation', project)).toBe('llmist');
expect(resolveEngineName('implementation', project)).toBe('claude-code');
});

it('prioritizes override > project default > fallback', () => {
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/cli/dashboard/agents/agents.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const sampleAgentConfig = {
projectId: 'my-project',
model: 'claude-sonnet-4-5-20250929',
maxIterations: 50,
agentEngine: 'llmist',
agentEngine: 'claude-code',
maxConcurrency: null,
prompt: null,
};
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/cli/dashboard/projects/projects.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const sampleProject = {
baseBranch: 'main',
branchPrefix: 'cascade/',
model: 'claude-sonnet-4-5-20250929',
agentEngine: 'llmist',
agentEngine: 'claude-code',
workItemBudgetUsd: '5.00',
maxInFlightItems: 3,
};
Expand Down
8 changes: 4 additions & 4 deletions tests/unit/config/schema.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ describe.concurrent('ProjectConfigSchema', () => {
expect(() => ProjectConfigSchema.parse(config)).toThrow('Unsupported engine settings');
});

it('applies default "llmist" for agentEngine.default when object provided', () => {
it('applies default "claude-code" for agentEngine.default when object provided', () => {
const config = {
id: 'test',
orgId: 'default',
Expand All @@ -165,7 +165,7 @@ describe.concurrent('ProjectConfigSchema', () => {
};

const result = ProjectConfigSchema.parse(config);
expect(result.agentEngine?.default).toBe('llmist');
expect(result.agentEngine?.default).toBe('claude-code');
expect(result.agentEngine?.overrides).toEqual({});
});

Expand Down Expand Up @@ -260,7 +260,7 @@ describe.concurrent('validateConfig', () => {
expect(() => validateConfig({ projects: [] })).toThrow();
});

it('applies default "llmist" for project agentEngine.default', () => {
it('applies default "claude-code" for project agentEngine.default', () => {
const config = {
projects: [
{
Expand All @@ -275,7 +275,7 @@ describe.concurrent('validateConfig', () => {
};

const result = validateConfig(config);
expect(result.projects[0].agentEngine?.default).toBe('llmist');
expect(result.projects[0].agentEngine?.default).toBe('claude-code');
});

it('accepts custom project agentEngine value', () => {
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/db/repositories/configRepository.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ describe('configRepository', () => {
const proj = config.projects[0];

expect(proj.agentEngine).toBeDefined();
expect(proj.agentEngine?.default).toBe('llmist'); // Zod default
expect(proj.agentEngine?.default).toBe('claude-code'); // Zod default
expect(proj.agentEngine?.overrides).toEqual({
implementation: 'claude-code',
});
Expand Down
2 changes: 1 addition & 1 deletion tools/resolve-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ async function resolveEffectiveConfig(
effectiveModel:
projectAc?.model ?? projectRow.model ?? 'openrouter:google/gemini-3-flash-preview',
effectiveMaxIterations: projectAc?.maxIterations ?? projectRow.maxIterations ?? 50,
effectiveEngine: projectAc?.agentEngine ?? projectRow.agentEngine ?? 'llmist',
effectiveEngine: projectAc?.agentEngine ?? projectRow.agentEngine ?? 'claude-code',
projectOverrides: {
model: projectRow.model,
maxIterations: projectRow.maxIterations,
Expand Down
2 changes: 1 addition & 1 deletion web/src/components/projects/project-agent-configs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ function DefinitionAgentSection({
const effectiveEngine = engines.find((engine) => engine.id === effectiveEngineId);

// Resolved inherited engine — project override or system default
const inheritedEngine = projectEngine ?? systemDefaults?.agentEngine ?? 'llmist';
const inheritedEngine = projectEngine ?? systemDefaults?.agentEngine ?? 'claude-code';
// Per-field engine defaults for the EngineSettingsFields component
const engineDefaults =
systemDefaults && effectiveEngineId
Expand Down
2 changes: 1 addition & 1 deletion web/src/components/projects/projects-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export function ProjectsTable({
<Badge variant="outline">{project.baseBranch ?? 'main'}</Badge>
</TableCell>
<TableCell className="hidden md:table-cell">
{project.agentEngine ?? 'llmist'}
{project.agentEngine ?? 'claude-code'}
</TableCell>
<TableCell className="hidden md:table-cell text-right tabular-nums">
{project.workItemBudgetUsd ? `$${project.workItemBudgetUsd}` : '-'}
Expand Down
Loading