Skip to content

Commit 07bc125

Browse files
that-github-userunknownclaude
authored
Support Amazon Bedrock model IDs and authentication (#125)
Accept anthropic.* model IDs without warning in CLI and config validation. AWS env vars (ACCESS_KEY, SECRET_KEY, SESSION_TOKEN, REGION) passed through to agent processes via process.env spread. Updated .env.example and README. Generated by thinktank Opus (5 agents, 3 pass, Copeland: +2). Closes #122 Co-authored-by: unknown <that-github-user@github.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 3572df2 commit 07bc125

5 files changed

Lines changed: 93 additions & 1 deletion

File tree

.env.example

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
11
# Required: Anthropic API key (used by Claude Code CLI)
22
# Get one at https://console.anthropic.com/
33
ANTHROPIC_API_KEY=sk-ant-...
4+
5+
# Optional: Amazon Bedrock credentials (use instead of ANTHROPIC_API_KEY)
6+
# Set these to route Claude requests through AWS Bedrock.
7+
# Use --model with a Bedrock model ID, e.g. anthropic.claude-opus-4-6-v1
8+
# AWS_ACCESS_KEY_ID=AKIA...
9+
# AWS_SECRET_ACCESS_KEY=...
10+
# AWS_SESSION_TOKEN=...
11+
# AWS_REGION=us-east-1
12+
# AWS_DEFAULT_REGION=us-east-1

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ Requires [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code) insta
4646

4747
Use `--model` to select a Claude model: `sonnet` (default), `opus`, `haiku`, or a full model ID like `claude-opus-4-6`.
4848

49+
**Amazon Bedrock**: Pass a Bedrock model ID such as `anthropic.claude-opus-4-6-v1` and set the standard AWS environment variables (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_REGION`, etc.). See `.env.example` for details.
50+
4951
## How it works
5052

5153
```

src/cli.test.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import assert from "node:assert/strict";
2+
import { describe, it } from "node:test";
3+
4+
/**
5+
* Tests for CLI model ID validation logic.
6+
* The CLI accepts: known aliases, claude-* prefixed, and anthropic.* prefixed model IDs.
7+
*/
8+
describe("CLI model validation", () => {
9+
function isKnownModel(model: string): boolean {
10+
const knownModels = ["sonnet", "opus", "haiku"];
11+
return (
12+
knownModels.includes(model) || model.startsWith("claude-") || model.startsWith("anthropic.")
13+
);
14+
}
15+
16+
it("accepts known alias 'sonnet'", () => {
17+
assert.equal(isKnownModel("sonnet"), true);
18+
});
19+
20+
it("accepts known alias 'opus'", () => {
21+
assert.equal(isKnownModel("opus"), true);
22+
});
23+
24+
it("accepts known alias 'haiku'", () => {
25+
assert.equal(isKnownModel("haiku"), true);
26+
});
27+
28+
it("accepts claude- prefixed model IDs", () => {
29+
assert.equal(isKnownModel("claude-opus-4-6"), true);
30+
assert.equal(isKnownModel("claude-sonnet-4-6"), true);
31+
});
32+
33+
it("accepts anthropic. prefixed Bedrock model IDs", () => {
34+
assert.equal(isKnownModel("anthropic.claude-opus-4-6-v1"), true);
35+
assert.equal(isKnownModel("anthropic.claude-sonnet-4-6-v1"), true);
36+
assert.equal(isKnownModel("anthropic.claude-v2"), true);
37+
});
38+
39+
it("rejects unknown model IDs", () => {
40+
assert.equal(isKnownModel("gpt-4"), false);
41+
assert.equal(isKnownModel("gemini-pro"), false);
42+
assert.equal(isKnownModel("unknown"), false);
43+
});
44+
});

src/cli.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,11 @@ program
115115
}
116116

117117
const knownModels = ["sonnet", "opus", "haiku"];
118-
if (!knownModels.includes(opts.model) && !opts.model.startsWith("claude-")) {
118+
if (
119+
!knownModels.includes(opts.model) &&
120+
!opts.model.startsWith("claude-") &&
121+
!opts.model.startsWith("anthropic.")
122+
) {
119123
console.warn(
120124
`Warning: unknown model "${opts.model}" — known models: ${knownModels.join(", ")}`,
121125
);

src/runners/claude-code.test.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import assert from "node:assert/strict";
2+
import { describe, it } from "node:test";
3+
4+
describe("claude-code runner", () => {
5+
describe("AWS environment variable passthrough", () => {
6+
const awsVars = [
7+
"AWS_ACCESS_KEY_ID",
8+
"AWS_SECRET_ACCESS_KEY",
9+
"AWS_SESSION_TOKEN",
10+
"AWS_REGION",
11+
"AWS_DEFAULT_REGION",
12+
];
13+
14+
for (const varName of awsVars) {
15+
it(`passes ${varName} through to spawned process via process.env`, () => {
16+
// The runner uses { ...process.env } as the spawn env.
17+
// Verify that setting a process.env var makes it available in the spread.
18+
const original = process.env[varName];
19+
try {
20+
process.env[varName] = "test-value";
21+
const env = { ...process.env };
22+
assert.equal(env[varName], "test-value");
23+
} finally {
24+
if (original === undefined) {
25+
delete process.env[varName];
26+
} else {
27+
process.env[varName] = original;
28+
}
29+
}
30+
});
31+
}
32+
});
33+
});

0 commit comments

Comments
 (0)