78 file(s) changed (+1348 −362) across 14 area(s)

Reading order: The main change: apps/review; Alongside: benchmarks; Alongside: apps/cli; Alongside: scripts; Alongside: apps/smithers-studio-2; Alongside: apps/smithers; Alongside: apps/smithers-demo; Alongside: packages/scorers; Alongside: packages/agents; Alongside: packages/usage; Alongside: .smithers; Wiring and configuration; The proof: tests; The paper trail: docs.

repo /Users/williamcory/smitherstarget workspace78 file(s)+1348−362findings 0generated 2026-06-11T15:44:25.275Z

Chapters

  1. The main change: apps/review (9 file(s))
  2. Alongside: benchmarks (9 file(s))
  3. Alongside: apps/cli (5 file(s))
  4. Alongside: scripts (1 file(s))
  5. Alongside: apps/smithers-studio-2 (1 file(s))
  6. Alongside: apps/smithers (5 file(s))
  7. Alongside: apps/smithers-demo (1 file(s))
  8. Alongside: packages/scorers (2 file(s))
  9. Alongside: packages/agents (1 file(s))
  10. Alongside: packages/usage (1 file(s))
  11. Alongside: .smithers (1 file(s))
  12. Wiring and configuration (7 file(s))
  13. The proof: tests (4 file(s))
  14. The paper trail: docs (31 file(s))

1The main change: apps/review

9 file(s) changed in apps/review (+444 −4).

apps/review/.alchemy/smithers-review/williamcory/smithers-review.jsonadded+139 −0

added (+139 −0)

Diff (+139 −0)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
{
"kind": "cloudflare::Worker",
"id": "smithers-review",
"fqn": "smithers-review/williamcory/smithers-review",
"seq": 1,
"data": {},
"status": "created",
"output": {
"Symbol(alchemy::ResourceKind)": "cloudflare::Worker",
"Symbol(alchemy::ResourceID)": "smithers-review",
"Symbol(alchemy::ResourceFQN)": "smithers-review/williamcory/smithers-review",
"Symbol(alchemy::ResourceScope)": {
"@scope": null
},
"Symbol(alchemy::ResourceSeq)": 1,
"entrypoint": "src/server/worker.ts",
"compatibilityDate": "2025-05-01",
"url": "https://smithers-review-smithers-review-williamcory.willcory10.workers.dev",
"adopt": true,
"bindings": {
"WALKTHROUGHS": {
"Symbol(alchemy::ResourceKind)": "cloudflare::R2Bucket",
"Symbol(alchemy::ResourceID)": "walkthroughs",
"Symbol(alchemy::ResourceFQN)": "smithers-review/williamcory/walkthroughs",
"Symbol(alchemy::ResourceScope)": {
"@scope": null
},
"Symbol(alchemy::ResourceSeq)": 0,
"name": "smithers-review-walkthroughs-williamcory",
"location": "ENAM",
"creationDate": {
"@date": "2026-06-11T15:39:38.296Z"
},
"jurisdiction": "default",
"type": "r2_bucket",
"accountId": "dd3525a4132493566aeb38de533c8827",
"dev": {
"id": "smithers-review-walkthroughs-williamcory",
"remote": false,
"isDeployed": true
}
},
"REVIEW_PUBLISH_TOKEN": {
"@secret": {
"version": "v1",
"ciphertext": "rsY5I9W/Aavyu/UBGuu27u3q8516cN7P3xsrcJfkW9Ro+asMVlrOk6WAYVyHYyH2",
"iv": "rD0t2XWYdbVj2LCP",
"salt": "XXlQtBU9UTurm0L70bH/8w==",
"tag": "gX8FpNvG+SH2mPTDIQKoKg=="
}
},
"PUBLIC_BASE_URL": "https://review.jjhub.tech"
},
"domains": [
{
"Symbol(alchemy::ResourceKind)": "cloudflare::CustomDomain",
"Symbol(alchemy::ResourceID)": "review.jjhub.tech",
"Symbol(alchemy::ResourceFQN)": "smithers-review/williamcory/smithers-review/review.jjhub.tech",
"Symbol(alchemy::ResourceScope)": {
"@scope": null
},
"Symbol(alchemy::ResourceSeq)": 0,
"name": "review.jjhub.tech",
"zoneId": "72854846f57d9e46794e7e6aae7e3328",
"adopt": true,
"workerName": "smithers-review-smithers-review-williamcory",
"dev": false,
"id": "c52358c69dc05bde3d76c7f8a3ccd97de845d03e",
"environment": "production",
"createdAt": 1781192629587,
"updatedAt": 1781192629587
}
],
"routes": [],
"type": "service",
"id": "smithers-review",
"name": "smithers-review-smithers-review-williamcory",
"cwd": "",
"compatibilityFlags": [],
"format": "esm",
"createdAt": {
"@date": "2026-06-11T15:43:49.589Z"
},
"updatedAt": {
"@date": "2026-06-11T15:43:49.589Z"
},
"dev": {
"hasRemote": true
}
},
"props": {
"entrypoint": "src/server/worker.ts",
"compatibilityDate": "2025-05-01",
"url": true,
"adopt": true,
"bindings": {
"WALKTHROUGHS": {
"Symbol(alchemy::ResourceKind)": "cloudflare::R2Bucket",
"Symbol(alchemy::ResourceID)": "walkthroughs",
"Symbol(alchemy::ResourceFQN)": "smithers-review/williamcory/walkthroughs",
"Symbol(alchemy::ResourceScope)": {
"@scope": null
},
"Symbol(alchemy::ResourceSeq)": 0,
"name": "smithers-review-walkthroughs-williamcory",
"location": "ENAM",
"creationDate": {
"@date": "2026-06-11T15:39:38.296Z"
},
"jurisdiction": "default",
"type": "r2_bucket",
"accountId": "dd3525a4132493566aeb38de533c8827",
"dev": {
"id": "smithers-review-walkthroughs-williamcory",
"remote": false,
"isDeployed": true
}
},
"REVIEW_PUBLISH_TOKEN": {
"@secret": {
"version": "v1",
"ciphertext": "tye0CasMa/nqnCR8ORNb6B6zj/u5WGRYhVokVrowhceOjrYa1PwSE1mckG3Olp1x",
"iv": "satWrjDI+zifa6vG",
"salt": "v3hCyfy/oGnUEZ+u43leGA==",
"tag": "sDddZ8OfYAXOPwNIKVbqpg=="
}
},
"PUBLIC_BASE_URL": "https://review.jjhub.tech"
},
"domains": [
{
"domainName": "review.jjhub.tech",
"zoneId": "72854846f57d9e46794e7e6aae7e3328",
"adopt": true
}
],
"routes": []
}
}
No newline at end of file
apps/review/src/server/worker.tsadded+112 −0

added (+112 −0)

Diff (+112 −0)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/**
* Cloudflare Worker serving published walkthroughs at review.smithers.sh.
*
* POST /api/walkthroughs (Bearer REVIEW_PUBLISH_TOKEN, HTML body) -> { id, url }
* GET /w/<id> serve a published walkthrough
* GET / usage landing page
*
* Storage is R2; ids are random capability links, there is no listing.
*/
const MAX_WALKTHROUGH_BYTES = 25 * 1024 * 1024;
type R2ObjectBody = { body: ReadableStream } | null;
type WalkthroughBucket = {
put(key: string, value: ArrayBuffer | string, options?: { httpMetadata?: { contentType?: string } }): Promise<unknown>;
get(key: string): Promise<R2ObjectBody>;
};
export type ReviewWorkerEnv = {
WALKTHROUGHS: WalkthroughBucket;
REVIEW_PUBLISH_TOKEN: string;
PUBLIC_BASE_URL?: string;
};
const landingPage = `<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>smithers review</title>
<style>
body { margin: 0; font: 16px/1.6 -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif; color: #1f2328; background: #f6f8fa; }
main { max-width: 720px; margin: 0 auto; padding: 64px 24px; }
h1 { font-size: 28px; margin: 0 0 8px; }
p { color: #59636e; max-width: 65ch; }
pre { background: #fff; border: 1px solid #d1d9e0; border-radius: 8px; padding: 14px 16px; overflow-x: auto; font-size: 13px; }
code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
</style>
</head>
<body>
<main>
<h1>smithers review</h1>
<p>Code review plus story-form walkthroughs. Walkthroughs published here are unlisted; you need the link.</p>
<p>Publish one from a repo:</p>
<pre><code>smithers-review --from main --to HEAD --publish</code></pre>
<p>Part of <a href="https://github.com/smithersai/smithers">smithers</a>.</p>
</main>
</body>
</html>`;
function newWalkthroughId(): string {
const bytes = new Uint8Array(12);
crypto.getRandomValues(bytes);
return [...bytes].map((b) => (b % 36).toString(36)).join("");
}
function timingSafeEqual(a: string, b: string): boolean {
const encoder = new TextEncoder();
const left = encoder.encode(a);
const right = encoder.encode(b);
if (left.length !== right.length) return false;
let diff = 0;
for (let i = 0; i < left.length; i += 1) diff |= left[i] ^ right[i];
return diff === 0;
}
export default {
async fetch(request: Request, env: ReviewWorkerEnv): Promise<Response> {
const url = new URL(request.url);
if (request.method === "GET" && url.pathname === "/") {
return new Response(landingPage, { headers: { "content-type": "text/html; charset=utf-8" } });
}
if (request.method === "POST" && url.pathname === "/api/walkthroughs") {
const token = env.REVIEW_PUBLISH_TOKEN ?? "";
const auth = request.headers.get("authorization") ?? "";
if (!token || !timingSafeEqual(auth, `Bearer ${token}`)) {
return Response.json({ error: "unauthorized" }, { status: 401 });
}
const html = await request.arrayBuffer();
if (html.byteLength === 0) {
return Response.json({ error: "empty body" }, { status: 400 });
}
if (html.byteLength > MAX_WALKTHROUGH_BYTES) {
return Response.json({ error: "walkthrough exceeds 25MB" }, { status: 413 });
}
const id = newWalkthroughId();
await env.WALKTHROUGHS.put(`walkthroughs/${id}.html`, html, {
httpMetadata: { contentType: "text/html; charset=utf-8" },
});
const base = (env.PUBLIC_BASE_URL ?? url.origin).replace(/\/$/, "");
return Response.json({ id, url: `${base}/w/${id}` }, { status: 201 });
}
if (request.method === "GET" && /^\/w\/[a-z0-9]{8,32}$/.test(url.pathname)) {
const id = url.pathname.slice("/w/".length);
const object = await env.WALKTHROUGHS.get(`walkthroughs/${id}.html`);
if (!object) return new Response("Not found", { status: 404 });
return new Response(object.body, {
headers: {
"content-type": "text/html; charset=utf-8",
"cache-control": "public, max-age=31536000, immutable",
"x-robots-tag": "noindex",
},
});
}
return new Response("Not found", { status: 404 });
},
};
apps/review/alchemy.run.tsadded+58 −0

added (+58 −0)

Diff (+58 −0)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/**
* Alchemy infrastructure-as-code for the smithers review publish service.
*
* One Cloudflare Worker (entry: src/server/worker.ts) + one R2 bucket. The
* Worker keeps its workers.dev URL and serves review.jjhub.tech as a custom
* domain (the jjhub.tech zone is on this Cloudflare account).
*
* review.smithers.sh: the smithers.sh zone lives on Vercel DNS (registrar
* Name.com), so serving it from this Worker needs Cloudflare for SaaS
* (custom hostname on jjhub.tech + a CNAME at Vercel). The current
* CLOUDFLARE_API_TOKEN lacks the SSL-and-Certificates permission for custom
* hostnames and the available VERCEL_API_TOKEN is expired, so that leg is
* gated behind REVIEW_ENABLE_SMITHERS_SH_ROUTE=1 until credentials exist.
* See .smithers/specs/smithers-review-walkthrough.md, "Publishing".
*
* Deploy: REVIEW_PUBLISH_TOKEN=... bun x alchemy deploy (from apps/review)
* Destroy: bun x alchemy destroy
*
* Required env: CLOUDFLARE_API_TOKEN, ALCHEMY_PASSWORD, REVIEW_PUBLISH_TOKEN.
*/
import alchemy from "alchemy";
import { R2Bucket, Worker } from "alchemy/cloudflare";
const JJHUB_ZONE_ID = "72854846f57d9e46794e7e6aae7e3328";
const app = await alchemy("smithers-review");
const publishToken = process.env.REVIEW_PUBLISH_TOKEN?.trim();
if (!publishToken) {
throw new Error("REVIEW_PUBLISH_TOKEN is required to deploy (the publish API bearer token).");
}
const bucket = await R2Bucket("walkthroughs", {
adopt: true,
});
const smithersShRoutes =
process.env.REVIEW_ENABLE_SMITHERS_SH_ROUTE === "1"
? [{ pattern: "review.smithers.sh/*", zoneId: JJHUB_ZONE_ID, adopt: true }]
: [];
export const worker = await Worker("smithers-review", {
entrypoint: "src/server/worker.ts",
compatibilityDate: "2025-05-01",
url: true,
adopt: true,
bindings: {
WALKTHROUGHS: bucket,
REVIEW_PUBLISH_TOKEN: alchemy.secret(publishToken),
PUBLIC_BASE_URL: process.env.REVIEW_PUBLIC_BASE_URL?.trim() || "https://review.jjhub.tech",
},
domains: [{ domainName: "review.jjhub.tech", zoneId: JJHUB_ZONE_ID, adopt: true }],
routes: smithersShRoutes,
});
console.log(`smithers review deployed → ${worker.url ?? "(no workers.dev url)"}`);
await app.finalize();
apps/review/src/cli/publishWalkthrough.tsadded+46 −0

added (+46 −0)

Diff (+46 −0)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import { existsSync, readFileSync } from "node:fs";
import { homedir } from "node:os";
import { join } from "node:path";
const DEFAULT_PUBLISH_URL = "https://review.smithers.sh";
function loadPublishConfig(): { url: string; token: string } {
let url = process.env.SMITHERS_REVIEW_PUBLISH_URL?.trim() || "";
let token = process.env.SMITHERS_REVIEW_PUBLISH_TOKEN?.trim() || "";
if (!url || !token) {
const path = join(homedir(), ".smithers-review.json");
if (existsSync(path)) {
const raw = JSON.parse(readFileSync(path, "utf8")) as { publishUrl?: string; publishToken?: string };
url = url || raw.publishUrl?.trim() || "";
token = token || raw.publishToken?.trim() || "";
}
}
url = url || DEFAULT_PUBLISH_URL;
if (!token) {
throw new Error(
"no publish token: set SMITHERS_REVIEW_PUBLISH_TOKEN or write ~/.smithers-review.json with { \"publishToken\": \"...\" }",
);
}
return { url: url.replace(/\/$/, ""), token };
}
/** Upload a walkthrough HTML file to the publish service; returns the share URL. */
export async function publishWalkthrough(htmlPath: string): Promise<string> {
const { url, token } = loadPublishConfig();
const html = readFileSync(htmlPath);
const response = await fetch(`${url}/api/walkthroughs`, {
method: "POST",
headers: {
authorization: `Bearer ${token}`,
"content-type": "text/html; charset=utf-8",
},
body: html,
});
if (!response.ok) {
const detail = await response.text().catch(() => "");
throw new Error(`publish failed: HTTP ${response.status}${detail ? ` ${detail.slice(0, 200)}` : ""}`);
}
const data = (await response.json()) as { url?: string };
if (!data.url) throw new Error("publish failed: response had no url");
return data.url;
}
apps/review/.alchemy/smithers-review/williamcory/walkthroughs.jsonadded+36 −0

added (+36 −0)

Diff (+36 −0)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
{
"kind": "cloudflare::R2Bucket",
"id": "walkthroughs",
"fqn": "smithers-review/williamcory/walkthroughs",
"seq": 0,
"data": {},
"status": "created",
"output": {
"Symbol(alchemy::ResourceKind)": "cloudflare::R2Bucket",
"Symbol(alchemy::ResourceID)": "walkthroughs",
"Symbol(alchemy::ResourceFQN)": "smithers-review/williamcory/walkthroughs",
"Symbol(alchemy::ResourceScope)": {
"@scope": null
},
"Symbol(alchemy::ResourceSeq)": 0,
"name": "smithers-review-walkthroughs-williamcory",
"location": "ENAM",
"creationDate": {
"@date": "2026-06-11T15:39:38.296Z"
},
"jurisdiction": "default",
"type": "r2_bucket",
"accountId": "dd3525a4132493566aeb38de533c8827",
"dev": {
"id": "smithers-review-walkthroughs-williamcory",
"remote": false,
"isDeployed": true
}
},
"props": {
"adopt": true,
"dev": {
"force": false
}
}
}
No newline at end of file
apps/review/.alchemy/smithers-review/williamcory/smithers-review/review.jjhub.tech.jsonadded+33 −0

added (+33 −0)

Diff (+33 −0)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{
"kind": "cloudflare::CustomDomain",
"id": "review.jjhub.tech",
"fqn": "smithers-review/williamcory/smithers-review/review.jjhub.tech",
"seq": 0,
"data": {},
"status": "created",
"output": {
"Symbol(alchemy::ResourceKind)": "cloudflare::CustomDomain",
"Symbol(alchemy::ResourceID)": "review.jjhub.tech",
"Symbol(alchemy::ResourceFQN)": "smithers-review/williamcory/smithers-review/review.jjhub.tech",
"Symbol(alchemy::ResourceScope)": {
"@scope": null
},
"Symbol(alchemy::ResourceSeq)": 0,
"name": "review.jjhub.tech",
"zoneId": "72854846f57d9e46794e7e6aae7e3328",
"adopt": true,
"workerName": "smithers-review-smithers-review-williamcory",
"dev": false,
"id": "c52358c69dc05bde3d76c7f8a3ccd97de845d03e",
"environment": "production",
"createdAt": 1781192629587,
"updatedAt": 1781192629587
},
"props": {
"name": "review.jjhub.tech",
"zoneId": "72854846f57d9e46794e7e6aae7e3328",
"adopt": true,
"workerName": "smithers-review-smithers-review-williamcory",
"dev": false
}
}
No newline at end of file
apps/review/src/cli/main.tsmodified+14 −1

modified (+14 −1)

Diff (+14 −1)
6 unmodified lines
7
8
9
10
11
12
13
11 unmodified lines
25
26
27
28
29
30
31
61 unmodified lines
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
99
112
113
114
115
6 unmodified lines
import { createReviewAgents } from "../workflow/createReviewAgents";
import { createReviewWorkflow } from "../workflow/createReviewWorkflow";
import { parseReviewArgs, type ReviewArgs } from "./parseReviewArgs";
import { publishWalkthrough } from "./publishWalkthrough";
const USAGE = `smithers review — code review + story-form HTML walkthrough
11 unmodified lines
--concurrency <n> parallel file reviews (default 8)
--timeout <min> per-agent-task timeout in minutes (default 10)
--split side-by-side diffs instead of unified
--publish upload to review.smithers.sh and print the share URL
--open open the walkthrough in the default browser
-h, --help show this help`;
61 unmodified lines
if (review?.message) console.log(`Review: ${String(review.message)}`);
console.log(String(walkthrough.message ?? `Walkthrough written to ${String(walkthrough.path)}`));
let publishFailed = false;
if (args.publish) {
try {
const shareUrl = await publishWalkthrough(String(walkthrough.path));
console.log(`Published: ${shareUrl}`);
} catch (error) {
publishFailed = true;
console.error(`smithers-review: ${(error as Error).message}`);
}
}
if (args.open) {
const opener = process.platform === "darwin" ? "open" : "xdg-open";
spawn(opener, [String(walkthrough.path)], { stdio: "ignore", detached: true }).unref();
}
const failed = result.status === "failed" || result.status === "cancelled";
const failed = result.status === "failed" || result.status === "cancelled" || publishFailed;
process.exit(failed ? 1 : 0);
}
apps/review/src/workflow/createReviewAgents.tsmodified+3 −3

modified (+3 −3)

Diff (+3 −3)
2 unmodified lines
3
4
5
6
6
7
8
9
10
9
10
11
12
2 unmodified lines
/**
* Default agent arrays for review and narration. Mirrors .smithers/agents.ts:
* the ClaudeCode subscription providers are the reliable ones locally
* (issue #236); opus primary, sonnet failover.
* (issue #236); Fable primary, Opus failover.
*/
export function createReviewAgents(repoDir: string): { review: AgentLike[]; narrate: AgentLike[] } {
const primary = new ClaudeCodeAgent({ model: process.env.SMITHERS_REVIEW_MODEL ?? "claude-opus-4-7", cwd: repoDir });
const fallback = new ClaudeCodeAgent({ model: process.env.SMITHERS_REVIEW_FALLBACK_MODEL ?? "claude-sonnet-4-7", cwd: repoDir });
const primary = new ClaudeCodeAgent({ model: process.env.SMITHERS_REVIEW_MODEL ?? "claude-fable-5", cwd: repoDir });
const fallback = new ClaudeCodeAgent({ model: process.env.SMITHERS_REVIEW_FALLBACK_MODEL ?? "claude-opus-4-8", cwd: repoDir });
return { review: [primary, fallback], narrate: [primary, fallback] };
}
apps/review/src/cli/parseReviewArgs.tsmodified+3 −0

modified (+3 −0)

Diff (+3 −0)
11 unmodified lines
12
13
14
15
16
17
18
13 unmodified lines
32
33
34
35
36
37
38
16 unmodified lines
55
56
57
58
59
60
61
11 unmodified lines
concurrency: number;
timeout: number;
split: boolean;
publish: boolean;
open: boolean;
help: boolean;
};
13 unmodified lines
concurrency: 8,
timeout: 10,
split: false,
publish: false,
open: false,
help: false,
};
16 unmodified lines
else if (arg === "--concurrency") args.concurrency = Number(next());
else if (arg === "--timeout") args.timeout = Number(next());
else if (arg === "--split") args.split = true;
else if (arg === "--publish") args.publish = true;
else if (arg === "--open") args.open = true;
else if (arg === "--help" || arg === "-h") args.help = true;
else if (arg.startsWith("-")) throw new Error(`Unknown option: ${arg}`);

2Alongside: benchmarks

9 file(s) changed in benchmarks (+86 −91).

benchmarks/claw-eval-live/gateway/src/mixture.tsmodified+38 −39

modified (+38 −39)

Diff (+38 −39)
15 unmodified lines
16
17
18
19
19
20
21
21
22
23
23
24
25
26
4 unmodified lines
31
32
33
34
35
34
35
36
38
37
38
39
40
41
42
44
43
44
45
47
46
47
48
50
49
50
51
52
53
55
56
57
58
59
54
55
56
57
58
59
60
61
62
63
65
64
65
66
67
69
70
68
69
70
72
73
71
72
73
74
76
77
78
75
76
77
78
79
80
5 unmodified lines
86
87
88
90
91
89
90
91
92
93
172 unmodified lines
266
267
268
270
271
269
270
271
273
272
273
274
275
277
276
277
279
278
279
280
281
283
282
283
284
285
20 unmodified lines
306
307
308
310
311
309
310
311
313
312
313
314
315
317
318
316
317
318
319
321
322
320
321
322
324
323
324
326
325
326
327
328
15 unmodified lines
* through, so the benchmark executes them exactly as it would for
* any model.
* - SYNTHESIS: the moment gpt-5.5 is ready to answer (no tool_calls), Claude
* Opus 4.8 (via Smithers ClaudeCodeAgent, subscription) writes the
* Fable (via Smithers ClaudeCodeAgent, subscription) writes the
* final answer from the gathered context. That is the role-split
* "mixture of Opus 4.8 + Codex 5.5" (gpt-5.5 gathers, Opus 4.8
* "mixture of Fable + GPT-5.5" (gpt-5.5 gathers, Fable
* synthesizes) and it lands on the turn the graders actually
* measure. If Opus is unavailable, the turn falls back to gpt-5.5's
* measure. If Fable is unavailable, the turn falls back to gpt-5.5's
* own final answer. The brain contains no LLM judge of its own.
*
* Fairness invariants (see README): the brain only ever sees what the benchmark
4 unmodified lines
import { ClaudeCodeAgent, OpenAIAgent } from "@smithers-orchestrator/agents";
// ---- model identifiers -----------------------------------------------------
// "Codex 5.5" → gpt-5.5 (the flagship 5.5; no `gpt-5.5-codex` variant exists,
// the latest codex-tuned model is gpt-5.3-codex). gpt-5.5 is the strongest 5.5.
// "Codex 5.5" → gpt-5.5 (the flagship 5.5; no `gpt-5.5-codex` variant exists).
const GATHER_MODEL = process.env.CLAW_GATHER_MODEL ?? "gpt-5.5";
const GPT_SYNTH_MODEL = process.env.CLAW_GPT_MODEL ?? "gpt-5.5";
const OPUS_MODEL = process.env.CLAW_OPUS_MODEL ?? "opus"; // -> claude-opus-4-8
const FABLE_MODEL = process.env.CLAW_FABLE_MODEL ?? "claude-fable-5";
const OPENAI_URL = "https://api.openai.com/v1/chat/completions";
const OPENAI_KEY = process.env.OPENAI_API_KEY ?? "";
const OPUS_TIMEOUT_MS = Number(process.env.CLAW_OPUS_TIMEOUT_MS ?? 150_000);
const FABLE_TIMEOUT_MS = Number(process.env.CLAW_FABLE_TIMEOUT_MS ?? 150_000);
const GPT_TIMEOUT_MS = Number(process.env.CLAW_GPT_TIMEOUT_MS ?? 120_000);
// Each Opus draft spawns a `claude` CLI subprocess. Bound how many run at once
// Each Fable draft spawns a `claude` CLI subprocess. Bound how many run at once
// so a parallel batch can't fork-bomb the box; over the cap we simply fall back
// to the gpt-5.5 draft for that turn (synthesis still happens, just single-model).
const OPUS_MAX = Number(process.env.CLAW_OPUS_MAX_CONCURRENCY ?? 2);
const FABLE_MAX = Number(process.env.CLAW_FABLE_MAX_CONCURRENCY ?? 2);
// Cap the transcript fed to the synthesis drafts (large tool results / file dumps
// would otherwise blow up memory and token cost).
const MAX_TRANSCRIPT_CHARS = Number(process.env.CLAW_MAX_TRANSCRIPT_CHARS ?? 140_000);
let opusActive = 0;
const opusWaiters: Array<() => void> = [];
function acquireOpus(): Promise<boolean> {
if (opusActive < OPUS_MAX) {
opusActive++;
let fableActive = 0;
const fableWaiters: Array<() => void> = [];
function acquireFable(): Promise<boolean> {
if (fableActive < FABLE_MAX) {
fableActive++;
return Promise.resolve(true);
}
return new Promise<boolean>((resolve) => {
const grant = () => {
clearTimeout(timer);
opusActive++;
fableActive++;
resolve(true);
};
const timer = setTimeout(() => {
const i = opusWaiters.indexOf(grant);
if (i >= 0) opusWaiters.splice(i, 1);
const i = fableWaiters.indexOf(grant);
if (i >= 0) fableWaiters.splice(i, 1);
resolve(false); // saturated -> caller falls back to gpt-only synthesis
}, OPUS_TIMEOUT_MS);
opusWaiters.push(grant);
}, FABLE_TIMEOUT_MS);
fableWaiters.push(grant);
});
}
function releaseOpus(): void {
opusActive = Math.max(0, opusActive - 1);
const next = opusWaiters.shift();
function releaseFable(): void {
fableActive = Math.max(0, fableActive - 1);
const next = fableWaiters.shift();
if (next) next();
}
5 unmodified lines
}
// Reused agent instances (stateless per generate()).
const opusAgent = new ClaudeCodeAgent({
model: OPUS_MODEL,
const fableAgent = new ClaudeCodeAgent({
model: FABLE_MODEL,
yolo: false,
tools: "", // decision/writing only — no tool use
systemPrompt: SYNTH_SYSTEM(),
172 unmodified lines
}
// ---- phase 2 drafts --------------------------------------------------------
async function opusDraft(transcript: string): Promise<string> {
const got = await acquireOpus();
async function fableDraft(transcript: string): Promise<string> {
const got = await acquireFable();
if (!got) {
console.error("[mixture] opus saturated — falling back to gpt-only synthesis this turn");
console.error("[mixture] fable saturated — falling back to gpt-only synthesis this turn");
return "";
}
try {
const res: any = await opusAgent.generate({
const res: any = await fableAgent.generate({
prompt: `Here is the full task context and all information already gathered via tools.\n\n${transcript}\n\nNow write the complete final answer.`,
timeout: OPUS_TIMEOUT_MS,
timeout: FABLE_TIMEOUT_MS,
});
return (res?.text ?? "").trim();
} finally {
releaseOpus();
releaseFable();
}
}
20 unmodified lines
};
}
// Ready to answer -> Opus 4.8 writes the final deliverable (the graded turn).
// gpt-5.5 has already done all the tool-driven gathering; Opus 4.8 — the
// Ready to answer -> Fable writes the final deliverable (the graded turn).
// gpt-5.5 has already done all the tool-driven gathering; Fable — the
// stronger synthesizer — composes the final answer from that context. This is
// the role-split mixture: GPT-5.5 gathers, Opus 4.8 synthesizes. (No LLM
// the role-split mixture: GPT-5.5 gathers, Fable synthesizes. (No LLM
// arbiter: the only LLM-as-judge in the whole pipeline is the benchmark's own
// neutral judge, keeping the fairness story minimal.)
const { transcript } = renderTranscript(req.messages);
const opusFinal = await opusDraft(transcript).catch((e) => {
console.error("[mixture] opusDraft failed:", String(e).slice(0, 200));
const fableFinal = await fableDraft(transcript).catch((e) => {
console.error("[mixture] fableDraft failed:", String(e).slice(0, 200));
return "";
});
if (opusFinal) {
return finalResult(opusFinal, g.usage, { phase: "synthesis", writer: "opus-4.8" });
if (fableFinal) {
return finalResult(fableFinal, g.usage, { phase: "synthesis", writer: "claude-fable-5" });
}
// Opus unavailable/saturated -> fall back to gpt-5.5's own final answer.
// Fable unavailable/saturated -> fall back to gpt-5.5's own final answer.
const gptFinal = (g.content ?? "").trim() || (await gptDraft(transcript).catch(() => ""));
return finalResult(gptFinal, g.usage, { phase: "synthesis", writer: "gpt-5.5", reason: "opus unavailable" });
return finalResult(gptFinal, g.usage, { phase: "synthesis", writer: "gpt-5.5", reason: "fable unavailable" });
}
function finalResult(
benchmarks/swe-bench-pro/components/agents.jsmodified+23 −27

modified (+23 −27)

Diff (+23 −27)
17 unmodified lines
18
19
20
21
22
23
24
21
22
23
24
25
27
26
27
28
30
31
29
30
31
33
34
35
36
37
32
33
34
35
36
37
38
39
43
44
45
46
40
41
42
43
48
49
50
51
52
44
45
46
47
48
55
49
50
51
58
59
52
53
54
61
62
63
55
56
57
58
59
60
61
62
17 unmodified lines
];
/**
* Claude Opus 4.8 implementer. Reads the task spec + repo and edits files in
* place to satisfy the requirements. Runs on the host `claude` CLI against the
* extracted checkout (`cwd`), using the user's subscription (the constructor
* clears ANTHROPIC_API_KEY so it does not fall back to metered API billing).
* GPT-5.5 implementer. Reads the task spec + repo and edits files in place to
* satisfy the requirements. Runs on the host `codex` CLI with workspace-write
* sandboxing scoped to the extracted checkout.
*
* @param {{ cwd: string, model?: string, timeoutMs?: number }} opts
* @returns {ClaudeCodeAgent}
* @returns {CodexAgent}
*/
export function implementerAgent(opts) {
return new ClaudeCodeAgent({
id: "opus-implementer",
return new CodexAgent({
id: "gpt-implementer",
cwd: opts.cwd,
model: opts.model ?? process.env.SWEBP_IMPLEMENTER_MODEL ?? "claude-opus-4-8",
permissionMode: "bypassPermissions",
yolo: true,
allowedTools: BUILD_TOOLS,
disallowedTools: ["WebFetch", "WebSearch"],
model: opts.model ?? process.env.SWEBP_IMPLEMENTER_MODEL ?? "gpt-5.5",
sandbox: "workspace-write",
fullAuto: true,
timeoutMs: opts.timeoutMs ?? 30 * 60 * 1000,
});
}
/**
* Codex 5.5 (GPT-5.5) reviewer/repairer. Independently re-reads the spec, audits
* Opus's working-tree diff, builds/tests what it can, and directly fixes any
* remaining gaps. Runs on the host `codex` CLI with workspace-write sandboxing
* scoped to the checkout, so it can edit but not roam the host.
* Claude Fable reviewer/repairer. Independently re-reads the spec, audits the
* GPT implementer's working-tree diff, builds/tests what it can, and directly
* fixes any remaining gaps using the user's Claude subscription.
*
* Network posture (kept symmetric with the implementer on purpose): `--full-auto`
* selects Codex's workspace-write sandbox, which disables network access by
* default — so the reviewer cannot fetch external solutions. The implementer
* keeps Bash for dependency installs but is denied WebFetch/WebSearch. Neither
* agent can reach the hidden tests, which exist only inside the scoring container.
* Network posture: the reviewer keeps Bash for local build/test commands but is
* denied WebFetch/WebSearch. Neither agent can reach the hidden tests, which
* exist only inside the scoring container.
*
* @param {{ cwd: string, model?: string, timeoutMs?: number }} opts
* @returns {CodexAgent}
* @returns {ClaudeCodeAgent}
*/
export function reviewerAgent(opts) {
return new CodexAgent({
id: "codex-reviewer",
return new ClaudeCodeAgent({
id: "fable-reviewer",
cwd: opts.cwd,
model: opts.model ?? process.env.SWEBP_REVIEWER_MODEL ?? "gpt-5.5",
sandbox: "workspace-write",
fullAuto: true,
model: opts.model ?? process.env.SWEBP_REVIEWER_MODEL ?? "claude-fable-5",
permissionMode: "bypassPermissions",
yolo: true,
allowedTools: BUILD_TOOLS,
disallowedTools: ["WebFetch", "WebSearch"],
timeoutMs: opts.timeoutMs ?? 30 * 60 * 1000,
});
}
benchmarks/claw-eval-live/gateway/src/server.tsmodified+9 −9

modified (+9 −9)

Diff (+9 −9)
13 unmodified lines
14
15
16
17
17
18
19
20
21
22
23
24
24
25
26
27
26
27
28
29
29
30
31
31
32
33
33
34
35
36
8 unmodified lines
45
46
47
48
48
49
50
51
80 unmodified lines
132
133
134
135
135
13 unmodified lines
// Bun caps idleTimeout at 255s, and a turn is idle on the socket for its whole
// gather+synthesis duration (the response is only written after both phases
// finish). mixture.ts reads its per-phase budgets from CLAW_GPT_TIMEOUT_MS +
// CLAW_OPUS_TIMEOUT_MS at module load, and their defaults (120s + 150s = 270s)
// CLAW_FABLE_TIMEOUT_MS at module load, and their defaults (120s + 150s = 270s)
// exceed that ceiling, so a slow synthesis turn would be killed by Bun before
// it could respond. Clamp the sum to fit under idleTimeout (with margin) BEFORE
// importing mixture.ts so the per-phase timeouts become the real constraint.
const IDLE_TIMEOUT_S = 255; // Bun's documented maximum.
const PHASE_BUDGET_MS = (IDLE_TIMEOUT_S - 5) * 1000; // leave headroom for I/O.
{
const opus = Number(process.env.CLAW_OPUS_TIMEOUT_MS ?? 150_000);
const fable = Number(process.env.CLAW_FABLE_TIMEOUT_MS ?? 150_000);
const gpt = Number(process.env.CLAW_GPT_TIMEOUT_MS ?? 120_000);
if (opus + gpt > PHASE_BUDGET_MS) {
const scale = PHASE_BUDGET_MS / (opus + gpt);
if (fable + gpt > PHASE_BUDGET_MS) {
const scale = PHASE_BUDGET_MS / (fable + gpt);
process.env.CLAW_GPT_TIMEOUT_MS = String(Math.floor(gpt * scale));
process.env.CLAW_OPUS_TIMEOUT_MS = String(Math.floor(opus * scale));
process.env.CLAW_FABLE_TIMEOUT_MS = String(Math.floor(fable * scale));
console.warn(
`[gateway] gather+synthesis budget ${opus + gpt}ms exceeds idle ceiling; ` +
`[gateway] gather+synthesis budget ${fable + gpt}ms exceeds idle ceiling; ` +
`clamped to CLAW_GPT_TIMEOUT_MS=${process.env.CLAW_GPT_TIMEOUT_MS} ` +
`CLAW_OPUS_TIMEOUT_MS=${process.env.CLAW_OPUS_TIMEOUT_MS}`,
`CLAW_FABLE_TIMEOUT_MS=${process.env.CLAW_FABLE_TIMEOUT_MS}`,
);
}
}
8 unmodified lines
process.on("unhandledRejection", (reason) => console.error("[gateway] unhandledRejection:", reason));
const PORT = Number(process.env.CLAW_GATEWAY_PORT ?? 8788);
const MODEL_ID = process.env.CLAW_MODEL_ID ?? "smithers-mixture-opus48-gpt55";
const MODEL_ID = process.env.CLAW_MODEL_ID ?? "smithers-mixture-fable5-gpt55";
function requireEnv() {
const missing: string[] = [];
80 unmodified lines
console.log(`[gateway] Smithers mixture brain listening on http://127.0.0.1:${server.port}`);
console.log(`[gateway] model_id=${MODEL_ID}`);
console.log(`[gateway] gather=${process.env.CLAW_GATHER_MODEL ?? "gpt-5.5"} opus=${process.env.CLAW_OPUS_MODEL ?? "opus"} arbiter=${process.env.CLAW_ARBITER_MODEL ?? "gemini-3.5-flash"}`);
console.log(`[gateway] gather=${process.env.CLAW_GATHER_MODEL ?? "gpt-5.5"} fable=${process.env.CLAW_FABLE_MODEL ?? "claude-fable-5"} arbiter=${process.env.CLAW_ARBITER_MODEL ?? "gemini-3.5-flash"}`);
benchmarks/swe-bench-pro/src/runViaGateway.jsmodified+4 −4

modified (+4 −4)

Diff (+4 −4)
56 unmodified lines
57
58
59
60
61
60
61
62
63
64
130 unmodified lines
195
196
197
198
199
198
199
200
201
202
56 unmodified lines
SWEBP_GATEWAY_HOST: host,
SWEBP_GATEWAY_WORKFLOW_KEY: key,
SWEBP_DB_PATH: join(runDir, "gateway.db"),
SWEBP_IMPLEMENTER_MODEL: opts.implementerModel ?? process.env.SWEBP_IMPLEMENTER_MODEL ?? "claude-opus-4-8",
SWEBP_REVIEWER_MODEL: opts.reviewerModel ?? process.env.SWEBP_REVIEWER_MODEL ?? "gpt-5.5",
SWEBP_IMPLEMENTER_MODEL: opts.implementerModel ?? process.env.SWEBP_IMPLEMENTER_MODEL ?? "gpt-5.5",
SWEBP_REVIEWER_MODEL: opts.reviewerModel ?? process.env.SWEBP_REVIEWER_MODEL ?? "claude-fable-5",
...(opts.token ? { SWEBP_GATEWAY_TOKEN: opts.token } : {}),
};
130 unmodified lines
dataset: `${config.upstream.dataset}:${config.upstream.datasetSplit}`,
transport: "gateway",
models: {
implementer: opts.implementerModel ?? process.env.SWEBP_IMPLEMENTER_MODEL ?? "claude-opus-4-8",
reviewer: opts.reviewerModel ?? process.env.SWEBP_REVIEWER_MODEL ?? "gpt-5.5",
implementer: opts.implementerModel ?? process.env.SWEBP_IMPLEMENTER_MODEL ?? "gpt-5.5",
reviewer: opts.reviewerModel ?? process.env.SWEBP_REVIEWER_MODEL ?? "claude-fable-5",
},
integrityChecked: !opts.skipIntegrity,
finishedAtMs: opts.nowMs ?? null,
benchmarks/swe-bench-pro/workflow.tsxmodified+4 −4

modified (+4 −4)

Diff (+4 −4)
9 unmodified lines
10
11
12
13
14
15
16
13
14
15
16
17
18
19
9 unmodified lines
* Two frontier models collaborate on a real repository checkout (already pinned
* to `base_commit` with history stripped by the runner):
*
* implementClaude Opus 4.8 reads the task spec, edits the source in place,
* and self-verifies with the repo's own build/test where it can.
* reviewCodex 5.5 independently audits the working-tree diff against the
* requirements/interface, rebuilds, and directly fixes any gaps.
* implementGPT-5.5 reads the task spec, edits the source in place, and
* self-verifies with the repo's own build/test where it can.
* reviewClaude Fable independently audits the working-tree diff against
* the requirements/interface, rebuilds, and directly fixes gaps.
*
* The agents never receive the hidden tests or the gold patchonly the
* problem statement, behavioral requirements, and interface. The runner captures
benchmarks/swe-bench-pro/src/runBenchmark.jsmodified+3 −3

modified (+3 −3)

Diff (+3 −3)
10 unmodified lines
11
12
13
14
14
15
16
17
41 unmodified lines
59
60
61
62
63
62
63
64
65
66
10 unmodified lines
*
* Instances run sequentially by default: the canonical images are amd64 and run
* under emulation on Apple Silicon, and each instance already spawns its own
* Opus + Codex subprocesses, so serial execution keeps the box responsive and
* GPT + Fable subprocesses, so serial execution keeps the box responsive and
* the timings honest. Set `concurrency > 1` only on a fast amd64 host.
*
* @param {object} opts
41 unmodified lines
const report = summarizeResults(results, {
dataset: `${config.upstream.dataset}:${config.upstream.datasetSplit}`,
models: {
implementer: opts.implementerModel ?? process.env.SWEBP_IMPLEMENTER_MODEL ?? "claude-opus-4-8",
reviewer: opts.reviewerModel ?? process.env.SWEBP_REVIEWER_MODEL ?? "gpt-5.5",
implementer: opts.implementerModel ?? process.env.SWEBP_IMPLEMENTER_MODEL ?? "gpt-5.5",
reviewer: opts.reviewerModel ?? process.env.SWEBP_REVIEWER_MODEL ?? "claude-fable-5",
},
integrityChecked: !opts.skipIntegrity,
finishedAtMs: opts.nowMs ?? null,
benchmarks/swe-bench-pro/scripts/cli.jsmodified+2 −2

modified (+2 −2)

Diff (+2 −2)
44 unmodified lines
45
46
47
48
49
48
49
50
51
52
44 unmodified lines
--limit N Cap count
Run options:
--implementer M Implementer model (default claude-opus-4-8)
--reviewer M Reviewer model (default gpt-5.5-codex)
--implementer M Implementer model (default gpt-5.5)
--reviewer M Reviewer model (default claude-fable-5)
--skip-integrity Skip gold/empty controls (faster, less rigorous)
--agent-timeout-ms Per-instance agent wall-clock cap
--report PATH Where to write the JSON report
benchmarks/swe-bench-pro/src/runWorkflowForInstance.jsmodified+2 −2

modified (+2 −2)

Diff (+2 −2)
43 unmodified lines
44
45
46
47
48
47
48
49
50
51
43 unmodified lines
const env = {
...process.env,
SWEBP_DB_PATH: dbPath,
SWEBP_IMPLEMENTER_MODEL: opts.implementerModel ?? process.env.SWEBP_IMPLEMENTER_MODEL ?? "claude-opus-4-8",
SWEBP_REVIEWER_MODEL: opts.reviewerModel ?? process.env.SWEBP_REVIEWER_MODEL ?? "gpt-5.5",
SWEBP_IMPLEMENTER_MODEL: opts.implementerModel ?? process.env.SWEBP_IMPLEMENTER_MODEL ?? "gpt-5.5",
SWEBP_REVIEWER_MODEL: opts.reviewerModel ?? process.env.SWEBP_REVIEWER_MODEL ?? "claude-fable-5",
};
const args = [
benchmarks/claw-eval-live/start-gateway.shmodified+1 −1

modified (+1 −1)

Diff (+1 −1)
14 unmodified lines
15
16
17
18
18
19
20
21
14 unmodified lines
exit 1
fi
while true; do
# Opus 4.8 is reached via the `claude` CLI subscription; unset any API key so
# Fable is reached via the `claude` CLI subscription; unset any API key so
# ClaudeCodeAgent uses subscription auth (it does this itself, but be explicit).
env -u ANTHROPIC_API_KEY bun "$HERE/gateway/src/server.ts"
code=$?

3Alongside: apps/cli

5 file(s) changed in apps/cli (+75 −47).

apps/cli/src/agent-detection.jsmodified+44 −16

modified (+44 −16)

Diff (+44 −16)
120 unmodified lines
121
122
123
124
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
136
145
146
147
148
21 unmodified lines
170
171
172
164
165
166
173
174
175
176
177
178
179
171
180
181
182
183
175
184
185
186
187
179
188
189
190
191
5 unmodified lines
197
198
199
191
200
201
202
203
195
204
205
206
207
323 unmodified lines
531
532
533
525
526
534
535
536
528
529
537
538
539
540
532
541
542
543
544
64 unmodified lines
609
610
611
603
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
120 unmodified lines
const ROLE_PREFERENCES = {
spec: ["claude", "codex", "opencode"],
research: ["antigravity", "kimi", "opencode", "codex", "claude"],
plan: ["antigravity", "codex", "opencode", "claude", "kimi"],
plan: ["claude", "codex", "opencode", "antigravity", "kimi"],
implement: ["codex", "opencode", "amp", "antigravity", "claude", "kimi"],
validate: ["codex", "opencode", "amp", "antigravity"],
review: ["claude", "amp", "codex", "opencode"],
};
const AGENT_VARIANTS = [
{
derivedFrom: "claude",
variantId: "claudeOpus",
displayName: "Claude Opus",
constructor: {
importName: "ClaudeCodeAgent",
expr: 'new SmithersClaudeCodeAgent({ model: "claude-opus-4-8", cwd: process.cwd() })',
},
},
{
derivedFrom: "claude",
variantId: "claudeSonnet",
displayName: "Claude Sonnet",
constructor: {
importName: "ClaudeCodeAgent",
expr: 'new SmithersClaudeCodeAgent({ model: "claude-sonnet-4-7", cwd: process.cwd() })',
expr: 'new SmithersClaudeCodeAgent({ model: "claude-sonnet-4-6", cwd: process.cwd() })',
},
},
];
21 unmodified lines
gemini: "gemini",
};
const TIER_PREFERENCES = {
cheapFast: { order: ["kimi", "vibe", "claudeSonnet", "antigravity", "pi"], maxSize: 2 },
smart: { order: ["codex", "opencode", "claude", "kimi", "antigravity", "amp"], maxSize: 3 },
smartTool: { order: ["claude", "codex", "opencode", "kimi", "antigravity", "amp"], maxSize: 3 },
cheapFast: { order: ["claudeSonnet", "kimi", "vibe", "antigravity", "pi"], maxSize: 2 },
smart: { order: ["claude", "claudeOpus", "codex", "opencode", "kimi", "antigravity", "amp"], maxSize: 3 },
smartTool: { order: ["codex", "opencode", "claude", "claudeOpus", "kimi", "antigravity", "amp"], maxSize: 3 },
};
const CONSTRUCTORS = {
claude: {
importName: "ClaudeCodeAgent",
expr: 'new SmithersClaudeCodeAgent({ model: "claude-opus-4-7", cwd: process.cwd() })',
expr: 'new SmithersClaudeCodeAgent({ model: "claude-fable-5", cwd: process.cwd() })',
},
codex: {
importName: "CodexAgent",
expr: 'new SmithersCodexAgent({ model: "gpt-5.3-codex", cwd: process.cwd(), skipGitRepoCheck: true })',
expr: 'new SmithersCodexAgent({ model: "gpt-5.5", cwd: process.cwd(), skipGitRepoCheck: true })',
},
opencode: {
importName: "OpenCodeAgent",
expr: 'new SmithersOpenCodeAgent({ model: "anthropic/claude-opus-4-20250514", cwd: process.cwd() })',
expr: 'new SmithersOpenCodeAgent({ model: "anthropic/claude-fable-5", cwd: process.cwd() })',
},
antigravity: {
importName: "AntigravityAgent",
5 unmodified lines
},
pi: {
importName: "PiAgent",
expr: 'new SmithersPiAgent({ provider: "openai", model: "gpt-5.3-codex" })',
expr: 'new SmithersPiAgent({ provider: "openai", model: "gpt-5.5" })',
},
kimi: {
importName: "KimiAgent",
expr: 'new SmithersKimiAgent({ model: "kimi-latest" })',
expr: 'new SmithersKimiAgent({ model: "kimi-k2.6" })',
},
amp: {
importName: "AmpAgent",
323 unmodified lines
* @type {Record<string, string>}
*/
const ACCOUNT_PROVIDER_DEFAULT_MODEL = {
"claude-code": "claude-opus-4-7",
"anthropic-api": "claude-opus-4-7",
"claude-code": "claude-fable-5",
"anthropic-api": "claude-fable-5",
"antigravity": undefined,
"codex": "gpt-5.4-codex",
"openai-api": "gpt-5.4-codex",
"codex": "gpt-5.5",
"openai-api": "gpt-5.5",
"gemini": "gemini-3.1-pro-preview",
"gemini-api": "gemini-3.1-pro-preview",
"kimi": "kimi-latest",
"kimi": "kimi-k2.6",
};
/**
64 unmodified lines
` ${family}: [${members.map((m) => `providers.${m}`).join(", ")}],`,
);
const allLabels = accounts.map((a) => labelToCamel(a.label));
poolLines.push(` smart: [${allLabels.map((m) => `providers.${m}`).join(", ")}],`);
const membersForFamilies = (...families) => {
const seen = new Set();
const members = [];
for (const family of families) {
for (const member of poolMembers.get(family) ?? []) {
if (seen.has(member)) continue;
seen.add(member);
members.push(member);
}
}
for (const member of allLabels) {
if (seen.has(member)) continue;
seen.add(member);
members.push(member);
}
return members;
};
poolLines.push(` smart: [${membersForFamilies("claude", "codex").map((m) => `providers.${m}`).join(", ")}],`);
poolLines.push(` smartTool: [${membersForFamilies("codex", "claude").map((m) => `providers.${m}`).join(", ")}],`);
poolLines.push(` cheapFast: [${membersForFamilies("kimi", "gemini", "codex", "claude").slice(0, 2).map((m) => `providers.${m}`).join(", ")}],`);
return [
"// smithers-source: generated",
"// Source of truth: ~/.smithers/accounts.json (managed via `smithers agent add|list|remove`)",
apps/cli/src/optimize-suite.jsmodified+14 −14

modified (+14 −14)

Diff (+14 −14)
32 unmodified lines
33
34
35
36
36
37
38
39
40
41
42
42
43
44
45
46
47
48
48
49
50
51
52
53
54
54
55
56
57
58
59
60
60
61
62
63
64
65
66
66
67
68
69
70
71
72
72
73
74
75
76
77
78
78
79
80
81
82
83
84
84
85
86
87
88
89
90
90
91
92
93
20 unmodified lines
114
115
116
117
117
118
119
120
121
122
123
123
124
125
126
127
128
129
129
130
131
132
133
134
135
135
136
137
138
32 unmodified lines
kind: "openai-compatible",
baseURL: "https://api.cerebras.ai/v1",
apiKeyEnv: "CEREBRAS_API_KEY",
defaultModel: "gpt-oss-120b",
defaultModel: "zai-glm-4.7",
},
"openai-api": {
kind: "openai-compatible",
baseURL: "https://api.openai.com/v1",
apiKeyEnv: "OPENAI_API_KEY",
defaultModel: "gpt-5.3-codex",
defaultModel: "gpt-5.5",
},
openai: {
kind: "openai-compatible",
baseURL: "https://api.openai.com/v1",
apiKeyEnv: "OPENAI_API_KEY",
defaultModel: "gpt-5.3-codex",
defaultModel: "gpt-5.5",
},
"openai-sdk": {
kind: "openai-compatible",
baseURL: "https://api.openai.com/v1",
apiKeyEnv: "OPENAI_API_KEY",
defaultModel: "gpt-5.3-codex",
defaultModel: "gpt-5.5",
},
codex: {
kind: "openai-compatible",
baseURL: "https://api.openai.com/v1",
apiKeyEnv: "OPENAI_API_KEY",
defaultModel: "gpt-5.3-codex",
defaultModel: "gpt-5.5",
},
"anthropic-api": {
kind: "anthropic",
baseURL: "https://api.anthropic.com/v1",
apiKeyEnv: "ANTHROPIC_API_KEY",
defaultModel: "claude-opus-4-7",
defaultModel: "claude-fable-5",
},
anthropic: {
kind: "anthropic",
baseURL: "https://api.anthropic.com/v1",
apiKeyEnv: "ANTHROPIC_API_KEY",
defaultModel: "claude-opus-4-7",
defaultModel: "claude-fable-5",
},
"anthropic-sdk": {
kind: "anthropic",
baseURL: "https://api.anthropic.com/v1",
apiKeyEnv: "ANTHROPIC_API_KEY",
defaultModel: "claude-opus-4-7",
defaultModel: "claude-fable-5",
},
"claude-code": {
kind: "anthropic",
baseURL: "https://api.anthropic.com/v1",
apiKeyEnv: "ANTHROPIC_API_KEY",
defaultModel: "claude-opus-4-7",
defaultModel: "claude-fable-5",
},
claude: {
kind: "anthropic",
baseURL: "https://api.anthropic.com/v1",
apiKeyEnv: "ANTHROPIC_API_KEY",
defaultModel: "claude-opus-4-7",
defaultModel: "claude-fable-5",
},
"gemini-api": {
kind: "gemini",
20 unmodified lines
kind: "openai-compatible",
baseURL: "https://api.moonshot.ai/v1",
apiKeyEnv: "MOONSHOT_API_KEY",
defaultModel: "kimi-latest",
defaultModel: "kimi-k2.6",
},
moonshot: {
kind: "openai-compatible",
baseURL: "https://api.moonshot.ai/v1",
apiKeyEnv: "MOONSHOT_API_KEY",
defaultModel: "kimi-latest",
defaultModel: "kimi-k2.6",
},
opencode: {
kind: "openai-compatible",
baseURLEnv: "SMITHERS_OPTIMIZER_BASE_URL",
apiKeyEnv: "SMITHERS_OPTIMIZER_API_KEY",
defaultModel: "anthropic/claude-sonnet-4-5",
defaultModel: "anthropic/claude-fable-5",
},
pi: {
kind: "openai-compatible",
baseURLEnv: "SMITHERS_OPTIMIZER_BASE_URL",
apiKeyEnv: "SMITHERS_OPTIMIZER_API_KEY",
defaultModel: "gpt-5.3-codex",
defaultModel: "gpt-5.5",
},
amp: {
kind: "openai-compatible",
apps/cli/src/workflow-pack.jsmodified+9 −9

modified (+9 −9)

Diff (+9 −9)
192 unmodified lines
193
194
195
196
196
197
198
199
11 unmodified lines
211
212
213
214
214
215
216
217
12 unmodified lines
230
231
232
233
233
234
235
236
41 unmodified lines
278
279
280
281
281
282
283
284
2694 unmodified lines
2979
2980
2981
2982
2982
2983
2984
2985
99 unmodified lines
3085
3086
3087
3088
3088
3089
3090
3091
184 unmodified lines
3276
3277
3278
3279
3279
3280
3281
3282
21 unmodified lines
3304
3305
3306
3307
3307
3308
3309
3310
779 unmodified lines
4090
4091
4092
4093
4093
4094
4095
4096
192 unmodified lines
'// Built-in Claude Code CLI agent (cliEngine: "claude-code").',
"// Tweak `model`, `cwd`, or uncomment extra options below to match your setup.",
"export const ClaudeCodeAgent = new SmithersClaudeCodeAgent({",
' model: "claude-opus-4-7",',
' model: "claude-fable-5",',
" cwd: process.cwd(),",
' // systemPrompt: "Add shared instructions for every Claude run.",',
" // timeoutMs: 10 * 60 * 1000,",
11 unmodified lines
'// Built-in Codex CLI agent (cliEngine: "codex").',
"// Tweak `model`, `cwd`, or uncomment extra options below to match your setup.",
"export const CodexAgent = new SmithersCodexAgent({",
' model: "gpt-5.3-codex",',
' model: "gpt-5.5",',
" cwd: process.cwd(),",
" skipGitRepoCheck: true,",
' // systemPrompt: "Add shared instructions for every Codex run.",',
12 unmodified lines
'// Built-in OpenCode CLI agent (cliEngine: "opencode").',
"// Tweak `model`, `cwd`, or uncomment extra options below to match your setup.",
"export const OpenCodeAgent = new SmithersOpenCodeAgent({",
' model: "anthropic/claude-sonnet-4-5",',
' model: "anthropic/claude-fable-5",',
" cwd: process.cwd(),",
' // agentName: "build",',
' // systemPrompt: "Add shared instructions for every OpenCode run.",',
41 unmodified lines
"",
"- `claude-code.ts`, `codex.ts`, `opencode.ts`, and `antigravity.ts` are user-owned config.",
"- Edit them to pin models, set `cwd`, add a shared `systemPrompt`, or enable engine-specific flags.",
"- `index.ts` re-exports all three so root-level files can import from `./agents`.",
"- `index.ts` re-exports all four so root-level files can import from `./agents`.",
"",
"Examples:",
"",
2694 unmodified lines
" <ValidationLoop",
' idPrefix="impl"',
" prompt={ctx.input.prompt}",
" implementAgents={agents.smart}",
" implementAgents={agents.smartTool}",
" validateAgents={agents.cheapFast}",
" reviewAgents={agents.smart}",
" feedback={feedback}",
99 unmodified lines
" <ValidationLoop",
' idPrefix="impl"',
" prompt={implementPrompt}",
" implementAgents={agents.smart}",
" implementAgents={agents.smartTool}",
" validateAgents={agents.cheapFast}",
" reviewAgents={agents.smart}",
" feedback={feedback}",
184 unmodified lines
" <ValidationLoop",
' idPrefix="improve-test-coverage"',
" prompt={ctx.input.prompt}",
" implementAgents={agents.smart}",
" implementAgents={agents.smartTool}",
" validateAgents={agents.cheapFast}",
" reviewAgents={agents.smart}",
" />",
21 unmodified lines
" <ValidationLoop",
' idPrefix="debug"',
" prompt={ctx.input.prompt}",
" implementAgents={agents.smart}",
" implementAgents={agents.smartTool}",
" validateAgents={agents.cheapFast}",
" reviewAgents={agents.smart}",
" />",
779 unmodified lines
" <ValidationLoop",
" idPrefix={ticket.slug}",
" prompt={`Implement the ticket below.\\n\\nTICKET FILE: .smithers/tickets/${ticket.id}\\n\\n${ticket.content}`}",
" implementAgents={agents.smart}",
" implementAgents={agents.smartTool}",
" validateAgents={agents.smart}",
" reviewAgents={agents.smart}",
" feedback={feedback}",
apps/cli/src/ask.jsmodified+6 −6

modified (+6 −6)

Diff (+6 −6)
311 unmodified lines
312
313
314
315
315
316
317
318
4 unmodified lines
323
324
325
326
326
327
328
329
9 unmodified lines
339
340
341
342
342
343
344
345
3 unmodified lines
349
350
351
352
352
353
354
355
28 unmodified lines
384
385
386
387
387
388
389
390
8 unmodified lines
399
400
401
402
402
403
404
405
311 unmodified lines
return {
agent: new ClaudeCodeAgent({
cwd,
model: "claude-sonnet-4-20250514",
model: "claude-fable-5",
systemPrompt,
dangerouslySkipPermissions: true,
}),
4 unmodified lines
return {
agent: new ClaudeCodeAgent({
cwd,
model: "claude-sonnet-4-20250514",
model: "claude-fable-5",
mcpConfig: [mcpConfig.path],
strictMcpConfig: true,
systemPrompt,
9 unmodified lines
return {
agent: new KimiAgent({
cwd,
model: "kimi-latest",
model: "kimi-k2.6",
systemPrompt,
}),
cleanup() { },
3 unmodified lines
return {
agent: new KimiAgent({
cwd,
model: "kimi-latest",
model: "kimi-k2.6",
mcpConfigFile: [mcpConfig.path],
systemPrompt,
}),
28 unmodified lines
return {
agent: new CodexAgent({
cwd,
model: "gpt-5.3-codex",
model: "gpt-5.5",
config: bootstrap.mode === "mcp-config-inline"
? bootstrap.configOverrides
: undefined,
8 unmodified lines
agent: new PiAgent({
cwd,
provider: "openai",
model: "gpt-5.3-codex",
model: "gpt-5.5",
systemPrompt,
}),
cleanup() { },
apps/cli/src/index.jsmodified+2 −2

modified (+2 −2)

Diff (+2 −2)
5869 unmodified lines
5870
5871
5872
5873
5873
5874
5875
5876
5877
5878
5879
5880
5880
5881
5882
5883
5869 unmodified lines
const { ClaudeCodeAgent } = await import("@smithers-orchestrator/agents/ClaudeCodeAgent");
return new ClaudeCodeAgent({
cwd,
model: "claude-opus-4-7",
model: "claude-fable-5",
});
}
case "codex": {
const { CodexAgent } = await import("@smithers-orchestrator/agents/CodexAgent");
return new CodexAgent({
cwd,
model: "gpt-5.3-codex",
model: "gpt-5.5",
skipGitRepoCheck: true,
});
}

4Alongside: scripts

1 file(s) changed in scripts (+44 −0).

scripts/sandbox.tsadded+44 −0

added (+44 −0)

Diff (+44 −0)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#!/usr/bin/env bun
import { execSync, spawnSync } from "child_process";
import { existsSync, readFileSync, writeFileSync, unlinkSync } from "fs";
const STATE_FILE = ".sandbox-vm";
const ZONE = "us-central1-a";
const MACHINE_TYPE = "e2-small";
const cmd = process.argv[2];
function vmName(): string {
const ts = new Date().toISOString().replace(/[-:T.Z]/g, "").slice(0, 14);
return `sandbox-${ts}`;
}
if (cmd === "up") {
const name = vmName();
console.log(`Creating ${name} (${MACHINE_TYPE}) in ${ZONE}...`);
execSync(
`gcloud compute instances create ${name}` +
` --machine-type=${MACHINE_TYPE}` +
` --image-family=debian-12` +
` --image-project=debian-cloud` +
` --zone=${ZONE}`,
{ stdio: "inherit" },
);
writeFileSync(STATE_FILE, JSON.stringify({ name, zone: ZONE }));
console.log(`\nConnecting to ${name}...`);
spawnSync("gcloud", ["compute", "ssh", name, `--zone=${ZONE}`, "--ssh-flag=-A"], { stdio: "inherit" });
console.log(`\nSession ended. Run 'pnpm sandbox:down' to delete the VM.`);
} else if (cmd === "down") {
if (!existsSync(STATE_FILE)) {
console.error("No sandbox VM found. Nothing to delete.");
process.exit(1);
}
const { name, zone } = JSON.parse(readFileSync(STATE_FILE, "utf8"));
console.log(`Deleting ${name}...`);
execSync(`gcloud compute instances delete ${name} --zone=${zone} --quiet`, { stdio: "inherit" });
unlinkSync(STATE_FILE);
console.log("Deleted.");
} else {
console.error("Usage: pnpm sandbox:[up|down]");
process.exit(1);
}

5Alongside: apps/smithers-studio-2

1 file(s) changed in apps/smithers-studio-2 (+10 −9).

apps/smithers-studio-2/server/workspaceBackend.tsmodified+10 −9

modified (+10 −9)

Diff (+10 −9)
305 unmodified lines
306
307
308
309
309
310
311
312
5 unmodified lines
318
319
320
321
322
321
322
323
324
325
325
326
326
327
328
329
3 unmodified lines
333
334
335
336
336
337
338
339
339
340
341
341
342
343
344
344
345
346
347
348
305 unmodified lines
};
const AGENT_ROLES: Record<string, string[]> = {
claude: ["coding", "review", "spec"],
claude: ["coding", "review", "spec", "plan"],
codex: ["coding", "implement"],
antigravity: ["coding", "research", "plan"],
gemini: ["coding", "research"],
5 unmodified lines
const AGENT_MODELS: Record<string, Array<{ id: string; label: string }>> = {
claude: [
{ id: "claude-sonnet-4-20250514", label: "Claude Sonnet 4" },
{ id: "claude-opus-4-7", label: "Claude Opus 4.7" },
{ id: "claude-fable-5", label: "Claude Fable 5" },
{ id: "claude-opus-4-8", label: "Claude Opus 4.8" },
{ id: "claude-sonnet-4-6", label: "Claude Sonnet 4.6" },
],
codex: [
{ id: "gpt-5.3-codex", label: "GPT-5.3 Codex" },
{ id: "gpt-5.4-codex", label: "GPT-5.4 Codex" },
{ id: "gpt-5.5", label: "GPT-5.5" },
],
antigravity: [
{ id: "gemini-3.1-pro-preview", label: "Gemini 3.1 Pro Preview" },
3 unmodified lines
{ id: "gemini-2.5-flash", label: "Gemini 2.5 Flash" },
],
pi: [
{ id: "gpt-5.3-codex", label: "GPT-5.3 Codex" },
{ id: "gpt-5.5", label: "GPT-5.5" },
],
opencode: [
{ id: "anthropic/claude-opus-4-20250514", label: "Claude Opus via OpenCode" },
{ id: "anthropic/claude-fable-5", label: "Claude Fable via OpenCode" },
{ id: "anthropic/claude-opus-4-8", label: "Claude Opus via OpenCode" },
{ id: "github-copilot/claude-sonnet-4.6", label: "Claude Sonnet via Copilot" },
{ id: "openai/gpt-5.3-codex", label: "GPT-5.3 Codex via OpenCode" },
{ id: "openai/gpt-5.5", label: "GPT-5.5 via OpenCode" },
],
kimi: [
{ id: "kimi-latest", label: "Kimi Latest" },
{ id: "kimi-k2.6", label: "Kimi K2.6" },
],
};

6Alongside: apps/smithers

5 file(s) changed in apps/smithers (+7 −7).

apps/smithers/src/agents/agents.tsmodified+2 −2

modified (+2 −2)

Diff (+2 −2)
46 unmodified lines
47
48
49
50
50
51
52
53
217 unmodified lines
271
272
273
274
274
275
276
277
46 unmodified lines
name: "Cerebras",
initials: "Cb",
color: "#bf5b16",
detail: "gpt-oss-120b · chat",
detail: "zai-glm-4.7 · chat",
auth: "key set",
available: true,
},
217 unmodified lines
label: "cerebras",
providerId: "openai-api",
name: "Cerebras (OpenAI-compatible)",
model: "gpt-oss-120b",
model: "zai-glm-4.7",
roles: ["chat"],
command: "cerebras",
binary: "",
apps/smithers/src/worker.tsmodified+2 −2

modified (+2 −2)

Diff (+2 −2)
16 unmodified lines
17
18
19
20
21
20
21
22
23
24
16 unmodified lines
/** Cerebras' OpenAI-compatible Chat Completions endpoint (default upstream). */
const DEFAULT_CEREBRAS_BASE_URL = "https://api.cerebras.ai/v1";
/** The Cerebras model the chat runs on — the very fast gpt-oss-120b. */
const DEFAULT_CEREBRAS_MODEL = "gpt-oss-120b";
/** The Cerebras model the chat runs on. */
const DEFAULT_CEREBRAS_MODEL = "zai-glm-4.7";
/** Most messages we will forward to Cerebras in a single request. */
const MAX_MESSAGES = 100;
apps/smithers/alchemy.run.tsmodified+1 −1

modified (+1 −1)

Diff (+1 −1)
2 unmodified lines
3
4
5
6
6
7
8
9
2 unmodified lines
*
* Deploys the PWA to Cloudflare as a single Worker that:
* - serves the built Vite app (dist/) as static assets with SPA routing, and
* - handles POST /api/chat by running Cerebras (gpt-oss-120b) server-side.
* - handles POST /api/chat by running Cerebras (`zai-glm-4.7`) server-side.
*
* Deploy: bun run deploy (or: pnpm deploy)
* Destroy: bun run destroy
apps/smithers/mockups/smithers-feature-gap.htmlmodified+1 −1

modified (+1 −1)

Diff (+1 −1)
784 unmodified lines
785
786
787
788
788
789
790
791
784 unmodified lines
<div class="cb" style="padding-top:4px;padding-bottom:4px">
<div class="lrow"><div class="av" style="background:#0f8f78">C</div><div><div class="nm">Claude Code</div><div class="meta">claude-opus-4-8 · code, review</div></div><div class="tags"><span class="mini ok">oauth</span><span class="statusdot on"></span></div></div>
<div class="lrow"><div class="av" style="background:#356fd2">X</div><div><div class="nm">Codex</div><div class="meta">gpt-5.5 · code</div></div><div class="tags"><span class="mini ok">key set</span><span class="statusdot on"></span></div></div>
<div class="lrow"><div class="av" style="background:#bf5b16">Cb</div><div><div class="nm">Cerebras</div><div class="meta">gpt-oss-120b · chat</div></div><div class="tags"><span class="mini ok">key set</span><span class="statusdot on"></span></div></div>
<div class="lrow"><div class="av" style="background:#bf5b16">Cb</div><div><div class="nm">Cerebras</div><div class="meta">zai-glm-4.7 · chat</div></div><div class="tags"><span class="mini ok">key set</span><span class="statusdot on"></span></div></div>
<div class="lrow off"><div class="av" style="background:#9a9aa3">G</div><div><div class="nm">Gemini</div><div class="meta">not detected</div></div><div class="tags"><span class="mini">no key</span><span class="statusdot off"></span></div></div>
</div>
</div></div>
apps/smithers/src/env.tsmodified+1 −1

modified (+1 −1)

Diff (+1 −1)
10 unmodified lines
11
12
13
14
14
15
16
17
10 unmodified lines
* the whole gateway path can be exercised without a real key.
*/
CEREBRAS_BASE_URL?: string;
/** Override for the upstream model id. Defaults to gpt-oss-120b. */
/** Override for the upstream model id. Defaults to zai-glm-4.7. */
CEREBRAS_MODEL?: string;
/**
* Optional Plue API origin used for Smithers browser auth. When configured,

7Alongside: apps/smithers-demo

1 file(s) changed in apps/smithers-demo (+2 −2).

apps/smithers-demo/src/cerebrasDebate.jsmodified+2 −2

modified (+2 −2)

Diff (+2 −2)
1 unmodified line
2
3
4
5
5
6
7
7
8
9
10
1 unmodified line
const OPENAI_CHAT_URL = "https://api.openai.com/v1/chat/completions";
const ANTHROPIC_MESSAGES_URL = "https://api.anthropic.com/v1/messages";
export const DEFAULT_CEREBRAS_MODEL = "gpt-oss-120b";
export const DEFAULT_CEREBRAS_MODEL = "zai-glm-4.7";
export const DEFAULT_OPENAI_MODEL = "gpt-5.5";
export const DEFAULT_ANTHROPIC_MODEL = "claude-opus-4.7";
export const DEFAULT_ANTHROPIC_MODEL = "claude-fable-5";
export const DEBATE_E2E_PROMPT =
"Do a loop where you have two LMs debate communism versus capitalism and then have a judge LM output a final result.";

8Alongside: packages/scorers

2 file(s) changed in packages/scorers (+2 −2).

packages/scorers/src/index.d.tsmodified+1 −1

modified (+1 −1)

Diff (+1 −1)
195 unmodified lines
196
197
198
199
199
200
201
202
195 unmodified lines
* id: "tone",
* name: "Professional Tone",
* description: "Evaluates professional tone",
* judge: new AnthropicAgent({ model: "claude-sonnet-4-20250514" }),
* judge: new AnthropicAgent({ model: "claude-fable-5" }),
* instructions: "You evaluate text for professional tone.",
* promptTemplate: ({ output }) =>
* `Rate the professionalism of this text (0-1 JSON):\n\n${String(output)}`,
packages/scorers/src/llmJudge.jsmodified+1 −1

modified (+1 −1)

Diff (+1 −1)
76 unmodified lines
77
78
79
80
80
81
82
83
76 unmodified lines
* id: "tone",
* name: "Professional Tone",
* description: "Evaluates professional tone",
* judge: new AnthropicAgent({ model: "claude-sonnet-4-20250514" }),
* judge: new AnthropicAgent({ model: "claude-fable-5" }),
* instructions: "You evaluate text for professional tone.",
* promptTemplate: ({ output }) =>
* `Rate the professionalism of this text (0-1 JSON):\n\n${String(output)}`,

9Alongside: packages/agents

1 file(s) changed in packages/agents (+1 −1).

packages/agents/src/diagnostics/getDiagnosticStrategy.jsmodified+1 −1

modified (+1 −1)

Diff (+1 −1)
112 unmodified lines
113
114
115
116
116
117
118
119
112 unmodified lines
"content-type": "application/json",
},
body: JSON.stringify({
model: "claude-sonnet-4-20250514",
model: "claude-fable-5",
messages: [{ role: "user", content: "hi" }],
}),
signal: AbortSignal.timeout(4_000),

10Alongside: packages/usage

1 file(s) changed in packages/usage (+1 −1).

packages/usage/src/anthropicHeaderUsage.jsmodified+1 −1

modified (+1 −1)

Diff (+1 −1)
4 unmodified lines
5
6
7
8
8
9
10
11
4 unmodified lines
const COUNT_TOKENS_URL = "https://api.anthropic.com/v1/messages/count_tokens";
/** The count_tokens probe needs a valid model id but generates no output tokens. */
const PROBE_MODEL = process.env.SMITHERS_ANTHROPIC_PROBE_MODEL ?? "claude-sonnet-4-20250514";
const PROBE_MODEL = process.env.SMITHERS_ANTHROPIC_PROBE_MODEL ?? "claude-fable-5";
/**
* Reads live Anthropic rate-limit headers for an API-key account. Uses the

11Alongside: .smithers

1 file(s) changed in .smithers (+0 −1).

.smithers/ui/close-issues.tsxmodified+0 −1

modified (+0 −1)

Diff (+0 −1)
187 unmodified lines
188
189
190
191
191
192
193
187 unmodified lines
await Promise.all([
runsQuery.refetch(),
runDetail.refetch(),
stream.refetch?.(),
approvalsQuery.refetch(),
discoverOut.refetch(),
].filter(Boolean) as Promise<unknown>[]);

12Wiring and configuration

Build, dependency, and configuration changes that support the work above.

apps/review/package.jsonmodified+4 −1

modified (+4 −1)

Diff (+4 −1)
12 unmodified lines
13
14
15
16
16
17
18
19
20
21
6 unmodified lines
28
29
30
31
32
33
34
12 unmodified lines
"scripts": {
"start": "bun ./src/cli/main.ts",
"test": "bun test tests",
"typecheck": "tsc -p tsconfig.json --noEmit"
"typecheck": "tsc -p tsconfig.json --noEmit",
"deploy": "alchemy deploy",
"destroy": "alchemy destroy"
},
"dependencies": {
"@pierre/diffs": "^1.2.9",
6 unmodified lines
},
"devDependencies": {
"@types/node": "25.6.0",
"alchemy": "^0.93.11",
"bun-types": "^1.3.12",
"react": "19.2.4",
"react-dom": "19.2.4",
benchmarks/claw-eval-live/config.smithers.yamlmodified+2 −2

modified (+2 −2)

Diff (+2 −2)
3 unmodified lines
4
5
6
7
7
8
9
10
10
11
12
13
3 unmodified lines
model:
api_key: smithers-local # unused by the gateway; client requires a value
base_url: http://127.0.0.1:8788/v1 # the Smithers mixture brain
model_id: smithers-mixture-opus48-gpt55
model_id: smithers-mixture-fable5-gpt55
input_modalities: [text, image] # gpt-5.5 (gather) is vision-capable
# Neutral judge: Gemini — NOT one of the two contestant models (Opus 4.8 / gpt-5.5),
# Neutral judge: Gemini — NOT one of the two contestant models (Fable / gpt-5.5),
# so the communication dimension cannot be self-graded. This is exactly the judge
# the benchmark authors recommend (config_template.yaml -> gemini-3-flash-preview).
judge:
package.jsonmodified+3 −1

modified (+3 −1)

Diff (+3 −1)
79 unmodified lines
80
81
82
83
83
84
85
86
87
88
79 unmodified lines
"docs:llms": "bun scripts/generate-llms.ts && bun scripts/optimize-llms-full.ts",
"docs": "cd docs && bunx mintlify dev",
"version": "node scripts/bump.mjs",
"release": "node scripts/publish.mjs"
"release": "node scripts/publish.mjs",
"sandbox:up": "bun scripts/sandbox.ts up",
"sandbox:down": "bun scripts/sandbox.ts down"
},
"pnpm": {
"overrides": {
pnpm-lock.yamlmodified+3 −0

modified (+3 −0)

Diff (+3 −0)
359 unmodified lines
360
361
362
363
364
365
366
367
368
359 unmodified lines
'@types/node':
specifier: 25.6.0
version: 25.6.0
alchemy:
specifier: ^0.93.11
version: 0.93.11(@cloudflare/vite-plugin@1.39.2(vite@8.0.14(@types/node@25.6.0)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3))(workerd@1.20260601.1)(wrangler@4.97.0(@cloudflare/workers-types@4.20260604.1)))(@electric-sql/pglite@0.5.1)(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.13)(better-sqlite3@11.10.0)(bun-types@1.3.14)(pg@8.21.0)(vite@8.0.14(@types/node@25.6.0)(esbuild@0.28.0)(tsx@4.22.4)(yaml@2.8.3))(workerd@1.20260601.1)
bun-types:
specifier: ^1.3.12
version: 1.3.14
.smithers/package.jsonmodified+1 −1

modified (+1 −1)

Diff (+1 −1)
8 unmodified lines
9
10
11
12
12
13
14
15
8 unmodified lines
"lint:fix": "oxlint --react-plugin --node-plugin --import-plugin --ignore-path ../.gitignore --fix .",
"workflow:list": "smithers workflow list",
"workflow:run": "smithers workflow run",
"workflow:implement": "smithers workflow implement",
"workflow:implement": "smithers workflow run implement",
"test:open-code-review": "bun test ./tests/open-code-review.test.ts ./tests/open-code-review-ui.e2e.test.ts"
},
"dependencies": {
apps/review/tsconfig.jsonmodified+1 −1

modified (+1 −1)

Diff (+1 −1)
22 unmodified lines
23
24
25
26
26
27
22 unmodified lines
"smithers-workflows/*": ["../../.smithers/*"]
}
},
"include": ["src/**/*", "tests/**/*"]
"include": ["src/**/*", "tests/**/*", "alchemy.run.ts"]
}
benchmarks/claw-eval-live/gateway/package.jsonmodified+1 −1

modified (+1 −1)

Diff (+1 −1)
2 unmodified lines
3
4
5
6
6
7
8
9
2 unmodified lines
"version": "0.0.0",
"private": true,
"type": "module",
"description": "OpenAI-compatible gateway exposing a Smithers mixture of Claude Opus 4.8 + gpt-5.5 as the agent brain for the Claw-Eval-Live benchmark.",
"description": "OpenAI-compatible gateway exposing a Smithers mixture of Claude Fable + gpt-5.5 as the agent brain for the Claw-Eval-Live benchmark.",
"scripts": {
"start": "bun src/server.ts"
}

13The proof: tests

Tests added or updated for this change.

apps/cli/tests/init-agents.e2e.test.jsmodified+5 −5not agent-reviewed (default_path)

modified (+5 −5)

Diff (+5 −5)
30 unmodified lines
31
32
33
34
35
34
35
36
37
38
14 unmodified lines
53
54
55
56
56
57
58
59
36 unmodified lines
96
97
98
99
100
99
100
101
102
103
30 unmodified lines
expect(agentsSource).toContain('export { ClaudeCodeAgent } from "./agents/claude-code";');
expect(agentsSource).toContain("claude: ClaudeCodeAgent");
expect(agentsSource).toContain("cheapFast: [providers.claudeSonnet]");
expect(agentsSource).toContain("smart: [providers.claude]");
expect(agentsSource).toContain("smartTool: [providers.claude]");
expect(agentsSource).toContain("smart: [providers.claude, providers.claudeOpus]");
expect(agentsSource).toContain("smartTool: [providers.claude, providers.claudeOpus]");
expect(agentsSource).not.toContain("providers.codex");
});
test("smithers init includes Codex implementation roles when Codex plus OPENAI_API_KEY are available", () => {
14 unmodified lines
expect(agentsSource).toContain("cheapFast: [providers.codex]");
expect(agentsSource).toContain("smart: [providers.codex]");
expect(agentsSource).toContain("smartTool: [providers.codex]");
expect(agentsSource).toContain("smartTool: Smithers would normally suggest Claude Code here");
expect(agentsSource).toContain("smart: Smithers would normally suggest Claude Code here");
expect(agentsSource).toContain("cheapFast: Smithers would normally suggest Kimi here");
});
test("smithers init includes OpenCode roles when OpenCode CLI credentials are available", () => {
36 unmodified lines
expect(result.exitCode).toBe(0);
const agentsSource = repo.read(".smithers/agents.ts");
expect(agentsSource).toContain("cheapFast: [providers.claudeSonnet, providers.antigravity]");
expect(agentsSource).toContain("smart: [providers.codex, providers.opencode, providers.claude]");
expect(agentsSource).toContain("smartTool: [providers.claude, providers.codex, providers.opencode]");
expect(agentsSource).toContain("smart: [providers.claude, providers.claudeOpus, providers.codex]");
expect(agentsSource).toContain("smartTool: [providers.codex, providers.opencode, providers.claude]");
expect(agentsSource).not.toContain("providers.gemini");
});
test("smithers init exits with a typed error when no usable agents are detected", () => {
apps/cli/tests/agents-ts-codegen.test.jsmodified+7 −2not agent-reviewed (default_path)

modified (+7 −2)

Diff (+7 −2)
40 unmodified lines
41
42
43
44
44
45
46
47
48
49
50
55 unmodified lines
106
107
108
109
110
111
112
21 unmodified lines
134
135
136
134
137
138
139
140
141
1 unmodified line
143
144
145
146
147
148
149
40 unmodified lines
// pools group by engine family
expect(generated).toContain("claude: [providers.claudeWork, providers.claudePersonal]");
expect(generated).toContain("codex: [providers.codexWork]");
// smart pool combines all
// Smart pools are role-ordered: Claude/Fable first for planning/review,
// Codex/GPT first for implementation/tooling.
expect(generated).toContain("smart: [providers.claudeWork, providers.claudePersonal, providers.codexWork]");
expect(generated).toContain("smartTool: [providers.codexWork, providers.claudeWork, providers.claudePersonal]");
});
test("path.join(homedir(), ...) is used for paths under $HOME", () => {
55 unmodified lines
preserveProviderIds: extractGeneratedDetectionProviderIds(initial),
});
expect(regenerated).toContain("claude: ClaudeCodeAgent");
expect(regenerated).toContain("claudeOpus: new SmithersClaudeCodeAgent(");
expect(regenerated).toContain("claudeSonnet: new SmithersClaudeCodeAgent(");
expect(regenerated).toContain("codexProd: new SmithersCodexAgent(");
});
21 unmodified lines
"// smithers-source: generated",
"export const providers = {",
" claude: ClaudeCodeAgent,",
" claudeSonnet: new SmithersClaudeCodeAgent({ model: \"claude-sonnet-4-7\", cwd: process.cwd() }),",
" claudeOpus: new SmithersClaudeCodeAgent({ model: \"claude-opus-4-8\", cwd: process.cwd() }),",
" claudeSonnet: new SmithersClaudeCodeAgent({ model: \"claude-sonnet-4-6\", cwd: process.cwd() }),",
"} as const;",
"",
].join("\n");
1 unmodified line
preserveProviderIds: extractGeneratedDetectionProviderIds(previous),
});
expect(generated).toContain("claude: ClaudeCodeAgent");
expect(generated).toContain("claudeOpus: new SmithersClaudeCodeAgent(");
expect(generated).toContain("claudeSonnet: new SmithersClaudeCodeAgent(");
expect(generated).toContain("codexProd: new SmithersCodexAgent(");
});
apps/smithers-demo/tests/cerebrasDebate.e2e.test.tsmodified+4 −4not agent-reviewed (default_path)

modified (+4 −4)

Diff (+4 −4)
43 unmodified lines
44
45
46
47
47
48
49
50
11 unmodified lines
62
63
64
65
65
66
67
68
69
70
71
72
72
73
74
75
14 unmodified lines
90
91
92
93
93
94
95
96
43 unmodified lines
await callProviderChat({
provider: "anthropic",
apiKey: "anthropic-key",
model: "claude-opus-4.7",
model: "claude-fable-5",
messages: [
{ role: "system", content: "judge fairly" },
{ role: "user", content: DEBATE_E2E_PROMPT },
11 unmodified lines
expect(JSON.parse(String(requests[0].init.body))).toMatchObject({ model: "gpt-5.5" });
expect(requests[1].url).toBe("https://api.anthropic.com/v1/messages");
expect(requests[1].init.headers).toMatchObject({ "x-api-key": "anthropic-key" });
expect(JSON.parse(String(requests[1].init.body))).toMatchObject({ model: "claude-opus-4.7" });
expect(JSON.parse(String(requests[1].init.body))).toMatchObject({ model: "claude-fable-5" });
});
test("posts to the real Cerebras chat completions endpoint shape", async () => {
const requests: Array<{ url: string; init: RequestInit }> = [];
const content = await callCerebrasChat({
apiKey: "test-key",
model: "gpt-oss-120b",
model: "zai-glm-4.7",
messages: [{ role: "user", content: DEBATE_E2E_PROMPT }],
fetchImpl: (async (url, init) => {
requests.push({ url: String(url), init: init ?? {} });
14 unmodified lines
"Content-Type": "application/json",
});
expect(JSON.parse(String(requests[0].init.body))).toMatchObject({
model: "gpt-oss-120b",
model: "zai-glm-4.7",
messages: [{ role: "user", content: DEBATE_E2E_PROMPT }],
});
});
apps/cli/tests/optimize-suite.test.jsmodified+2 −2not agent-reviewed (default_path)

modified (+2 −2)

Diff (+2 −2)
135 unmodified lines
136
137
138
139
139
140
141
142
35 unmodified lines
178
179
180
181
181
182
183
184
135 unmodified lines
expect(getOptimizerProviderConfig("codex")?.kind).toBe("openai-compatible");
expect(getOptimizerProviderConfig("antigravity")?.kind).toBe("gemini");
expect(getOptimizerProviderConfig("kimi")?.kind).toBe("openai-compatible");
expect(resolveOptimizerProviderModel("cerebras")).toBe("gpt-oss-120b");
expect(resolveOptimizerProviderModel("cerebras")).toBe("zai-glm-4.7");
expect(resolveOptimizerProviderModel("openai-compatible", "custom-model")).toBe("custom-model");
});
35 unmodified lines
}, { fetch: fakeFetch, env: { OPENAI_API_KEY: "openai-key" } });
expect(openaiPatches.answer.source).toBe("codex-gepa");
expect(calls.at(-1).url).toBe("https://api.openai.com/v1/chat/completions");
expect(calls.at(-1).body.model).toBe("gpt-5.3-codex");
expect(calls.at(-1).body.model).toBe("gpt-5.5");
await buildProviderGepaPatches({
provider: "claude-code",

14The paper trail: docs

Documentation that records the change.

apps/cli/docs/llms-full.txtmodified+109 −29not agent-reviewed (unsupported_ext)

modified (+109 −29)

Diff (+109 −29)
687 unmodified lines
688
689
690
691
691
692
693
694
37 unmodified lines
732
733
734
735
735
736
737
738
739
740
740
741
742
743
1571 unmodified lines
2315
2316
2317
2318
2318
2319
2320
2321
67 unmodified lines
2389
2390
2391
2392
2392
2393
2394
2395
3874 unmodified lines
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
1263 unmodified lines
7619
7620
7621
7542
7622
7623
7624
7625
26 unmodified lines
7652
7653
7654
7575
7655
7656
7657
7658
7 unmodified lines
7666
7667
7668
7589
7669
7670
7671
7672
3 unmodified lines
7676
7677
7678
7599
7600
7601
7679
7680
7681
7682
7603
7604
7605
7683
7684
7685
7686
7687
7688
156 unmodified lines
7845
7846
7847
7768
7848
7849
7850
7851
1888 unmodified lines
9740
9741
9742
9663
9743
9744
9745
9746
65 unmodified lines
9812
9813
9814
9735
9815
9816
9817
9818
38 unmodified lines
9857
9858
9859
9780
9860
9861
9862
9863
273 unmodified lines
10137
10138
10139
10060
10140
10141
10142
10143
10144
10145
10146
10067
10147
10148
10149
10150
9 unmodified lines
10160
10161
10162
10083
10163
10164
10165
10166
101 unmodified lines
10268
10269
10270
10191
10271
10272
10273
10274
10195
10275
10276
10277
10278
36 unmodified lines
10315
10316
10317
10238
10318
10319
10320
10321
242 unmodified lines
10564
10565
10566
10487
10567
10568
10569
10570
26 unmodified lines
10597
10598
10599
10520
10600
10601
10602
10603
84 unmodified lines
10688
10689
10690
10611
10691
10692
10693
10694
18 unmodified lines
10713
10714
10715
10636
10716
10717
10718
10719
19 unmodified lines
10739
10740
10741
10662
10742
10743
10744
10745
687 unmodified lines
});
const analyst = new AnthropicAgent({
model: "claude-sonnet-4-20250514",
model: "claude-fable-5",
instructions: "You are a senior code reviewer. Return structured JSON.",
});
37 unmodified lines
});
const analyst = new AnthropicAgent({
model: "claude-sonnet-4-20250514",
model: "claude-fable-5",
instructions: "You are a senior code reviewer. Return structured JSON.",
});
const fixer = new AnthropicAgent({
model: "claude-sonnet-4-20250514",
model: "claude-fable-5",
instructions: "Write minimal, correct fixes as a unified diff.",
});
1571 unmodified lines
});
const researcher = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
instructions: "You are a research assistant.",
});
67 unmodified lines
import { anthropic } from "@ai-sdk/anthropic";
const codeAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
instructions: "You are a senior software engineer.",
});
3874 unmodified lines
| { type: "bearer"; token: string }
| { type: "basic"; username: string; password: string };
type OpenApiRefObject = {
$ref: string;
};
type OpenApiSchemaObject = {
type?: string;
format?: string;
description?: string;
properties?: Record<string, OpenApiSchemaObject | OpenApiRefObject>;
required?: string[];
items?: OpenApiSchemaObject | OpenApiRefObject;
enum?: unknown[];
default?: unknown;
nullable?: boolean;
oneOf?: Array<OpenApiSchemaObject | OpenApiRefObject>;
anyOf?: Array<OpenApiSchemaObject | OpenApiRefObject>;
allOf?: Array<OpenApiSchemaObject | OpenApiRefObject>;
additionalProperties?: boolean | OpenApiSchemaObject | OpenApiRefObject;
minimum?: number;
maximum?: number;
minLength?: number;
maxLength?: number;
pattern?: string;
$ref?: string;
};
type OpenApiParameterObject = {
name: string;
in: "query" | "header" | "path" | "cookie";
description?: string;
required?: boolean;
schema?: OpenApiSchemaObject | OpenApiRefObject;
deprecated?: boolean;
};
type OpenApiRequestBodyObject = {
description?: string;
required?: boolean;
content: Record<string, { schema?: OpenApiSchemaObject | OpenApiRefObject }>;
};
type OpenApiOperationObject = {
operationId?: string;
summary?: string;
description?: string;
parameters?: Array<OpenApiParameterObject | OpenApiRefObject>;
requestBody?: OpenApiRequestBodyObject | OpenApiRefObject;
responses?: Record<string, unknown>;
tags?: string[];
deprecated?: boolean;
};
type OpenApiPathItem = {
get?: OpenApiOperationObject;
post?: OpenApiOperationObject;
put?: OpenApiOperationObject;
delete?: OpenApiOperationObject;
patch?: OpenApiOperationObject;
parameters?: Array<OpenApiParameterObject | OpenApiRefObject>;
};
type OpenApiSpec = {
openapi: string;
info: {
title: string;
version: string;
description?: string;
};
servers?: Array<{
url: string;
description?: string;
}>;
paths: Record<string, OpenApiPathItem>;
components?: {
schemas?: Record<string, OpenApiSchemaObject>;
parameters?: Record<string, OpenApiParameterObject>;
requestBodies?: Record<string, OpenApiRequestBodyObject>;
};
};
type OpenApiToolsOptions = {
baseUrl?: string;
headers?: Record<string, string>;
1263 unmodified lines
--cases evals/smoke.jsonl \
--suite smoke-gepa \
--provider cerebras \
--model gpt-oss-120b \
--model zai-glm-4.7 \
--artifact .smithers/optimizations/smoke-gepa.json
```
26 unmodified lines
--cases evals/opt.jsonl \
--suite cerebras-proof \
--provider cerebras \
--model gpt-oss-120b \
--model zai-glm-4.7 \
--artifact artifacts/optimized.json \
--report-dir artifacts/reports \
--format json
7 unmodified lines
"optimized": { "score": 1, "passed": 1, "total": 1 },
"improved": true,
"provider": "cerebras",
"model": "gpt-oss-120b"
"model": "zai-glm-4.7"
}
```
3 unmodified lines
| Provider | Optimizer API | Required env | Default model |
| --- | --- | --- | --- |
| `cerebras` | OpenAI-compatible | `CEREBRAS_API_KEY` | `gpt-oss-120b` |
| `openai-api`, `openai`, `openai-sdk`, `codex` | OpenAI-compatible | `OPENAI_API_KEY` | `gpt-5.3-codex` |
| `anthropic-api`, `anthropic`, `anthropic-sdk`, `claude-code`, `claude` | Anthropic Messages API | `ANTHROPIC_API_KEY` | `claude-opus-4-7` |
| `cerebras` | OpenAI-compatible | `CEREBRAS_API_KEY` | `zai-glm-4.7` |
| `openai-api`, `openai`, `openai-sdk`, `codex` | OpenAI-compatible | `OPENAI_API_KEY` | `gpt-5.5` |
| `anthropic-api`, `anthropic`, `anthropic-sdk`, `claude-code`, `claude` | Anthropic Messages API | `ANTHROPIC_API_KEY` | `claude-fable-5` |
| `gemini-api`, `gemini`, `antigravity` | Gemini generateContent API | `GEMINI_API_KEY` or `GOOGLE_API_KEY` | `gemini-3.1-pro-preview` |
| `kimi`, `moonshot` | OpenAI-compatible Moonshot API | `MOONSHOT_API_KEY` | `kimi-latest` |
| `opencode` | OpenAI-compatible endpoint | `SMITHERS_OPTIMIZER_API_KEY` and `SMITHERS_OPTIMIZER_BASE_URL` | `anthropic/claude-sonnet-4-5` |
| `pi` | OpenAI-compatible endpoint | `SMITHERS_OPTIMIZER_API_KEY` and `SMITHERS_OPTIMIZER_BASE_URL` | `gpt-5.3-codex` |
| `kimi`, `moonshot` | OpenAI-compatible Moonshot API | `MOONSHOT_API_KEY` | `kimi-k2.6` |
| `opencode` | OpenAI-compatible endpoint | `SMITHERS_OPTIMIZER_API_KEY` and `SMITHERS_OPTIMIZER_BASE_URL` | `anthropic/claude-fable-5` |
| `pi` | OpenAI-compatible endpoint | `SMITHERS_OPTIMIZER_API_KEY` and `SMITHERS_OPTIMIZER_BASE_URL` | `gpt-5.5` |
| `amp`, `forge`, `openai-compatible` | OpenAI-compatible endpoint | `SMITHERS_OPTIMIZER_API_KEY` and `SMITHERS_OPTIMIZER_BASE_URL` | pass `--model` when needed |
The CLI provider names (`claude-code`, `codex`, `antigravity`, `gemini`, `kimi`) map to their hosted API equivalents for optimization because GEPA needs a direct model call to propose prompt patches. Providers with no single hosted backend (`opencode`, `pi`, `amp`, `forge`) are still accepted through a generic OpenAI-compatible endpoint.
156 unmodified lines
});
const agent = new ToolLoopAgent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools,
});
```
1888 unmodified lines
});
const opsAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools: { linearGetIssue },
});
```
65 unmodified lines
});
const claude = new ClaudeCodeAgent({
model: "claude-sonnet-4-20250514",
model: "claude-fable-5",
systemPrompt: "You are a careful code reviewer.",
timeoutMs: 30 * 60 * 1000,
});
38 unmodified lines
});
const codex = new CodexAgent({
model: "gpt-5.3-codex",
model: "gpt-5.5",
sandbox: "workspace-write",
skipGitRepoCheck: true,
yolo: true,
273 unmodified lines
```ts
const claude = new AnthropicAgent({
model: "claude-opus-4-7",
model: "claude-fable-5",
tools,
instructions: "You are a careful planner.",
stopWhen: stepCountIs(40),
});
const codex = new OpenAIAgent({
model: "gpt-5.3-codex",
model: "gpt-5.5",
tools,
instructions: "You are a precise implementation agent.",
stopWhen: stepCountIs(40),
9 unmodified lines
## Model Input
`AnthropicAgent` and `OpenAIAgent` accept a model ID string (`"claude-opus-4-7"`, `"gpt-5.3-codex"`) or a prebuilt provider model instance. `HermesAgent` accepts an optional model ID string and defaults it to `"hermes"`.
`AnthropicAgent` and `OpenAIAgent` accept a model ID string (`"claude-fable-5"`, `"gpt-5.5"`) or a prebuilt provider model instance. `HermesAgent` accepts an optional model ID string and defaults it to `"hermes"`.
## Options
101 unmodified lines
export const claude = useCli
? new ClaudeCodeAgent({
model: "claude-opus-4-7",
model: "claude-fable-5",
dangerouslySkipPermissions: true,
})
: new AnthropicAgent({
model: "claude-opus-4-7",
model: "claude-fable-5",
tools,
instructions: "You are a careful planner.",
stopWhen: stepCountIs(40),
36 unmodified lines
try {
const agent = new AnthropicAgent({
model: "claude-sonnet-4-20250514",
model: "claude-fable-5",
instructions: "Use the available tools when they are relevant.",
tools: mcp.tools,
});
242 unmodified lines
import { read, grep } from "smithers-orchestrator";
const codeAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools: { read, grep },
});
```
26 unmodified lines
import { write, read } from "smithers-orchestrator";
const writerAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools: { write, read },
});
```
84 unmodified lines
import { bash } from "smithers-orchestrator";
const devAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools: { bash },
});
```
18 unmodified lines
import { z } from "zod";
const codeAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools: { read, write, edit, grep, bash },
instructions: "You are a senior engineer. Use the available tools to complete tasks.",
});
19 unmodified lines
import { tools } from "smithers-orchestrator";
const fullAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools,
});
```
docs/llms-full.txtmodified+109 −29not agent-reviewed (unsupported_ext)

modified (+109 −29)

Diff (+109 −29)
687 unmodified lines
688
689
690
691
691
692
693
694
37 unmodified lines
732
733
734
735
735
736
737
738
739
740
740
741
742
743
1571 unmodified lines
2315
2316
2317
2318
2318
2319
2320
2321
67 unmodified lines
2389
2390
2391
2392
2392
2393
2394
2395
3874 unmodified lines
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
1263 unmodified lines
7619
7620
7621
7542
7622
7623
7624
7625
26 unmodified lines
7652
7653
7654
7575
7655
7656
7657
7658
7 unmodified lines
7666
7667
7668
7589
7669
7670
7671
7672
3 unmodified lines
7676
7677
7678
7599
7600
7601
7679
7680
7681
7682
7603
7604
7605
7683
7684
7685
7686
7687
7688
156 unmodified lines
7845
7846
7847
7768
7848
7849
7850
7851
1888 unmodified lines
9740
9741
9742
9663
9743
9744
9745
9746
65 unmodified lines
9812
9813
9814
9735
9815
9816
9817
9818
38 unmodified lines
9857
9858
9859
9780
9860
9861
9862
9863
273 unmodified lines
10137
10138
10139
10060
10140
10141
10142
10143
10144
10145
10146
10067
10147
10148
10149
10150
9 unmodified lines
10160
10161
10162
10083
10163
10164
10165
10166
101 unmodified lines
10268
10269
10270
10191
10271
10272
10273
10274
10195
10275
10276
10277
10278
36 unmodified lines
10315
10316
10317
10238
10318
10319
10320
10321
242 unmodified lines
10564
10565
10566
10487
10567
10568
10569
10570
26 unmodified lines
10597
10598
10599
10520
10600
10601
10602
10603
84 unmodified lines
10688
10689
10690
10611
10691
10692
10693
10694
18 unmodified lines
10713
10714
10715
10636
10716
10717
10718
10719
19 unmodified lines
10739
10740
10741
10662
10742
10743
10744
10745
687 unmodified lines
});
const analyst = new AnthropicAgent({
model: "claude-sonnet-4-20250514",
model: "claude-fable-5",
instructions: "You are a senior code reviewer. Return structured JSON.",
});
37 unmodified lines
});
const analyst = new AnthropicAgent({
model: "claude-sonnet-4-20250514",
model: "claude-fable-5",
instructions: "You are a senior code reviewer. Return structured JSON.",
});
const fixer = new AnthropicAgent({
model: "claude-sonnet-4-20250514",
model: "claude-fable-5",
instructions: "Write minimal, correct fixes as a unified diff.",
});
1571 unmodified lines
});
const researcher = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
instructions: "You are a research assistant.",
});
67 unmodified lines
import { anthropic } from "@ai-sdk/anthropic";
const codeAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
instructions: "You are a senior software engineer.",
});
3874 unmodified lines
| { type: "bearer"; token: string }
| { type: "basic"; username: string; password: string };
type OpenApiRefObject = {
$ref: string;
};
type OpenApiSchemaObject = {
type?: string;
format?: string;
description?: string;
properties?: Record<string, OpenApiSchemaObject | OpenApiRefObject>;
required?: string[];
items?: OpenApiSchemaObject | OpenApiRefObject;
enum?: unknown[];
default?: unknown;
nullable?: boolean;
oneOf?: Array<OpenApiSchemaObject | OpenApiRefObject>;
anyOf?: Array<OpenApiSchemaObject | OpenApiRefObject>;
allOf?: Array<OpenApiSchemaObject | OpenApiRefObject>;
additionalProperties?: boolean | OpenApiSchemaObject | OpenApiRefObject;
minimum?: number;
maximum?: number;
minLength?: number;
maxLength?: number;
pattern?: string;
$ref?: string;
};
type OpenApiParameterObject = {
name: string;
in: "query" | "header" | "path" | "cookie";
description?: string;
required?: boolean;
schema?: OpenApiSchemaObject | OpenApiRefObject;
deprecated?: boolean;
};
type OpenApiRequestBodyObject = {
description?: string;
required?: boolean;
content: Record<string, { schema?: OpenApiSchemaObject | OpenApiRefObject }>;
};
type OpenApiOperationObject = {
operationId?: string;
summary?: string;
description?: string;
parameters?: Array<OpenApiParameterObject | OpenApiRefObject>;
requestBody?: OpenApiRequestBodyObject | OpenApiRefObject;
responses?: Record<string, unknown>;
tags?: string[];
deprecated?: boolean;
};
type OpenApiPathItem = {
get?: OpenApiOperationObject;
post?: OpenApiOperationObject;
put?: OpenApiOperationObject;
delete?: OpenApiOperationObject;
patch?: OpenApiOperationObject;
parameters?: Array<OpenApiParameterObject | OpenApiRefObject>;
};
type OpenApiSpec = {
openapi: string;
info: {
title: string;
version: string;
description?: string;
};
servers?: Array<{
url: string;
description?: string;
}>;
paths: Record<string, OpenApiPathItem>;
components?: {
schemas?: Record<string, OpenApiSchemaObject>;
parameters?: Record<string, OpenApiParameterObject>;
requestBodies?: Record<string, OpenApiRequestBodyObject>;
};
};
type OpenApiToolsOptions = {
baseUrl?: string;
headers?: Record<string, string>;
1263 unmodified lines
--cases evals/smoke.jsonl \
--suite smoke-gepa \
--provider cerebras \
--model gpt-oss-120b \
--model zai-glm-4.7 \
--artifact .smithers/optimizations/smoke-gepa.json
```
26 unmodified lines
--cases evals/opt.jsonl \
--suite cerebras-proof \
--provider cerebras \
--model gpt-oss-120b \
--model zai-glm-4.7 \
--artifact artifacts/optimized.json \
--report-dir artifacts/reports \
--format json
7 unmodified lines
"optimized": { "score": 1, "passed": 1, "total": 1 },
"improved": true,
"provider": "cerebras",
"model": "gpt-oss-120b"
"model": "zai-glm-4.7"
}
```
3 unmodified lines
| Provider | Optimizer API | Required env | Default model |
| --- | --- | --- | --- |
| `cerebras` | OpenAI-compatible | `CEREBRAS_API_KEY` | `gpt-oss-120b` |
| `openai-api`, `openai`, `openai-sdk`, `codex` | OpenAI-compatible | `OPENAI_API_KEY` | `gpt-5.3-codex` |
| `anthropic-api`, `anthropic`, `anthropic-sdk`, `claude-code`, `claude` | Anthropic Messages API | `ANTHROPIC_API_KEY` | `claude-opus-4-7` |
| `cerebras` | OpenAI-compatible | `CEREBRAS_API_KEY` | `zai-glm-4.7` |
| `openai-api`, `openai`, `openai-sdk`, `codex` | OpenAI-compatible | `OPENAI_API_KEY` | `gpt-5.5` |
| `anthropic-api`, `anthropic`, `anthropic-sdk`, `claude-code`, `claude` | Anthropic Messages API | `ANTHROPIC_API_KEY` | `claude-fable-5` |
| `gemini-api`, `gemini`, `antigravity` | Gemini generateContent API | `GEMINI_API_KEY` or `GOOGLE_API_KEY` | `gemini-3.1-pro-preview` |
| `kimi`, `moonshot` | OpenAI-compatible Moonshot API | `MOONSHOT_API_KEY` | `kimi-latest` |
| `opencode` | OpenAI-compatible endpoint | `SMITHERS_OPTIMIZER_API_KEY` and `SMITHERS_OPTIMIZER_BASE_URL` | `anthropic/claude-sonnet-4-5` |
| `pi` | OpenAI-compatible endpoint | `SMITHERS_OPTIMIZER_API_KEY` and `SMITHERS_OPTIMIZER_BASE_URL` | `gpt-5.3-codex` |
| `kimi`, `moonshot` | OpenAI-compatible Moonshot API | `MOONSHOT_API_KEY` | `kimi-k2.6` |
| `opencode` | OpenAI-compatible endpoint | `SMITHERS_OPTIMIZER_API_KEY` and `SMITHERS_OPTIMIZER_BASE_URL` | `anthropic/claude-fable-5` |
| `pi` | OpenAI-compatible endpoint | `SMITHERS_OPTIMIZER_API_KEY` and `SMITHERS_OPTIMIZER_BASE_URL` | `gpt-5.5` |
| `amp`, `forge`, `openai-compatible` | OpenAI-compatible endpoint | `SMITHERS_OPTIMIZER_API_KEY` and `SMITHERS_OPTIMIZER_BASE_URL` | pass `--model` when needed |
The CLI provider names (`claude-code`, `codex`, `antigravity`, `gemini`, `kimi`) map to their hosted API equivalents for optimization because GEPA needs a direct model call to propose prompt patches. Providers with no single hosted backend (`opencode`, `pi`, `amp`, `forge`) are still accepted through a generic OpenAI-compatible endpoint.
156 unmodified lines
});
const agent = new ToolLoopAgent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools,
});
```
1888 unmodified lines
});
const opsAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools: { linearGetIssue },
});
```
65 unmodified lines
});
const claude = new ClaudeCodeAgent({
model: "claude-sonnet-4-20250514",
model: "claude-fable-5",
systemPrompt: "You are a careful code reviewer.",
timeoutMs: 30 * 60 * 1000,
});
38 unmodified lines
});
const codex = new CodexAgent({
model: "gpt-5.3-codex",
model: "gpt-5.5",
sandbox: "workspace-write",
skipGitRepoCheck: true,
yolo: true,
273 unmodified lines
```ts
const claude = new AnthropicAgent({
model: "claude-opus-4-7",
model: "claude-fable-5",
tools,
instructions: "You are a careful planner.",
stopWhen: stepCountIs(40),
});
const codex = new OpenAIAgent({
model: "gpt-5.3-codex",
model: "gpt-5.5",
tools,
instructions: "You are a precise implementation agent.",
stopWhen: stepCountIs(40),
9 unmodified lines
## Model Input
`AnthropicAgent` and `OpenAIAgent` accept a model ID string (`"claude-opus-4-7"`, `"gpt-5.3-codex"`) or a prebuilt provider model instance. `HermesAgent` accepts an optional model ID string and defaults it to `"hermes"`.
`AnthropicAgent` and `OpenAIAgent` accept a model ID string (`"claude-fable-5"`, `"gpt-5.5"`) or a prebuilt provider model instance. `HermesAgent` accepts an optional model ID string and defaults it to `"hermes"`.
## Options
101 unmodified lines
export const claude = useCli
? new ClaudeCodeAgent({
model: "claude-opus-4-7",
model: "claude-fable-5",
dangerouslySkipPermissions: true,
})
: new AnthropicAgent({
model: "claude-opus-4-7",
model: "claude-fable-5",
tools,
instructions: "You are a careful planner.",
stopWhen: stepCountIs(40),
36 unmodified lines
try {
const agent = new AnthropicAgent({
model: "claude-sonnet-4-20250514",
model: "claude-fable-5",
instructions: "Use the available tools when they are relevant.",
tools: mcp.tools,
});
242 unmodified lines
import { read, grep } from "smithers-orchestrator";
const codeAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools: { read, grep },
});
```
26 unmodified lines
import { write, read } from "smithers-orchestrator";
const writerAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools: { write, read },
});
```
84 unmodified lines
import { bash } from "smithers-orchestrator";
const devAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools: { bash },
});
```
18 unmodified lines
import { z } from "zod";
const codeAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools: { read, write, edit, grep, bash },
instructions: "You are a senior engineer. Use the available tools to complete tasks.",
});
19 unmodified lines
import { tools } from "smithers-orchestrator";
const fullAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools,
});
```
skills/smithers/llms-full.txtmodified+109 −29not agent-reviewed (unsupported_ext)

modified (+109 −29)

Diff (+109 −29)
687 unmodified lines
688
689
690
691
691
692
693
694
37 unmodified lines
732
733
734
735
735
736
737
738
739
740
740
741
742
743
1571 unmodified lines
2315
2316
2317
2318
2318
2319
2320
2321
67 unmodified lines
2389
2390
2391
2392
2392
2393
2394
2395
3874 unmodified lines
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
1263 unmodified lines
7619
7620
7621
7542
7622
7623
7624
7625
26 unmodified lines
7652
7653
7654
7575
7655
7656
7657
7658
7 unmodified lines
7666
7667
7668
7589
7669
7670
7671
7672
3 unmodified lines
7676
7677
7678
7599
7600
7601
7679
7680
7681
7682
7603
7604
7605
7683
7684
7685
7686
7687
7688
156 unmodified lines
7845
7846
7847
7768
7848
7849
7850
7851
1888 unmodified lines
9740
9741
9742
9663
9743
9744
9745
9746
65 unmodified lines
9812
9813
9814
9735
9815
9816
9817
9818
38 unmodified lines
9857
9858
9859
9780
9860
9861
9862
9863
273 unmodified lines
10137
10138
10139
10060
10140
10141
10142
10143
10144
10145
10146
10067
10147
10148
10149
10150
9 unmodified lines
10160
10161
10162
10083
10163
10164
10165
10166
101 unmodified lines
10268
10269
10270
10191
10271
10272
10273
10274
10195
10275
10276
10277
10278
36 unmodified lines
10315
10316
10317
10238
10318
10319
10320
10321
242 unmodified lines
10564
10565
10566
10487
10567
10568
10569
10570
26 unmodified lines
10597
10598
10599
10520
10600
10601
10602
10603
84 unmodified lines
10688
10689
10690
10611
10691
10692
10693
10694
18 unmodified lines
10713
10714
10715
10636
10716
10717
10718
10719
19 unmodified lines
10739
10740
10741
10662
10742
10743
10744
10745
687 unmodified lines
});
const analyst = new AnthropicAgent({
model: "claude-sonnet-4-20250514",
model: "claude-fable-5",
instructions: "You are a senior code reviewer. Return structured JSON.",
});
37 unmodified lines
});
const analyst = new AnthropicAgent({
model: "claude-sonnet-4-20250514",
model: "claude-fable-5",
instructions: "You are a senior code reviewer. Return structured JSON.",
});
const fixer = new AnthropicAgent({
model: "claude-sonnet-4-20250514",
model: "claude-fable-5",
instructions: "Write minimal, correct fixes as a unified diff.",
});
1571 unmodified lines
});
const researcher = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
instructions: "You are a research assistant.",
});
67 unmodified lines
import { anthropic } from "@ai-sdk/anthropic";
const codeAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
instructions: "You are a senior software engineer.",
});
3874 unmodified lines
| { type: "bearer"; token: string }
| { type: "basic"; username: string; password: string };
type OpenApiRefObject = {
$ref: string;
};
type OpenApiSchemaObject = {
type?: string;
format?: string;
description?: string;
properties?: Record<string, OpenApiSchemaObject | OpenApiRefObject>;
required?: string[];
items?: OpenApiSchemaObject | OpenApiRefObject;
enum?: unknown[];
default?: unknown;
nullable?: boolean;
oneOf?: Array<OpenApiSchemaObject | OpenApiRefObject>;
anyOf?: Array<OpenApiSchemaObject | OpenApiRefObject>;
allOf?: Array<OpenApiSchemaObject | OpenApiRefObject>;
additionalProperties?: boolean | OpenApiSchemaObject | OpenApiRefObject;
minimum?: number;
maximum?: number;
minLength?: number;
maxLength?: number;
pattern?: string;
$ref?: string;
};
type OpenApiParameterObject = {
name: string;
in: "query" | "header" | "path" | "cookie";
description?: string;
required?: boolean;
schema?: OpenApiSchemaObject | OpenApiRefObject;
deprecated?: boolean;
};
type OpenApiRequestBodyObject = {
description?: string;
required?: boolean;
content: Record<string, { schema?: OpenApiSchemaObject | OpenApiRefObject }>;
};
type OpenApiOperationObject = {
operationId?: string;
summary?: string;
description?: string;
parameters?: Array<OpenApiParameterObject | OpenApiRefObject>;
requestBody?: OpenApiRequestBodyObject | OpenApiRefObject;
responses?: Record<string, unknown>;
tags?: string[];
deprecated?: boolean;
};
type OpenApiPathItem = {
get?: OpenApiOperationObject;
post?: OpenApiOperationObject;
put?: OpenApiOperationObject;
delete?: OpenApiOperationObject;
patch?: OpenApiOperationObject;
parameters?: Array<OpenApiParameterObject | OpenApiRefObject>;
};
type OpenApiSpec = {
openapi: string;
info: {
title: string;
version: string;
description?: string;
};
servers?: Array<{
url: string;
description?: string;
}>;
paths: Record<string, OpenApiPathItem>;
components?: {
schemas?: Record<string, OpenApiSchemaObject>;
parameters?: Record<string, OpenApiParameterObject>;
requestBodies?: Record<string, OpenApiRequestBodyObject>;
};
};
type OpenApiToolsOptions = {
baseUrl?: string;
headers?: Record<string, string>;
1263 unmodified lines
--cases evals/smoke.jsonl \
--suite smoke-gepa \
--provider cerebras \
--model gpt-oss-120b \
--model zai-glm-4.7 \
--artifact .smithers/optimizations/smoke-gepa.json
```
26 unmodified lines
--cases evals/opt.jsonl \
--suite cerebras-proof \
--provider cerebras \
--model gpt-oss-120b \
--model zai-glm-4.7 \
--artifact artifacts/optimized.json \
--report-dir artifacts/reports \
--format json
7 unmodified lines
"optimized": { "score": 1, "passed": 1, "total": 1 },
"improved": true,
"provider": "cerebras",
"model": "gpt-oss-120b"
"model": "zai-glm-4.7"
}
```
3 unmodified lines
| Provider | Optimizer API | Required env | Default model |
| --- | --- | --- | --- |
| `cerebras` | OpenAI-compatible | `CEREBRAS_API_KEY` | `gpt-oss-120b` |
| `openai-api`, `openai`, `openai-sdk`, `codex` | OpenAI-compatible | `OPENAI_API_KEY` | `gpt-5.3-codex` |
| `anthropic-api`, `anthropic`, `anthropic-sdk`, `claude-code`, `claude` | Anthropic Messages API | `ANTHROPIC_API_KEY` | `claude-opus-4-7` |
| `cerebras` | OpenAI-compatible | `CEREBRAS_API_KEY` | `zai-glm-4.7` |
| `openai-api`, `openai`, `openai-sdk`, `codex` | OpenAI-compatible | `OPENAI_API_KEY` | `gpt-5.5` |
| `anthropic-api`, `anthropic`, `anthropic-sdk`, `claude-code`, `claude` | Anthropic Messages API | `ANTHROPIC_API_KEY` | `claude-fable-5` |
| `gemini-api`, `gemini`, `antigravity` | Gemini generateContent API | `GEMINI_API_KEY` or `GOOGLE_API_KEY` | `gemini-3.1-pro-preview` |
| `kimi`, `moonshot` | OpenAI-compatible Moonshot API | `MOONSHOT_API_KEY` | `kimi-latest` |
| `opencode` | OpenAI-compatible endpoint | `SMITHERS_OPTIMIZER_API_KEY` and `SMITHERS_OPTIMIZER_BASE_URL` | `anthropic/claude-sonnet-4-5` |
| `pi` | OpenAI-compatible endpoint | `SMITHERS_OPTIMIZER_API_KEY` and `SMITHERS_OPTIMIZER_BASE_URL` | `gpt-5.3-codex` |
| `kimi`, `moonshot` | OpenAI-compatible Moonshot API | `MOONSHOT_API_KEY` | `kimi-k2.6` |
| `opencode` | OpenAI-compatible endpoint | `SMITHERS_OPTIMIZER_API_KEY` and `SMITHERS_OPTIMIZER_BASE_URL` | `anthropic/claude-fable-5` |
| `pi` | OpenAI-compatible endpoint | `SMITHERS_OPTIMIZER_API_KEY` and `SMITHERS_OPTIMIZER_BASE_URL` | `gpt-5.5` |
| `amp`, `forge`, `openai-compatible` | OpenAI-compatible endpoint | `SMITHERS_OPTIMIZER_API_KEY` and `SMITHERS_OPTIMIZER_BASE_URL` | pass `--model` when needed |
The CLI provider names (`claude-code`, `codex`, `antigravity`, `gemini`, `kimi`) map to their hosted API equivalents for optimization because GEPA needs a direct model call to propose prompt patches. Providers with no single hosted backend (`opencode`, `pi`, `amp`, `forge`) are still accepted through a generic OpenAI-compatible endpoint.
156 unmodified lines
});
const agent = new ToolLoopAgent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools,
});
```
1888 unmodified lines
});
const opsAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools: { linearGetIssue },
});
```
65 unmodified lines
});
const claude = new ClaudeCodeAgent({
model: "claude-sonnet-4-20250514",
model: "claude-fable-5",
systemPrompt: "You are a careful code reviewer.",
timeoutMs: 30 * 60 * 1000,
});
38 unmodified lines
});
const codex = new CodexAgent({
model: "gpt-5.3-codex",
model: "gpt-5.5",
sandbox: "workspace-write",
skipGitRepoCheck: true,
yolo: true,
273 unmodified lines
```ts
const claude = new AnthropicAgent({
model: "claude-opus-4-7",
model: "claude-fable-5",
tools,
instructions: "You are a careful planner.",
stopWhen: stepCountIs(40),
});
const codex = new OpenAIAgent({
model: "gpt-5.3-codex",
model: "gpt-5.5",
tools,
instructions: "You are a precise implementation agent.",
stopWhen: stepCountIs(40),
9 unmodified lines
## Model Input
`AnthropicAgent` and `OpenAIAgent` accept a model ID string (`"claude-opus-4-7"`, `"gpt-5.3-codex"`) or a prebuilt provider model instance. `HermesAgent` accepts an optional model ID string and defaults it to `"hermes"`.
`AnthropicAgent` and `OpenAIAgent` accept a model ID string (`"claude-fable-5"`, `"gpt-5.5"`) or a prebuilt provider model instance. `HermesAgent` accepts an optional model ID string and defaults it to `"hermes"`.
## Options
101 unmodified lines
export const claude = useCli
? new ClaudeCodeAgent({
model: "claude-opus-4-7",
model: "claude-fable-5",
dangerouslySkipPermissions: true,
})
: new AnthropicAgent({
model: "claude-opus-4-7",
model: "claude-fable-5",
tools,
instructions: "You are a careful planner.",
stopWhen: stepCountIs(40),
36 unmodified lines
try {
const agent = new AnthropicAgent({
model: "claude-sonnet-4-20250514",
model: "claude-fable-5",
instructions: "Use the available tools when they are relevant.",
tools: mcp.tools,
});
242 unmodified lines
import { read, grep } from "smithers-orchestrator";
const codeAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools: { read, grep },
});
```
26 unmodified lines
import { write, read } from "smithers-orchestrator";
const writerAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools: { write, read },
});
```
84 unmodified lines
import { bash } from "smithers-orchestrator";
const devAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools: { bash },
});
```
18 unmodified lines
import { z } from "zod";
const codeAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools: { read, write, edit, grep, bash },
instructions: "You are a senior engineer. Use the available tools to complete tasks.",
});
19 unmodified lines
import { tools } from "smithers-orchestrator";
const fullAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools,
});
```
docs/llms-core.txtmodified+94 −14not agent-reviewed (unsupported_ext)

modified (+94 −14)

Diff (+94 −14)
666 unmodified lines
667
668
669
670
670
671
672
673
38 unmodified lines
712
713
714
715
715
716
717
718
719
720
720
721
722
723
1571 unmodified lines
2295
2296
2297
2298
2298
2299
2300
2301
67 unmodified lines
2369
2370
2371
2372
2372
2373
2374
2375
3874 unmodified lines
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
1268 unmodified lines
7604
7605
7606
7527
7607
7608
7609
7610
26 unmodified lines
7637
7638
7639
7560
7640
7641
7642
7643
7 unmodified lines
7651
7652
7653
7574
7654
7655
7656
7657
3 unmodified lines
7661
7662
7663
7584
7585
7586
7664
7665
7666
7667
7588
7589
7590
7668
7669
7670
7671
7672
7673
666 unmodified lines
});
const analyst = new AnthropicAgent({
model: "claude-sonnet-4-20250514",
model: "claude-fable-5",
instructions: "You are a senior code reviewer. Return structured JSON.",
});
38 unmodified lines
});
const analyst = new AnthropicAgent({
model: "claude-sonnet-4-20250514",
model: "claude-fable-5",
instructions: "You are a senior code reviewer. Return structured JSON.",
});
const fixer = new AnthropicAgent({
model: "claude-sonnet-4-20250514",
model: "claude-fable-5",
instructions: "Write minimal, correct fixes as a unified diff.",
});
1571 unmodified lines
});
const researcher = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
instructions: "You are a research assistant.",
});
67 unmodified lines
import { anthropic } from "@ai-sdk/anthropic";
const codeAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
instructions: "You are a senior software engineer.",
});
3874 unmodified lines
| { type: "bearer"; token: string }
| { type: "basic"; username: string; password: string };
type OpenApiRefObject = {
$ref: string;
};
type OpenApiSchemaObject = {
type?: string;
format?: string;
description?: string;
properties?: Record<string, OpenApiSchemaObject | OpenApiRefObject>;
required?: string[];
items?: OpenApiSchemaObject | OpenApiRefObject;
enum?: unknown[];
default?: unknown;
nullable?: boolean;
oneOf?: Array<OpenApiSchemaObject | OpenApiRefObject>;
anyOf?: Array<OpenApiSchemaObject | OpenApiRefObject>;
allOf?: Array<OpenApiSchemaObject | OpenApiRefObject>;
additionalProperties?: boolean | OpenApiSchemaObject | OpenApiRefObject;
minimum?: number;
maximum?: number;
minLength?: number;
maxLength?: number;
pattern?: string;
$ref?: string;
};
type OpenApiParameterObject = {
name: string;
in: "query" | "header" | "path" | "cookie";
description?: string;
required?: boolean;
schema?: OpenApiSchemaObject | OpenApiRefObject;
deprecated?: boolean;
};
type OpenApiRequestBodyObject = {
description?: string;
required?: boolean;
content: Record<string, { schema?: OpenApiSchemaObject | OpenApiRefObject }>;
};
type OpenApiOperationObject = {
operationId?: string;
summary?: string;
description?: string;
parameters?: Array<OpenApiParameterObject | OpenApiRefObject>;
requestBody?: OpenApiRequestBodyObject | OpenApiRefObject;
responses?: Record<string, unknown>;
tags?: string[];
deprecated?: boolean;
};
type OpenApiPathItem = {
get?: OpenApiOperationObject;
post?: OpenApiOperationObject;
put?: OpenApiOperationObject;
delete?: OpenApiOperationObject;
patch?: OpenApiOperationObject;
parameters?: Array<OpenApiParameterObject | OpenApiRefObject>;
};
type OpenApiSpec = {
openapi: string;
info: {
title: string;
version: string;
description?: string;
};
servers?: Array<{
url: string;
description?: string;
}>;
paths: Record<string, OpenApiPathItem>;
components?: {
schemas?: Record<string, OpenApiSchemaObject>;
parameters?: Record<string, OpenApiParameterObject>;
requestBodies?: Record<string, OpenApiRequestBodyObject>;
};
};
type OpenApiToolsOptions = {
baseUrl?: string;
headers?: Record<string, string>;
1268 unmodified lines
--cases evals/smoke.jsonl \
--suite smoke-gepa \
--provider cerebras \
--model gpt-oss-120b \
--model zai-glm-4.7 \
--artifact .smithers/optimizations/smoke-gepa.json
```
26 unmodified lines
--cases evals/opt.jsonl \
--suite cerebras-proof \
--provider cerebras \
--model gpt-oss-120b \
--model zai-glm-4.7 \
--artifact artifacts/optimized.json \
--report-dir artifacts/reports \
--format json
7 unmodified lines
"optimized": { "score": 1, "passed": 1, "total": 1 },
"improved": true,
"provider": "cerebras",
"model": "gpt-oss-120b"
"model": "zai-glm-4.7"
}
```
3 unmodified lines
| Provider | Optimizer API | Required env | Default model |
| --- | --- | --- | --- |
| `cerebras` | OpenAI-compatible | `CEREBRAS_API_KEY` | `gpt-oss-120b` |
| `openai-api`, `openai`, `openai-sdk`, `codex` | OpenAI-compatible | `OPENAI_API_KEY` | `gpt-5.3-codex` |
| `anthropic-api`, `anthropic`, `anthropic-sdk`, `claude-code`, `claude` | Anthropic Messages API | `ANTHROPIC_API_KEY` | `claude-opus-4-7` |
| `cerebras` | OpenAI-compatible | `CEREBRAS_API_KEY` | `zai-glm-4.7` |
| `openai-api`, `openai`, `openai-sdk`, `codex` | OpenAI-compatible | `OPENAI_API_KEY` | `gpt-5.5` |
| `anthropic-api`, `anthropic`, `anthropic-sdk`, `claude-code`, `claude` | Anthropic Messages API | `ANTHROPIC_API_KEY` | `claude-fable-5` |
| `gemini-api`, `gemini`, `antigravity` | Gemini generateContent API | `GEMINI_API_KEY` or `GOOGLE_API_KEY` | `gemini-3.1-pro-preview` |
| `kimi`, `moonshot` | OpenAI-compatible Moonshot API | `MOONSHOT_API_KEY` | `kimi-latest` |
| `opencode` | OpenAI-compatible endpoint | `SMITHERS_OPTIMIZER_API_KEY` and `SMITHERS_OPTIMIZER_BASE_URL` | `anthropic/claude-sonnet-4-5` |
| `pi` | OpenAI-compatible endpoint | `SMITHERS_OPTIMIZER_API_KEY` and `SMITHERS_OPTIMIZER_BASE_URL` | `gpt-5.3-codex` |
| `kimi`, `moonshot` | OpenAI-compatible Moonshot API | `MOONSHOT_API_KEY` | `kimi-k2.6` |
| `opencode` | OpenAI-compatible endpoint | `SMITHERS_OPTIMIZER_API_KEY` and `SMITHERS_OPTIMIZER_BASE_URL` | `anthropic/claude-fable-5` |
| `pi` | OpenAI-compatible endpoint | `SMITHERS_OPTIMIZER_API_KEY` and `SMITHERS_OPTIMIZER_BASE_URL` | `gpt-5.5` |
| `amp`, `forge`, `openai-compatible` | OpenAI-compatible endpoint | `SMITHERS_OPTIMIZER_API_KEY` and `SMITHERS_OPTIMIZER_BASE_URL` | pass `--model` when needed |
The CLI provider names (`claude-code`, `codex`, `antigravity`, `gemini`, `kimi`) map to their hosted API equivalents for optimization because GEPA needs a direct model call to propose prompt patches. Providers with no single hosted backend (`opencode`, `pi`, `amp`, `forge`) are still accepted through a generic OpenAI-compatible endpoint.
.smithers/specs/smithers-review-walkthrough.mdmodified+33 −1not agent-reviewed (unsupported_ext)

modified (+33 −1)

Diff (+33 −1)
156 unmodified lines
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
162
192
193
194
195
196
156 unmodified lines
- Agent-driven runs are exercised manually (`smithers review` on this repo); they need
ClaudeCode credentials.
## Publishing (review.smithers.sh)
Walkthroughs are static HTML, so "deploying" smithers review means giving the
artifacts a home. A Cloudflare Worker (deployed with Alchemy IaC from
`apps/review/alchemy.run.ts`) serves published walkthroughs at
`https://review.smithers.sh`:
- `POST /api/walkthroughs` with `Authorization: Bearer <token>` and an HTML
body stores the walkthrough in R2 under a random id and returns
`{ id, url }`. The token is the `REVIEW_PUBLISH_TOKEN` Worker secret.
- `GET /w/<id>` serves the stored walkthrough.
- `GET /` is a usage landing page.
CLI: `--publish` uploads the generated walkthrough and prints the share URL.
The endpoint and token come from `SMITHERS_REVIEW_PUBLISH_URL` /
`SMITHERS_REVIEW_PUBLISH_TOKEN`, falling back to `~/.smithers-review.json`
(`{ "publishUrl": ..., "publishToken": ... }`).
Domain wiring: the `smithers.sh` zone lives on Vercel DNS (the registrar is
Name.com), not Cloudflare, so the Worker cannot take a plain custom domain.
Instead the hostname rides Cloudflare for SaaS on the `jjhub.tech` zone: a
custom hostname `review.smithers.sh` with HTTP cert validation, a proxied
fallback-origin record in jjhub.tech, a Worker route
`review.smithers.sh/*` on that zone, and a CNAME at Vercel DNS pointing
`review.smithers.sh` at the fallback origin. The Worker also keeps its
workers.dev URL as a domain-independent fallback.
Agents still run locally; the service stores and serves artifacts only. It
never sees repo contents beyond the HTML you choose to publish.
## Non-goals (for now)
- No GitHub App, webhooks, or PR comment posting. Output is local HTML.
- No GitHub App, webhooks, or PR comment posting. Output is local HTML
(optionally published).
- No incremental re-review state. Each run is a fresh review of the target.
- No chat replies on findings.
- No walkthrough listing/index endpoint; URLs are unlisted capability links.
.smithers/tickets/real-stack-e2e/t1-real-stack-boot.mdadded+31 −0not agent-reviewed (unsupported_ext)

added (+31 −0)

Diff (+31 −0)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# t1-real-stack-boot — Real stack boots: plue compose + cwd gateway + real playwright config
Build the no-mock stack skeleton. Deliverables:
1. `scripts/e2e-real/plue-up.sh`:
- default action (no arg): `docker compose up -d postgres migrate seed repo-host api` in $PLUE_DIR (default ../plue), wait for http://127.0.0.1:4000/api/health (up to 180s — migrations dominate cold boot), then `exec sleep infinity` so a playwright webServer can own the process. Plue keeps running when playwright kills the sleeper; reuseExistingServer makes the next run skip the boot.
- `down` / `status` args for humans: act and exit (down = compose down in $PLUE_DIR).
- Distinct non-zero exit code per failed leg. Idempotent: compose up on a running stack is a no-op.
2. `apps/smithers/playwright.real.config.ts`:
- testDir tests/e2e-real, workers: 1 (shared gateway DB + shared plue state), webServer entries:
(a) plue: command `bash ../../scripts/e2e-real/plue-up.sh`, url http://127.0.0.1:4000/api/health, reuseExistingServer: true, timeout 240s.
(b) gateway in the cwd: command `bun ../../.smithers/gateway.ts`, env { PORT: "7342", HOST: "127.0.0.1" }, url http://127.0.0.1:7342/health, reuseExistingServer: true. (gateway.ts chdir's itself to the repo root, so the command cwd does not matter.) Inject the values read from apps/smithers/.env.e2e.local (plain fs read in the config, tolerate absence) into this leg's env so agent credentials reach the claude CLI processes the gateway spawns.
(c) vite on 127.0.0.1:5375 with SMITHERS_AUTH_PROXY_TARGET + SMITHERS_PLATFORM_PROXY_TARGET = http://127.0.0.1:4000 and SMITHERS_GATEWAY_PROXY_TARGET = http://127.0.0.1:7342. No fixture processes anywhere in this config.
- Seed onboarding-completed localStorage for the app origin like the fixture config does (that is app state, not a mock).
3. `apps/smithers/tests/e2e-real/stack.spec.ts`:
- request GET /health on the app origin -> JSON {ok:true} (proves vite -> cwd gateway proxy);
- request GET /workflows on the app origin -> JSON listing at least one workflow (proves the gateway mounted the local pack);
- request GET /api/user anonymously -> 401 with a JSON body (proves vite -> REAL plue api, not the SPA fallback);
- page loads / and the app shell renders.
Success criteria:
- The verify command exits 0 from a cold start (plue down, no gateway on 7342).
- Running it again with everything already up is also green and faster (reuse).
- No file under tests/e2e-real or the real config imports from tests/fixtures.
Study apps/smithers/vite.config.ts for the exact proxy env var names, scripts/dev-with-plue.sh for the plue boot/health contract and the gateway reuse/refuse-to-clobber rules, and apps/smithers/playwright.config.ts ONLY for the storageState pattern.
## Verify command (must exit 0)
```bash
pnpm -C apps/smithers exec playwright test --config playwright.real.config.ts tests/e2e-real/stack.spec.ts
```
benchmarks/claw-eval-live/README.mdmodified+14 −14not agent-reviewed (unsupported_ext)

modified (+14 −14)

Diff (+14 −14)
1 unmodified line
2
3
4
5
5
6
7
8
25 unmodified lines
34
35
36
37
37
38
39
40
6 unmodified lines
47
48
49
50
50
51
52
53
52
53
54
55
55
56
57
58
59
60
59
60
61
62
63
2 unmodified lines
66
67
68
69
69
70
71
72
73
72
73
74
75
76
17 unmodified lines
94
95
96
97
97
98
99
100
20 unmodified lines
121
122
123
124
124
125
126
127
24 unmodified lines
152
153
154
155
155
156
157
158
1 unmodified line
Run the [Claw-Eval-Live](https://github.com/Claw-Eval-Live/Claw-Eval-Live) agent
benchmark ([arXiv:2604.28139](https://arxiv.org/abs/2604.28139)) with **Smithers
orchestrating a mixture of Claude Opus 4.8 + GPT5.5 ("Codex 5.5")** as the agent.
orchestrating a mixture of Claude Fable + GPT-5.5** as the agent.
Claw-Eval-Live evaluates agents on 105 real enterprise workflows across 17
families — they interact with controlled mock services, edit workspace files,
25 unmodified lines
│ • JSONL trace │ ◀───────────────────────────── │ decideTurn(): │
│ • grader.py + Gemini │ assistant turn (tool_calls │ GATHER → gpt-5.5 (native │
│ judge (UNCHANGED) │ or final text) │ tool calls, passthrough) │
└────────────────────────┘ │ SYNTHESIS → Opus 4.8 writes
└────────────────────────┘ │ SYNTHESIS → Fable writes
│ the final deliverable from │
│ the gathered context │
└──────────────────────────────┘
6 unmodified lines
through, so the benchmark executes the mock-service / sandbox tools exactly as
it would for a raw model.
- **Synthesis.** The moment `gpt-5.5` is ready to answer (returns no tool calls),
**Claude Opus 4.8** (via Smithers `ClaudeCodeAgent`, subscription auth) — the
**Claude Fable** (via Smithers `ClaudeCodeAgent`, subscription auth) — the
stronger synthesizer — composes the final deliverable from the gathered
context. This is the role-split "mixture of Opus 4.8 + Codex 5.5" (gpt-5.5
gathers, Opus 4.8 synthesizes), and it lands Opus on the turn the graders
context. This is the role-split "mixture of Fable + GPT-5.5" (gpt-5.5
gathers, Fable synthesizes), and it lands Fable on the turn the graders
actually measure (the benchmark loop ends, and final text is the dominant
scored signal for most families). If Opus is unavailable, the turn falls back
scored signal for most families). If Fable is unavailable, the turn falls back
to gpt-5.5's own final answer.
This split plays to each model's strengths (gpt-5.5's fast native function
calling for tool loops; Opus 4.8's synthesis quality on the graded deliverable)
while keeping Opus cost/latency bounded (≈ one Opus call per task, not per turn).
calling for tool loops; Fable's synthesis quality on the graded deliverable)
while keeping Fable cost/latency bounded (≈ one Fable call per task, not per turn).
The brain contains **no** LLM judge of its own — the only LLM-as-judge anywhere
in the pipeline is the benchmark's own (neutral) grader judge.
2 unmodified lines
| Role | Model | Auth |
|---|---|---|
| Multi-turn tool gathering | `gpt-5.5` | `OPENAI_API_KEY` |
| Final synthesis (the graded turn) | Claude Opus 4.8 (`opus``claude-opus-4-8`) | `claude` CLI subscription |
| Final synthesis (the graded turn) | Claude Fable (`claude-fable-5`) | `claude` CLI subscription |
| Benchmark judge (semantic grading) | `gemini-2.5-flash-lite` (neutral, not a contestant) | `GEMINI_API_KEY` |
> "Codex 5.5" → `gpt-5.5`: there is no `gpt-5.5-codex` model (the latest
> codex-tuned id is `gpt-5.3-codex`); `gpt-5.5` is the flagship 5.5.
> "Codex 5.5" → `gpt-5.5`: there is no `gpt-5.5-codex` model in the listings
> checked here; `gpt-5.5` is the flagship 5.5.
---
17 unmodified lines
synthesis path for all 105 tasks. There is no task-id branching, no
hardcoded outputs, no keyword stuffing.
4. **Neutral judge; the brain has no judge of its own.** The brain just routes
work between the two contestants (gpt-5.5 gathers, Opus 4.8 synthesizes) — it
work between the two contestants (gpt-5.5 gathers, Fable synthesizes) — it
contains no LLM-as-judge, so there is nothing for a contestant to self-grade.
The only LLM judge anywhere is the **benchmark's own** semantic grader, which
we point at **Gemini** (`gemini-2.5-flash-lite`) — neither contestant. (Per the
20 unmodified lines
## Run it
Prereqs: `uv`, `bun`, Docker (for the 5 `CTB_W*` tasks), an authenticated
`claude` CLI (Opus 4.8 subscription), and:
`claude` CLI (Fable subscription access), and:
```bash
export OPENAI_API_KEY=sk-... # gpt-5.5
24 unmodified lines
| File | Purpose |
|---|---|
| `gateway/src/server.ts` | OpenAI-compatible HTTP server (`/v1/chat/completions`, `/v1/models`, `/health`) |
| `gateway/src/mixture.ts` | The mixture brain: gather (gpt-5.5) → synthesis (Opus 4.8 + gpt-5.5 + Gemini arbiter) |
| `gateway/src/mixture.ts` | The mixture brain: gather (gpt-5.5) → synthesis (Fable, with gpt-5.5 fallback) |
| `config.smithers.yaml` | Points the benchmark's agent at the gateway; sets the neutral judge |
| `Dockerfile.sandbox` | Slim sandbox image for the 5 terminal tasks |
| `setup.sh` / `start-gateway.sh` / `run-one.sh` / `run-batch.sh` / `run-docker-w.sh` | Fetch, serve, run |
docs/llms-integrations.txtmodified+14 −14not agent-reviewed (unsupported_ext)

modified (+14 −14)

Diff (+14 −14)
25 unmodified lines
26
27
28
29
29
30
31
32
68 unmodified lines
101
102
103
104
104
105
106
107
38 unmodified lines
146
147
148
149
149
150
151
152
273 unmodified lines
426
427
428
429
429
430
431
432
433
434
435
436
436
437
438
439
9 unmodified lines
449
450
451
452
452
453
454
455
101 unmodified lines
557
558
559
560
560
561
562
563
564
564
565
566
567
41 unmodified lines
609
610
611
612
612
613
614
615
248 unmodified lines
864
865
866
867
867
868
869
870
26 unmodified lines
897
898
899
900
900
901
902
903
84 unmodified lines
988
989
990
991
991
992
993
994
18 unmodified lines
1013
1014
1015
1016
1016
1017
1018
1019
19 unmodified lines
1039
1040
1041
1042
1042
1043
1044
1045
25 unmodified lines
});
const opsAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools: { linearGetIssue },
});
```
68 unmodified lines
});
const claude = new ClaudeCodeAgent({
model: "claude-sonnet-4-20250514",
model: "claude-fable-5",
systemPrompt: "You are a careful code reviewer.",
timeoutMs: 30 * 60 * 1000,
});
38 unmodified lines
});
const codex = new CodexAgent({
model: "gpt-5.3-codex",
model: "gpt-5.5",
sandbox: "workspace-write",
skipGitRepoCheck: true,
yolo: true,
273 unmodified lines
```ts
const claude = new AnthropicAgent({
model: "claude-opus-4-7",
model: "claude-fable-5",
tools,
instructions: "You are a careful planner.",
stopWhen: stepCountIs(40),
});
const codex = new OpenAIAgent({
model: "gpt-5.3-codex",
model: "gpt-5.5",
tools,
instructions: "You are a precise implementation agent.",
stopWhen: stepCountIs(40),
9 unmodified lines
## Model Input
`AnthropicAgent` and `OpenAIAgent` accept a model ID string (`"claude-opus-4-7"`, `"gpt-5.3-codex"`) or a prebuilt provider model instance. `HermesAgent` accepts an optional model ID string and defaults it to `"hermes"`.
`AnthropicAgent` and `OpenAIAgent` accept a model ID string (`"claude-fable-5"`, `"gpt-5.5"`) or a prebuilt provider model instance. `HermesAgent` accepts an optional model ID string and defaults it to `"hermes"`.
## Options
101 unmodified lines
export const claude = useCli
? new ClaudeCodeAgent({
model: "claude-opus-4-7",
model: "claude-fable-5",
dangerouslySkipPermissions: true,
})
: new AnthropicAgent({
model: "claude-opus-4-7",
model: "claude-fable-5",
tools,
instructions: "You are a careful planner.",
stopWhen: stepCountIs(40),
41 unmodified lines
try {
const agent = new AnthropicAgent({
model: "claude-sonnet-4-20250514",
model: "claude-fable-5",
instructions: "Use the available tools when they are relevant.",
tools: mcp.tools,
});
248 unmodified lines
import { read, grep } from "smithers-orchestrator";
const codeAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools: { read, grep },
});
```
26 unmodified lines
import { write, read } from "smithers-orchestrator";
const writerAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools: { write, read },
});
```
84 unmodified lines
import { bash } from "smithers-orchestrator";
const devAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools: { bash },
});
```
18 unmodified lines
import { z } from "zod";
const codeAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools: { read, write, edit, grep, bash },
instructions: "You are a senior engineer. Use the available tools to complete tasks.",
});
19 unmodified lines
import { tools } from "smithers-orchestrator";
const fullAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools,
});
```
.smithers/tickets/real-stack-e2e/t3-real-chat-llm.mdadded+21 −0not agent-reviewed (unsupported_ext)

added (+21 −0)

Diff (+21 −0)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# t3-real-chat-llm — Chat streams a REAL LLM completion (Gemini Flash or Cerebras) through the real Worker
Wire /api/chat to a real LLM and prove it in the UI.
The Worker (apps/smithers/src/worker.ts) already supports upstream overrides via its env bindings: CEREBRAS_API_KEY (required), CEREBRAS_BASE_URL (default https://api.cerebras.ai/v1), CEREBRAS_MODEL (default gpt-oss-120b). Those are binding NAMES; pointing them at another real OpenAI-compatible LLM API is not a mock.
1. `scripts/e2e-real/worker.ts`: boot the REAL Worker code (same pattern as tests/fixtures/workerHost.ts — study it, but do NOT import it or the cerebrasUpstream fixture) on 127.0.0.1:5376. Upstream selection at boot:
- CEREBRAS_API_KEY set -> use it with the Cerebras defaults.
- else GEMINI_API_KEY set -> bindings CEREBRAS_API_KEY=$GEMINI_API_KEY, CEREBRAS_BASE_URL=https://generativelanguage.googleapis.com/v1beta/openai, CEREBRAS_MODEL=${SMITHERS_E2E_CHAT_MODEL:-gemini-2.5-flash} (Gemini's OpenAI-compatible endpoint, real Gemini Flash completions).
- neither set -> REFUSE to boot with a clear error naming both env vars. No fallback, no canned data.
Log which provider/model was selected (never the key).
2. Extend playwright.real.config.ts: worker webServer leg + SMITHERS_CHAT_PROXY_TARGET=http://127.0.0.1:5376 on the vite leg. Load the keys from apps/smithers/.env.e2e.local AND process.env into the worker leg's env (read the file in the config; never commit values).
3. `apps/smithers/tests/e2e-real/chat.spec.ts`: open the chat surface, send a short prompt (e.g. "Reply with one short sentence."), and assert a real assistant message streams back: non-empty assistant text appears, no error state, and the /api/chat response was a 200 SSE/stream. Generous timeout (real model latency). Assert behavior, not exact text. The spec must pass identically on either upstream.
Success criteria: verify command exits 0 with a REAL upstream (the workflow's preflight already proved the resolved upstream completes a prompt). The worker leg refuses to boot without a key. Zero fixture imports. If the Gemini model id 404s, list the live models via GET https://generativelanguage.googleapis.com/v1beta/openai/models with the key and pick the current flash id; document the choice.
## Verify command (must exit 0)
```bash
pnpm -C apps/smithers exec playwright test --config playwright.real.config.ts tests/e2e-real/chat.spec.ts
```
.smithers/tickets/real-stack-e2e/t6-real-suite-green.mdadded+18 −0not agent-reviewed (unsupported_ext)

added (+18 −0)

Diff (+18 −0)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# t6-real-suite-green — Full real suite + repo gates green in one shot
Stabilization ticket — make the whole thing green in ONE command from a cold start:
- `pnpm -C apps/smithers typecheck` green.
- `pnpm -C apps/smithers test:unit` green (including any assumption tests you added).
- `pnpm -C apps/smithers exec playwright test --config playwright.real.config.ts` green — all e2e-real specs in one run, sharing one stack boot, no inter-spec interference (workers: 1 already; specs assert on their own runIds).
- Fix flakes by fixing root causes (readiness probes, generous-but-bounded timeouts), never by retry-spam or weakened assertions.
- Update apps/smithers docs (e.g. a docs/e2e-real.md or README section) describing: required secrets in .env.e2e.local (chat upstream: CEREBRAS_API_KEY or GEMINI_API_KEY), plue-up.sh usage, the port map, the 7342-vs-7331 gateway rule, and how to run the suite.
- Ensure every piece of this work is committed (atomic, emoji conventional commits). Do not push — the workflow pushes after this gate.
Success criteria: the verify command exits 0, run twice in a row (idempotency). git status shows no uncommitted files from this work.
## Verify command (must exit 0)
```bash
pnpm -C apps/smithers typecheck && pnpm -C apps/smithers test:unit && pnpm -C apps/smithers exec playwright test --config playwright.real.config.ts
```
benchmarks/swe-bench-pro/README.mdmodified+9 −9not agent-reviewed (unsupported_ext)

modified (+9 −9)

Diff (+9 −9)
19 unmodified lines
20
21
22
23
23
24
25
26
43 unmodified lines
70
71
72
73
74
73
74
75
76
77
8 unmodified lines
86
87
88
89
90
91
89
90
91
92
93
94
16 unmodified lines
111
112
113
114
114
115
116
117
4 unmodified lines
122
123
124
125
126
125
126
127
128
129
19 unmodified lines
prepareCheckout ── extract /app from the canonical image at base_commit,
│ strip git history (the fix can't leak)
smithers up workflow.tsx ── Opus 4.8 implements → Codex 5.5 reviews & repairs
smithers up workflow.tsx ── GPT-5.5 implements → Claude Fable reviews & repairs
│ (agents see only problem statement + requirements +
│ interface — never the tests or the gold patch)
43 unmodified lines
### Honest limitations
- **Network during patch generation.** Like the canonical SWE-agent/mini-swe-agent
setups, the implementer keeps a shell (for dependency installs) but is denied
WebFetch/WebSearch; the reviewer runs in Codex's workspace-write sandbox with
setups, the reviewer keeps a shell for local build/test commands but is denied
WebFetch/WebSearch; the implementer runs in Codex's workspace-write sandbox with
network disabled. Both are instructed not to consult external solutions. The
meaningful cheat vector — overfitting to the hidden tests — is impossible: those
tests are never on disk during generation and are introduced only inside the
8 unmodified lines
## Setup
Requires Docker (running), Node 20+, `bun`, an authenticated `claude` CLI (Opus
4.8) and `codex` CLI (GPT-5.5). The canonical images are amd64; on Apple Silicon
they run under emulation (≈1 min/scoring).
Requires Docker (running), Node 20+, `bun`, an authenticated `codex` CLI
(GPT-5.5) and `claude` CLI (Claude Fable). The canonical images are amd64; on
Apple Silicon they run under emulation (≈1 min/scoring).
```bash
node scripts/setup.js # vendor scaleapi/SWE-bench_Pro-os into vendor/
16 unmodified lines
# A small mixed-model sweep
node scripts/cli.js run --languages go --limit 5 \
--implementer claude-opus-4-8 --reviewer gpt-5.5-codex
--implementer gpt-5.5 --reviewer claude-fable-5
```
Selection flags: `--ids`, `--repos`, `--languages`, `--limit`. Model flags:
4 unmodified lines
| Path | Role |
| --- | --- |
| `workflow.tsx` | Patch-generation workflow (Opus implement → Codex review/repair) |
| `components/agents.js` | Opus 4.8 + Codex 5.5 agent factories |
| `workflow.tsx` | Patch-generation workflow (GPT-5.5 implement → Fable review/repair) |
| `components/agents.js` | GPT-5.5 + Claude Fable agent factories |
| `src/loadInstances.js` | Dataset loader (faithful field decoding) |
| `src/prepareCheckout.js` | Extract repo at base_commit, strip history |
| `src/createEntryScript.js` | Port of ScaleAI's `create_entryscript` |
docs/guides/workflow-optimization.mdxmodified+9 −9not agent-reviewed (unsupported_ext)

modified (+9 −9)

Diff (+9 −9)
9 unmodified lines
10
11
12
13
13
14
15
16
26 unmodified lines
43
44
45
46
46
47
48
49
7 unmodified lines
57
58
59
60
60
61
62
63
3 unmodified lines
67
68
69
70
71
72
70
71
72
73
74
75
76
74
75
76
77
78
79
9 unmodified lines
--cases evals/smoke.jsonl \
--suite smoke-gepa \
--provider cerebras \
--model gpt-oss-120b \
--model zai-glm-4.7 \
--artifact .smithers/optimizations/smoke-gepa.json
```
26 unmodified lines
--cases evals/opt.jsonl \
--suite cerebras-proof \
--provider cerebras \
--model gpt-oss-120b \
--model zai-glm-4.7 \
--artifact artifacts/optimized.json \
--report-dir artifacts/reports \
--format json
7 unmodified lines
"optimized": { "score": 1, "passed": 1, "total": 1 },
"improved": true,
"provider": "cerebras",
"model": "gpt-oss-120b"
"model": "zai-glm-4.7"
}
```
3 unmodified lines
| Provider | Optimizer API | Required env | Default model |
| --- | --- | --- | --- |
| `cerebras` | OpenAI-compatible | `CEREBRAS_API_KEY` | `gpt-oss-120b` |
| `openai-api`, `openai`, `openai-sdk`, `codex` | OpenAI-compatible | `OPENAI_API_KEY` | `gpt-5.3-codex` |
| `anthropic-api`, `anthropic`, `anthropic-sdk`, `claude-code`, `claude` | Anthropic Messages API | `ANTHROPIC_API_KEY` | `claude-opus-4-7` |
| `cerebras` | OpenAI-compatible | `CEREBRAS_API_KEY` | `zai-glm-4.7` |
| `openai-api`, `openai`, `openai-sdk`, `codex` | OpenAI-compatible | `OPENAI_API_KEY` | `gpt-5.5` |
| `anthropic-api`, `anthropic`, `anthropic-sdk`, `claude-code`, `claude` | Anthropic Messages API | `ANTHROPIC_API_KEY` | `claude-fable-5` |
| `gemini-api`, `gemini`, `antigravity` | Gemini generateContent API | `GEMINI_API_KEY` or `GOOGLE_API_KEY` | `gemini-3.1-pro-preview` |
| `kimi`, `moonshot` | OpenAI-compatible Moonshot API | `MOONSHOT_API_KEY` | `kimi-latest` |
| `opencode` | OpenAI-compatible endpoint | `SMITHERS_OPTIMIZER_API_KEY` and `SMITHERS_OPTIMIZER_BASE_URL` | `anthropic/claude-sonnet-4-5` |
| `pi` | OpenAI-compatible endpoint | `SMITHERS_OPTIMIZER_API_KEY` and `SMITHERS_OPTIMIZER_BASE_URL` | `gpt-5.3-codex` |
| `kimi`, `moonshot` | OpenAI-compatible Moonshot API | `MOONSHOT_API_KEY` | `kimi-k2.6` |
| `opencode` | OpenAI-compatible endpoint | `SMITHERS_OPTIMIZER_API_KEY` and `SMITHERS_OPTIMIZER_BASE_URL` | `anthropic/claude-fable-5` |
| `pi` | OpenAI-compatible endpoint | `SMITHERS_OPTIMIZER_API_KEY` and `SMITHERS_OPTIMIZER_BASE_URL` | `gpt-5.5` |
| `amp`, `forge`, `openai-compatible` | OpenAI-compatible endpoint | `SMITHERS_OPTIMIZER_API_KEY` and `SMITHERS_OPTIMIZER_BASE_URL` | pass `--model` when needed |
The CLI provider names (`claude-code`, `codex`, `antigravity`, `gemini`, `kimi`) map to their hosted API equivalents for optimization because GEPA needs a direct model call to propose prompt patches. Providers with no single hosted backend (`opencode`, `pi`, `amp`, `forge`) are still accepted through a generic OpenAI-compatible endpoint.
.smithers/tickets/real-stack-e2e/t2-real-signin.mdadded+16 −0not agent-reviewed (unsupported_ext)

added (+16 −0)

Diff (+16 −0)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# t2-real-signin — Sign-in against the REAL plue api with a real seeded token
`apps/smithers/tests/e2e-real/signin.spec.ts`: drive the app's token sign-in UI against the REAL plue api (port 4000) and land signed in.
The real token: plue's compose seeds postgres from $PLUE_DIR/db/seed.sql, which inserts user alice (display name "Alice Dev", admin) and the access token `smithers_deadbeefdeadbeefdeadbeefdeadbeefdeadbeef` (sha-256 hash stored in access_tokens; scopes write:repository,write:user,write:organization). The api validates `Authorization: Bearer <token>` by hashing and looking up. Use that seeded token in the spec; cite db/seed.sql in a comment. (Compose also sets SMITHERS_ENABLE_E2E_TEST_ROUTES=true if you need /_test/ routes; minting is NOT required since the seed token exists.)
Success criteria:
- Spec starts signed out (anonymous /api/user is 401), performs token sign-in through the UI, asserts the signed-in state shows "Alice Dev" exactly as stored in plue's postgres, and survives a page reload still signed in.
- No fakePlueHost / fixture imports; the token comes from real plue's own seed, not from a fake's seed table.
- Pin the plue contract you depend on (token format, /api/user response fields) in a NEW bun assumption test under apps/smithers/tests/assumptions/ that probes the live plue api, guarded by an env flag so it only runs when plue is up. Do not modify the existing fixture-suite assumption files.
## Verify command (must exit 0)
```bash
pnpm -C apps/smithers exec playwright test --config playwright.real.config.ts tests/e2e-real/signin.spec.ts
```
.smithers/tickets/real-stack-e2e/t4-real-gateway-run.mdadded+16 −0not agent-reviewed (unsupported_ext)

added (+16 −0)

Diff (+16 −0)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# t4-real-gateway-run — Launch a gateway workflow run that makes a REAL Claude LLM call, watch it finish in the UI
Make the cwd gateway execute a real agent workflow end to end.
1. `.smithers/workflows/e2e-probe.tsx`: a minimal one-task agent workflow (output schema like { answer: z.string() }) whose Task uses a ClaudeCodeAgent (model claude-sonnet-4-6, cheap — NOT 4-7, which 404s on this account) and asks for a one-line answer. The gateway auto-mounts every .smithers/workflows/*.tsx at boot, so creating the file registers it on next gateway boot.
- Mount caveat: an ALREADY-RUNNING e2e gateway on 7342 will not see the new file. If 7342 is up and /workflows lacks e2e-probe, kill ONLY that gateway process (the one bound to 7342; never 7331) and let playwright's webServer reboot it. Script this guard into the spec setup or a tiny stack helper.
2. `scripts/e2e-real/probe-agent-cred.sh` — ASSUMPTION PROBE, must run before the spec: source apps/smithers/.env.e2e.local if present, `unset ANTHROPIC_API_KEY` unless that file supplied one (see ground rules: the shell-exported key has no credits), then run `claude -p "Say OK" --model claude-sonnet-4-6` ON THE HOST (the gateway spawns the same host CLI) and require exit 0 with non-empty output. If this fails, the spec is doomed — fail fast naming the missing credential (claude /login, claude setup-token, or ANTHROPIC_API_KEY).
3. `apps/smithers/tests/e2e-real/gatewayRun.spec.ts`: through the UI (study tests/e2e/launchRun.spec.ts + gatewayRun.spec.ts for the surfaces, but target the real config), launch the e2e-probe workflow on the real gateway, watch live run events arrive, and assert THAT run (by its runId) reaches finished with a visible non-empty output. Timeout generous (a real Claude call takes 30-120s).
Success criteria: probe script + spec both green via the verify command. The LLM call is real (visible token usage / agent events in the gateway run, no canned text).
## Verify command (must exit 0)
```bash
bash scripts/e2e-real/probe-agent-cred.sh && pnpm -C apps/smithers exec playwright test --config playwright.real.config.ts tests/e2e-real/gatewayRun.spec.ts
```
.smithers/tickets/real-stack-e2e/t5-real-approval.mdadded+12 −0not agent-reviewed (unsupported_ext)

added (+12 −0)

Diff (+12 −0)
1
2
3
4
5
6
7
8
9
10
11
12
# t5-real-approval — Human approval round-trip through the real gateway UI
1. `.smithers/workflows/e2e-approval-probe.tsx`: an <Approval> node (request title/summary) followed by a static Task that only mounts after approval (see the Approval docs pattern). Same mount caveat as t4: a stale gateway on 7342 must be restarted to pick the file up.
2. `apps/smithers/tests/e2e-real/approval.spec.ts`: launch e2e-approval-probe on the real gateway through the UI, assert the run pauses waiting-approval and the approval request surfaces in the UI, approve it FROM THE UI, then assert the run resumes and reaches finished with the gated task's output present.
Success criteria: the whole round-trip is driven through the real gateway RPC path (no direct DB pokes, no CLI approve in the spec), and the verify command exits 0.
## Verify command (must exit 0)
```bash
pnpm -C apps/smithers exec playwright test --config playwright.real.config.ts tests/e2e-real/approval.spec.ts
```
docs/integrations/sdk-agents.mdxmodified+5 −5not agent-reviewed (unsupported_ext)

modified (+5 −5)

Diff (+5 −5)
19 unmodified lines
20
21
22
23
23
24
25
26
27
28
29
30
30
31
32
33
9 unmodified lines
43
44
45
46
46
47
48
49
101 unmodified lines
151
152
153
154
154
155
156
157
158
158
159
160
161
19 unmodified lines
```ts
const claude = new AnthropicAgent({
model: "claude-opus-4-7",
model: "claude-fable-5",
tools,
instructions: "You are a careful planner.",
stopWhen: stepCountIs(40),
});
const codex = new OpenAIAgent({
model: "gpt-5.3-codex",
model: "gpt-5.5",
tools,
instructions: "You are a precise implementation agent.",
stopWhen: stepCountIs(40),
9 unmodified lines
## Model Input
`AnthropicAgent` and `OpenAIAgent` accept a model ID string (`"claude-opus-4-7"`, `"gpt-5.3-codex"`) or a prebuilt provider model instance. `HermesAgent` accepts an optional model ID string and defaults it to `"hermes"`.
`AnthropicAgent` and `OpenAIAgent` accept a model ID string (`"claude-fable-5"`, `"gpt-5.5"`) or a prebuilt provider model instance. `HermesAgent` accepts an optional model ID string and defaults it to `"hermes"`.
## Options
101 unmodified lines
export const claude = useCli
? new ClaudeCodeAgent({
model: "claude-opus-4-7",
model: "claude-fable-5",
dangerouslySkipPermissions: true,
})
: new AnthropicAgent({
model: "claude-opus-4-7",
model: "claude-fable-5",
tools,
instructions: "You are a careful planner.",
stopWhen: stepCountIs(40),
docs/integrations/tools.mdxmodified+5 −5not agent-reviewed (unsupported_ext)

modified (+5 −5)

Diff (+5 −5)
162 unmodified lines
163
164
165
166
166
167
168
169
26 unmodified lines
196
197
198
199
199
200
201
202
84 unmodified lines
287
288
289
290
290
291
292
293
18 unmodified lines
312
313
314
315
315
316
317
318
19 unmodified lines
338
339
340
341
341
342
343
344
162 unmodified lines
import { read, grep } from "smithers-orchestrator";
const codeAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools: { read, grep },
});
```
26 unmodified lines
import { write, read } from "smithers-orchestrator";
const writerAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools: { write, read },
});
```
84 unmodified lines
import { bash } from "smithers-orchestrator";
const devAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools: { bash },
});
```
18 unmodified lines
import { z } from "zod";
const codeAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools: { read, write, edit, grep, bash },
instructions: "You are a senior engineer. Use the available tools to complete tasks.",
});
19 unmodified lines
import { tools } from "smithers-orchestrator";
const fullAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools,
});
```
docs/examples/worktree-feature-workflow.mdxmodified+3 −3not agent-reviewed (unsupported_ext)

modified (+3 −3)

Diff (+3 −3)
81 unmodified lines
82
83
84
85
85
86
87
88
89
90
91
91
92
93
94
3 unmodified lines
98
99
100
101
101
102
103
104
81 unmodified lines
// Claude: switches between API agent and CLI agent
const claudeApi = new Agent({
model: anthropic("claude-opus-4-7"),
model: anthropic("claude-fable-5"),
instructions: SYSTEM_PROMPT,
stopWhen: stepCountIs(100),
});
const claudeCli = new ClaudeCodeAgent({
model: "claude-opus-4-7",
model: "claude-fable-5",
systemPrompt: SYSTEM_PROMPT,
dangerouslySkipPermissions: UNSAFE,
timeoutMs: 30 * 60 * 1000,
3 unmodified lines
// Codex: CLI agent (CodexAgent does not have an API mode)
export const codex = new CodexAgent({
model: "gpt-5.3-codex",
model: "gpt-5.5",
systemPrompt: SYSTEM_PROMPT,
yolo: UNSAFE,
timeoutMs: 30 * 60 * 1000,
docs/tour.mdxmodified+3 −3not agent-reviewed (unsupported_ext)

modified (+3 −3)

Diff (+3 −3)
94 unmodified lines
95
96
97
98
98
99
100
101
38 unmodified lines
140
141
142
143
143
144
145
146
147
148
148
149
150
151
94 unmodified lines
});
const analyst = new AnthropicAgent({
model: "claude-sonnet-4-20250514",
model: "claude-fable-5",
instructions: "You are a senior code reviewer. Return structured JSON.",
});
38 unmodified lines
});
const analyst = new AnthropicAgent({
model: "claude-sonnet-4-20250514",
model: "claude-fable-5",
instructions: "You are a senior code reviewer. Return structured JSON.",
});
const fixer = new AnthropicAgent({
model: "claude-sonnet-4-20250514",
model: "claude-fable-5",
instructions: "Write minimal, correct fixes as a unified diff.",
});
docs/integrations/cli-agents.mdxmodified+2 −2not agent-reviewed (unsupported_ext)

modified (+2 −2)

Diff (+2 −2)
15 unmodified lines
16
17
18
19
19
20
21
22
38 unmodified lines
61
62
63
64
64
65
66
67
15 unmodified lines
});
const claude = new ClaudeCodeAgent({
model: "claude-sonnet-4-20250514",
model: "claude-fable-5",
systemPrompt: "You are a careful code reviewer.",
timeoutMs: 30 * 60 * 1000,
});
38 unmodified lines
});
const codex = new CodexAgent({
model: "gpt-5.3-codex",
model: "gpt-5.5",
sandbox: "workspace-write",
skipGitRepoCheck: true,
yolo: true,
apps/smithers-demo/README.mdmodified+1 −1not agent-reviewed (unsupported_ext)

modified (+1 −1)

Diff (+1 −1)
31 unmodified lines
32
33
34
35
35
36
37
38
31 unmodified lines
ANTHROPIC_API_KEY=... pnpm --filter @smithers-orchestrator/smithers-demo cerebras:debate
```
The browser app stores provider, model, and key settings in local browser settings. Defaults are Cerebras `gpt-oss-120b`, OpenAI `gpt-5.5`, and Claude `claude-opus-4.7`.
The browser app stores provider, model, and key settings in local browser settings. Defaults are Cerebras `zai-glm-4.7`, OpenAI `gpt-5.5`, and Claude `claude-fable-5`.
## Validate
docs/agents/claude-code.mdxmodified+1 −1not agent-reviewed (unsupported_ext)

modified (+1 −1)

Diff (+1 −1)
109 unmodified lines
110
111
112
113
113
114
115
116
109 unmodified lines
```tsx
import { ClaudeCodeAgent } from "smithers-orchestrator";
const claude = new ClaudeCodeAgent({ model: "claude-sonnet-4-20250514" });
const claude = new ClaudeCodeAgent({ model: "claude-fable-5" });
```
See [CLI Agents → Claude Code](/integrations/cli-agents).
docs/agents/codex.mdxmodified+1 −1not agent-reviewed (unsupported_ext)

modified (+1 −1)

Diff (+1 −1)
74 unmodified lines
75
76
77
78
78
79
80
81
74 unmodified lines
```tsx
import { CodexAgent } from "smithers-orchestrator";
const codex = new CodexAgent({ model: "gpt-5.3-codex", sandbox: "workspace-write" });
const codex = new CodexAgent({ model: "gpt-5.5", sandbox: "workspace-write" });
```
See [CLI Agents → Codex](/integrations/cli-agents#codex-cli-agent).
docs/components/task.mdxmodified+1 −1not agent-reviewed (unsupported_ext)

modified (+1 −1)

Diff (+1 −1)
52 unmodified lines
53
54
55
56
56
57
58
59
52 unmodified lines
import { anthropic } from "@ai-sdk/anthropic";
const codeAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
instructions: "You are a senior software engineer.",
});
docs/components/workflow.mdxmodified+1 −1not agent-reviewed (unsupported_ext)

modified (+1 −1)

Diff (+1 −1)
23 unmodified lines
24
25
26
27
27
28
29
30
23 unmodified lines
});
const researcher = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
instructions: "You are a research assistant.",
});
docs/concepts/openapi-tools.mdxmodified+1 −1not agent-reviewed (unsupported_ext)

modified (+1 −1)

Diff (+1 −1)
15 unmodified lines
16
17
18
19
19
20
21
22
15 unmodified lines
});
const agent = new ToolLoopAgent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools,
});
```
docs/examples/hello-world.mdxmodified+1 −1not agent-reviewed (unsupported_ext)

modified (+1 −1)

Diff (+1 −1)
21 unmodified lines
22
23
24
25
25
26
27
28
21 unmodified lines
});
const greeter = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
instructions: "You are a friendly greeter. Respond with a short, warm greeting.",
});
docs/guides/model-selection.mdxmodified+1 −1not agent-reviewed (unsupported_ext)

modified (+1 −1)

Diff (+1 −1)
4 unmodified lines
5
6
7
8
8
4 unmodified lines
This material is now in [Recipes](/recipes).
Rule-of-thumb assignments: Codex (`gpt-5.3-codex`) for implementation, validation, and review-fix; Claude Opus (`claude-opus-4-7`) for research, planning, review, and reports; Claude Sonnet for cheap tool calls. Run two different models in parallel for review, since they have different blind spots. Codex `model_reasoning_effort` defaults to `high`; bump to `xhigh` for multi-file refactors.
Rule-of-thumb assignments: Codex (`gpt-5.5`) for implementation, validation, and review-fix; Claude Fable (`claude-fable-5`) for research, planning, review, and reports; Claude Opus (`claude-opus-4-8`) as the secondary smart Claude model; Claude Sonnet for cheap tool calls. Run two different models in parallel for review, since they have different blind spots. Codex `model_reasoning_effort` defaults to `high`; bump to `xhigh` for multi-file refactors.
docs/integrations/integrations.mdxmodified+1 −1not agent-reviewed (unsupported_ext)

modified (+1 −1)

Diff (+1 −1)
20 unmodified lines
21
22
23
24
24
25
26
27
20 unmodified lines
});
const opsAgent = new Agent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools: { linearGetIssue },
});
```
docs/integrations/mcp-toolset.mdxmodified+1 −1not agent-reviewed (unsupported_ext)

modified (+1 −1)

Diff (+1 −1)
31 unmodified lines
32
33
34
35
35
36
37
38
31 unmodified lines
try {
const agent = new AnthropicAgent({
model: "claude-sonnet-4-20250514",
model: "claude-fable-5",
instructions: "Use the available tools when they are relevant.",
tools: mcp.tools,
});
docs/llms-openapi.txtmodified+1 −1not agent-reviewed (unsupported_ext)

modified (+1 −1)

Diff (+1 −1)
20 unmodified lines
21
22
23
24
24
25
26
27
20 unmodified lines
});
const agent = new ToolLoopAgent({
model: anthropic("claude-sonnet-4-20250514"),
model: anthropic("claude-fable-5"),
tools,
});
```