juggernaut-bedrock 4.0.0 → 4.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +118 -0
- package/bin/.gitkeep +0 -0
- package/install.js +42 -61
- package/package.json +23 -5
package/README.md
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# juggernaut-bedrock
|
|
2
|
+
|
|
3
|
+
**Claude Code → Amazon Bedrock in one command.**
|
|
4
|
+
|
|
5
|
+
Juggernaut is a cross-platform CLI that wires [Claude Code](https://docs.anthropic.com/en/docs/claude-code) to [Amazon Bedrock](https://aws.amazon.com/bedrock/) instead of Anthropic's direct API. One install, one `apply`, then just run `claude` — no shell profile hacks, no manual env vars, no jq.
|
|
6
|
+
|
|
7
|
+
Built for developers shipping with GenAI today: IAM and SSO for teams, API keys for solo runs, and a `doctor` command when something's off.
|
|
8
|
+
|
|
9
|
+
<p align="center">
|
|
10
|
+
<a href="https://github.com/jpvelasco/juggernaut/actions/workflows/ci.yml"><img src="https://github.com/jpvelasco/juggernaut/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
|
|
11
|
+
<a href="https://github.com/jpvelasco/juggernaut/releases/latest"><img src="https://img.shields.io/github/v/release/jpvelasco/juggernaut" alt="Release"></a>
|
|
12
|
+
<a href="https://www.npmjs.com/package/juggernaut-bedrock"><img src="https://img.shields.io/npm/v/juggernaut-bedrock" alt="npm"></a>
|
|
13
|
+
<a href="https://app.codacy.com/gh/jpvelasco/juggernaut/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade"><img src="https://app.codacy.com/project/badge/Grade/2bf1e68b80964537b5c65350663c3073" alt="Codacy Grade"></a>
|
|
14
|
+
</p>
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install -g juggernaut-bedrock
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Or try it without installing globally:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npx juggernaut-bedrock version
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Works on **macOS**, **Linux**, **Windows**, and **WSL** — `x64` and `arm64`.
|
|
29
|
+
|
|
30
|
+
## Quickstart
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# 1. Install (above)
|
|
34
|
+
|
|
35
|
+
# 2. Configure — IAM/SSO (recommended) or interactive prompt
|
|
36
|
+
juggernaut apply --auth=iam
|
|
37
|
+
|
|
38
|
+
# 3. Launch Claude Code (token injected automatically)
|
|
39
|
+
claude
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Bedrock API key auth? Run `juggernaut apply` and follow the prompt — credentials land in your OS keychain, not your shell history.
|
|
43
|
+
|
|
44
|
+
## What it does
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
juggernaut apply --auth=iam
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
That one command:
|
|
51
|
+
|
|
52
|
+
1. **Writes** Bedrock config to `~/.claude/settings.json` (or project scope)
|
|
53
|
+
2. **Sets** model IDs, region, effort level, and `CLAUDE_CODE_USE_BEDROCK=1` — only after credentials check out
|
|
54
|
+
3. **Installs** a `claude` launcher shim that reads your token from the keychain and execs the real binary
|
|
55
|
+
|
|
56
|
+
No `.bashrc` edits. No copying API keys into env vars. No "why isn't Bedrock routing?" at 2am.
|
|
57
|
+
|
|
58
|
+
## Why Bedrock?
|
|
59
|
+
|
|
60
|
+
| | Direct Anthropic API | Amazon Bedrock |
|
|
61
|
+
|---|---------------------|----------------|
|
|
62
|
+
| **Billing** | Separate account | Your AWS bill |
|
|
63
|
+
| **Auth** | API keys | IAM, SSO, roles |
|
|
64
|
+
| **Region** | Anthropic infra | Your chosen AWS region |
|
|
65
|
+
| **Compliance** | Anthropic certs | SOC, HIPAA, FedRAMP via AWS |
|
|
66
|
+
| **Network** | Public internet | VPC endpoints, PrivateLink |
|
|
67
|
+
|
|
68
|
+
## Auth modes
|
|
69
|
+
|
|
70
|
+
| Mode | Command | Best for |
|
|
71
|
+
|------|---------|----------|
|
|
72
|
+
| **IAM / SSO** | `juggernaut apply --auth=iam` | Teams, enterprise, existing AWS identity |
|
|
73
|
+
| **Bedrock API key** | `juggernaut apply` | Solo devs, quick setup |
|
|
74
|
+
| **Interactive** | `juggernaut apply` (no flags) | First run — guided prompts |
|
|
75
|
+
| **Preview** | `juggernaut apply --dry-run` | See what would change, change nothing |
|
|
76
|
+
|
|
77
|
+
## Commands
|
|
78
|
+
|
|
79
|
+
| Command | What it does |
|
|
80
|
+
|---------|--------------|
|
|
81
|
+
| `apply` | Configure Bedrock + install the `claude` shim |
|
|
82
|
+
| `show` | Print your current Juggernaut config |
|
|
83
|
+
| `doctor` | Diagnostics — block, credentials, launcher |
|
|
84
|
+
| `migrate` | Upgrade from v3 shell installer to v4 Go binary |
|
|
85
|
+
| `uninstall` | Remove config, token, and shim |
|
|
86
|
+
| `version` | Print installed version (`--json` for machines) |
|
|
87
|
+
|
|
88
|
+
## Default models
|
|
89
|
+
|
|
90
|
+
| Tier | Model |
|
|
91
|
+
|------|-------|
|
|
92
|
+
| **Primary** | Claude Sonnet 4.6 |
|
|
93
|
+
| **Opus** | Claude Opus 4.7 |
|
|
94
|
+
| **Fast** | Claude Haiku 4.5 |
|
|
95
|
+
|
|
96
|
+
Override any tier: `juggernaut apply --auth=iam --model=global.anthropic.claude-sonnet-4-6`
|
|
97
|
+
|
|
98
|
+
## Troubleshooting
|
|
99
|
+
|
|
100
|
+
Stuck? Start here:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
juggernaut doctor
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Common fixes: complete Anthropic model access in the Bedrock console (403), refresh SSO (`aws sso login`), or re-run `juggernaut apply`.
|
|
107
|
+
|
|
108
|
+
## Documentation
|
|
109
|
+
|
|
110
|
+
Full docs, IAM policy, migration guide, and platform notes:
|
|
111
|
+
|
|
112
|
+
**[github.com/jpvelasco/juggernaut](https://github.com/jpvelasco/juggernaut)**
|
|
113
|
+
|
|
114
|
+
## License
|
|
115
|
+
|
|
116
|
+
MIT — see [LICENSE](https://github.com/jpvelasco/juggernaut/blob/main/LICENSE).
|
|
117
|
+
|
|
118
|
+
Juggernaut is an independent tool, not affiliated with Anthropic or Amazon Web Services.
|
package/bin/.gitkeep
ADDED
|
File without changes
|
package/install.js
CHANGED
|
@@ -3,11 +3,16 @@
|
|
|
3
3
|
const https = require("https");
|
|
4
4
|
const fs = require("fs");
|
|
5
5
|
const path = require("path");
|
|
6
|
-
const
|
|
6
|
+
const { Readable } = require("stream");
|
|
7
7
|
const crypto = require("crypto");
|
|
8
8
|
|
|
9
9
|
const REPO = "jpvelasco/juggernaut";
|
|
10
10
|
const BIN_DIR = path.join(__dirname, "bin");
|
|
11
|
+
const ALLOWED_HOSTS = new Set([
|
|
12
|
+
"github.com",
|
|
13
|
+
"api.github.com",
|
|
14
|
+
"release-assets.githubusercontent.com"
|
|
15
|
+
]);
|
|
11
16
|
|
|
12
17
|
function getPlatform() {
|
|
13
18
|
const osMap = { darwin: "darwin", linux: "linux", win32: "windows" };
|
|
@@ -20,12 +25,23 @@ function getPlatform() {
|
|
|
20
25
|
return { os: p, arch: a, platform: `${p}_${a}` };
|
|
21
26
|
}
|
|
22
27
|
|
|
23
|
-
function
|
|
28
|
+
function httpsGetBuffer(url) {
|
|
29
|
+
const parsed = new URL(url);
|
|
30
|
+
if (!ALLOWED_HOSTS.has(parsed.hostname)) {
|
|
31
|
+
throw new Error(`URL host not allowed: ${parsed.hostname}`);
|
|
32
|
+
}
|
|
24
33
|
return new Promise((resolve, reject) => {
|
|
25
34
|
https
|
|
26
35
|
.get(url, { headers: { "User-Agent": "juggernaut-npm-installer/1.0" } }, (res) => {
|
|
27
36
|
if (res.statusCode === 301 || res.statusCode === 302) {
|
|
28
|
-
|
|
37
|
+
const location = res.headers.location;
|
|
38
|
+
const redirectParsed = new URL(location);
|
|
39
|
+
if (!ALLOWED_HOSTS.has(redirectParsed.hostname)) {
|
|
40
|
+
reject(new Error(`Redirect host not allowed: ${redirectParsed.hostname}`));
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
httpsGetBuffer(location).then(resolve).catch(reject);
|
|
44
|
+
return;
|
|
29
45
|
}
|
|
30
46
|
const chunks = [];
|
|
31
47
|
res.on("data", (chunk) => chunks.push(chunk));
|
|
@@ -36,27 +52,8 @@ function httpsGet(url) {
|
|
|
36
52
|
});
|
|
37
53
|
}
|
|
38
54
|
|
|
39
|
-
function downloadFile(url, dest) {
|
|
40
|
-
return new Promise((resolve, reject) => {
|
|
41
|
-
const file = fs.createWriteStream(dest);
|
|
42
|
-
function fetch(fetchUrl) {
|
|
43
|
-
https
|
|
44
|
-
.get(fetchUrl, { headers: { "User-Agent": "juggernaut-npm-installer/1.0" } }, (res) => {
|
|
45
|
-
if (res.statusCode === 301 || res.statusCode === 302) {
|
|
46
|
-
return fetch(res.headers.location);
|
|
47
|
-
}
|
|
48
|
-
res.pipe(file);
|
|
49
|
-
file.on("finish", () => file.close(resolve));
|
|
50
|
-
file.on("error", reject);
|
|
51
|
-
})
|
|
52
|
-
.on("error", reject);
|
|
53
|
-
}
|
|
54
|
-
fetch(url);
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
|
|
58
55
|
async function getLatestVersion() {
|
|
59
|
-
const data = await
|
|
56
|
+
const data = await httpsGetBuffer(`https://api.github.com/repos/${REPO}/releases/latest`);
|
|
60
57
|
const release = JSON.parse(data.toString());
|
|
61
58
|
return release.tag_name.replace(/^v/, "");
|
|
62
59
|
}
|
|
@@ -68,49 +65,33 @@ async function main() {
|
|
|
68
65
|
const archive = `juggernaut_${platform}.${ext}`;
|
|
69
66
|
const baseUrl = `https://github.com/${REPO}/releases/download/v${version}`;
|
|
70
67
|
|
|
71
|
-
|
|
72
|
-
const
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
try {
|
|
76
|
-
console.log(`Downloading Juggernaut v${version} (${platform})...`);
|
|
77
|
-
await downloadFile(`${baseUrl}/${archive}`, archivePath);
|
|
78
|
-
await downloadFile(`${baseUrl}/checksums.txt`, checksumPath);
|
|
79
|
-
|
|
80
|
-
// Verify checksum.
|
|
81
|
-
const checksums = fs.readFileSync(checksumPath, "utf8");
|
|
82
|
-
const line = checksums.split("\n").find((l) => l.includes(archive));
|
|
83
|
-
if (!line) throw new Error(`Checksum not found for ${archive}`);
|
|
84
|
-
const expected = line.trim().split(/\s+/)[0].toLowerCase();
|
|
85
|
-
const actual = crypto
|
|
86
|
-
.createHash("sha256")
|
|
87
|
-
.update(fs.readFileSync(archivePath))
|
|
88
|
-
.digest("hex")
|
|
89
|
-
.toLowerCase();
|
|
90
|
-
if (actual !== expected) {
|
|
91
|
-
throw new Error(`Checksum mismatch for ${archive}\n expected: ${expected}\n got: ${actual}`);
|
|
92
|
-
}
|
|
68
|
+
console.log(`Downloading Juggernaut v${version} (${platform})...`);
|
|
69
|
+
const archiveBuf = await httpsGetBuffer(`${baseUrl}/${archive}`);
|
|
70
|
+
const checksumsBuf = await httpsGetBuffer(`${baseUrl}/checksums.txt`);
|
|
93
71
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
await tar.x({ file: archivePath, cwd: BIN_DIR });
|
|
103
|
-
fs.chmodSync(path.join(BIN_DIR, "juggernaut"), 0o755);
|
|
104
|
-
}
|
|
72
|
+
const checksums = checksumsBuf.toString("utf8");
|
|
73
|
+
const line = checksums.split("\n").find((l) => l.includes(archive));
|
|
74
|
+
if (!line) throw new Error(`Checksum not found for ${archive}`);
|
|
75
|
+
const expected = line.trim().split(/\s+/)[0].toLowerCase();
|
|
76
|
+
const actual = crypto.createHash("sha256").update(archiveBuf).digest("hex").toLowerCase();
|
|
77
|
+
if (actual !== expected) {
|
|
78
|
+
throw new Error(`Checksum mismatch for ${archive}\n expected: ${expected}\n got: ${actual}`);
|
|
79
|
+
}
|
|
105
80
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
81
|
+
if (ext === "zip") {
|
|
82
|
+
const AdmZip = require("adm-zip");
|
|
83
|
+
const zip = new AdmZip(archiveBuf);
|
|
84
|
+
zip.extractEntryTo("juggernaut.exe", BIN_DIR, false, true);
|
|
85
|
+
} else {
|
|
86
|
+
const tar = require("tar");
|
|
87
|
+
await tar.x({ cwd: BIN_DIR, mode: 0o700, strict: true }, Readable.from(archiveBuf));
|
|
110
88
|
}
|
|
89
|
+
|
|
90
|
+
console.log(`Juggernaut v${version} installed successfully.`);
|
|
91
|
+
console.log(`Run: juggernaut apply`);
|
|
111
92
|
}
|
|
112
93
|
|
|
113
94
|
main().catch((err) => {
|
|
114
95
|
console.error("Installation failed:", err.message);
|
|
115
96
|
process.exit(1);
|
|
116
|
-
});
|
|
97
|
+
});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "juggernaut-bedrock",
|
|
3
|
-
"version": "4.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "4.0.2",
|
|
4
|
+
"description": "Route Claude Code through Amazon Bedrock in one command — IAM, SSO, or API key. Cross-platform CLI for GenAI developers.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"juggernaut": "./bin/juggernaut"
|
|
7
7
|
},
|
|
@@ -9,16 +9,34 @@
|
|
|
9
9
|
"postinstall": "node install.js"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"tar": "
|
|
13
|
-
"adm-zip": "
|
|
12
|
+
"tar": "7.5.16",
|
|
13
|
+
"adm-zip": "0.5.17"
|
|
14
14
|
},
|
|
15
15
|
"os": ["darwin", "linux", "win32"],
|
|
16
16
|
"cpu": ["x64", "arm64"],
|
|
17
|
-
"keywords": [
|
|
17
|
+
"keywords": [
|
|
18
|
+
"claude",
|
|
19
|
+
"claude-code",
|
|
20
|
+
"bedrock",
|
|
21
|
+
"amazon-bedrock",
|
|
22
|
+
"aws",
|
|
23
|
+
"anthropic",
|
|
24
|
+
"genai",
|
|
25
|
+
"ai-coding",
|
|
26
|
+
"llm",
|
|
27
|
+
"coding-agent",
|
|
28
|
+
"cli",
|
|
29
|
+
"iam",
|
|
30
|
+
"sso",
|
|
31
|
+
"developer-tools"
|
|
32
|
+
],
|
|
18
33
|
"license": "MIT",
|
|
19
34
|
"repository": {
|
|
20
35
|
"type": "git",
|
|
21
36
|
"url": "https://github.com/jpvelasco/juggernaut"
|
|
22
37
|
},
|
|
38
|
+
"bugs": {
|
|
39
|
+
"url": "https://github.com/jpvelasco/juggernaut/issues"
|
|
40
|
+
},
|
|
23
41
|
"homepage": "https://github.com/jpvelasco/juggernaut#readme"
|
|
24
42
|
}
|