context-foundry 0.7.9

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 ADDED
@@ -0,0 +1,46 @@
1
+ # Foundry
2
+
3
+ Autonomous build loop that plans, builds, reviews, and learns -- forever.
4
+
5
+ This is the npm installer for Foundry. It downloads the correct pre-built binary for your platform from [GitHub Releases](https://github.com/context-foundry/context-foundry/releases).
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install -g context-foundry
11
+ ```
12
+
13
+ This installs the `foundry` command globally.
14
+
15
+ ## Requirements
16
+
17
+ - [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code) must be installed and authenticated
18
+
19
+ ## Usage
20
+
21
+ ```bash
22
+ # Point at any project with a TASKS.md
23
+ foundry --dir /path/to/project
24
+
25
+ # Interactive studio mode
26
+ foundry --dir /path/to/project studio
27
+
28
+ # Headless mode (CI/logs)
29
+ foundry --dir /path/to/project run --no-tui
30
+
31
+ # Self-update to latest release
32
+ foundry update
33
+ ```
34
+
35
+ ## Supported Platforms
36
+
37
+ | Platform | Architecture |
38
+ |----------|-------------|
39
+ | macOS | Apple Silicon (arm64) |
40
+ | macOS | Intel (x64) |
41
+ | Linux | x64 |
42
+ | Windows | x64 |
43
+
44
+ ## More Info
45
+
46
+ See the full documentation at [github.com/context-foundry/context-foundry](https://github.com/context-foundry/context-foundry).
package/bin/foundry ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env node
2
+
3
+ const path = require("path");
4
+ const { execFileSync } = require("child_process");
5
+ const os = require("os");
6
+
7
+ const nativeName = os.platform() === "win32" ? "foundry-native.exe" : "foundry-native";
8
+ const binaryPath = path.join(__dirname, nativeName);
9
+
10
+ try {
11
+ execFileSync(binaryPath, process.argv.slice(2), { stdio: "inherit" });
12
+ } catch (err) {
13
+ if (err.status !== undefined) {
14
+ process.exit(err.status);
15
+ }
16
+ console.error(`Failed to run foundry: ${err.message}`);
17
+ console.error("Try reinstalling: npm install -g context-foundry");
18
+ process.exit(1);
19
+ }
package/install.js ADDED
@@ -0,0 +1,185 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Downloads the correct Foundry binary from GitHub Releases during npm install.
4
+
5
+ const https = require("https");
6
+ const fs = require("fs");
7
+ const path = require("path");
8
+ const { execSync } = require("child_process");
9
+ const os = require("os");
10
+ const zlib = require("zlib");
11
+
12
+ const REPO = "context-foundry/context-foundry";
13
+
14
+ function getTarget() {
15
+ const platform = os.platform();
16
+ const arch = os.arch();
17
+
18
+ if (platform === "darwin" && arch === "arm64") return "mac-apple-silicon";
19
+ if (platform === "darwin" && arch === "x64") return "mac-intel";
20
+ if (platform === "linux" && arch === "x64") return "linux";
21
+ if (platform === "win32" && arch === "x64") return "windows";
22
+
23
+ throw new Error(`Unsupported platform: ${platform}-${arch}`);
24
+ }
25
+
26
+ function fetchLatestVersion() {
27
+ return new Promise((resolve, reject) => {
28
+ https.get(
29
+ `https://api.github.com/repos/${REPO}/releases/latest`,
30
+ { headers: { "User-Agent": "context-foundry-npm" } },
31
+ (res) => {
32
+ const chunks = [];
33
+ res.on("data", (chunk) => chunks.push(chunk));
34
+ res.on("end", () => {
35
+ try {
36
+ const data = JSON.parse(Buffer.concat(chunks).toString());
37
+ resolve(data.tag_name);
38
+ } catch (e) {
39
+ reject(new Error("Failed to parse GitHub API response"));
40
+ }
41
+ });
42
+ res.on("error", reject);
43
+ }
44
+ ).on("error", reject);
45
+ });
46
+ }
47
+
48
+ function getBinaryName() {
49
+ return os.platform() === "win32" ? "foundry.exe" : "foundry";
50
+ }
51
+
52
+ function getArchiveExt() {
53
+ return os.platform() === "win32" ? "zip" : "tar.gz";
54
+ }
55
+
56
+ function fetch(url) {
57
+ return new Promise((resolve, reject) => {
58
+ https
59
+ .get(url, { headers: { "User-Agent": "context-foundry-npm" } }, (res) => {
60
+ if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
61
+ return fetch(res.headers.location).then(resolve, reject);
62
+ }
63
+ if (res.statusCode !== 200) {
64
+ return reject(new Error(`HTTP ${res.statusCode} for ${url}`));
65
+ }
66
+ const chunks = [];
67
+ res.on("data", (chunk) => chunks.push(chunk));
68
+ res.on("end", () => resolve(Buffer.concat(chunks)));
69
+ res.on("error", reject);
70
+ })
71
+ .on("error", reject);
72
+ });
73
+ }
74
+
75
+ async function extractTarGz(buffer, destDir, binaryName) {
76
+ const tmpFile = path.join(os.tmpdir(), `foundry-${Date.now()}.tar.gz`);
77
+ fs.writeFileSync(tmpFile, buffer);
78
+ execSync(`tar xzf "${tmpFile}" -C "${destDir}"`, { stdio: "ignore" });
79
+ fs.unlinkSync(tmpFile);
80
+
81
+ const extracted = path.join(destDir, binaryName);
82
+ if (!fs.existsSync(extracted)) {
83
+ // Some archives nest in a directory
84
+ const entries = fs.readdirSync(destDir);
85
+ for (const entry of entries) {
86
+ const nested = path.join(destDir, entry, binaryName);
87
+ if (fs.existsSync(nested)) {
88
+ fs.renameSync(nested, extracted);
89
+ break;
90
+ }
91
+ }
92
+ }
93
+ return extracted;
94
+ }
95
+
96
+ async function extractZip(buffer, destDir, binaryName) {
97
+ const tmpFile = path.join(os.tmpdir(), `foundry-${Date.now()}.zip`);
98
+ fs.writeFileSync(tmpFile, buffer);
99
+
100
+ if (os.platform() === "win32") {
101
+ execSync(
102
+ `powershell -Command "Expand-Archive -Path '${tmpFile}' -DestinationPath '${destDir}' -Force"`,
103
+ { stdio: "ignore" }
104
+ );
105
+ } else {
106
+ execSync(`unzip -o "${tmpFile}" -d "${destDir}"`, { stdio: "ignore" });
107
+ }
108
+ fs.unlinkSync(tmpFile);
109
+
110
+ const extracted = path.join(destDir, binaryName);
111
+ if (!fs.existsSync(extracted)) {
112
+ const entries = fs.readdirSync(destDir);
113
+ for (const entry of entries) {
114
+ const nested = path.join(destDir, entry, binaryName);
115
+ if (fs.existsSync(nested)) {
116
+ fs.renameSync(nested, extracted);
117
+ break;
118
+ }
119
+ }
120
+ }
121
+ return extracted;
122
+ }
123
+
124
+ async function main() {
125
+ const target = getTarget();
126
+ const binaryName = getBinaryName();
127
+ const ext = getArchiveExt();
128
+ const version = await fetchLatestVersion();
129
+ const archiveName = `foundry-${target}.${ext}`;
130
+ const url = `https://github.com/${REPO}/releases/download/${version}/${archiveName}`;
131
+
132
+ const binDir = path.join(__dirname, "bin");
133
+ const nativeName = os.platform() === "win32" ? "foundry-native.exe" : "foundry-native";
134
+ const destPath = path.join(binDir, nativeName);
135
+
136
+ // Skip if binary already exists and is the right version
137
+ if (fs.existsSync(destPath)) {
138
+ try {
139
+ const existing = execSync(`"${destPath}" --version`, { encoding: "utf8" }).trim();
140
+ if (existing.includes(version.replace("v", ""))) {
141
+ console.log(`foundry ${version} already installed.`);
142
+ return;
143
+ }
144
+ } catch {
145
+ // Version check failed, re-download
146
+ }
147
+ }
148
+
149
+ console.log(`Downloading foundry ${version} for ${target}...`);
150
+
151
+ const buffer = await fetch(url);
152
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "foundry-"));
153
+
154
+ if (ext === "tar.gz") {
155
+ await extractTarGz(buffer, tmpDir, binaryName);
156
+ } else {
157
+ await extractZip(buffer, tmpDir, binaryName);
158
+ }
159
+
160
+ const extractedBinary = path.join(tmpDir, binaryName);
161
+ if (!fs.existsSync(extractedBinary)) {
162
+ throw new Error(`Binary not found after extraction in ${tmpDir}`);
163
+ }
164
+
165
+ if (!fs.existsSync(binDir)) {
166
+ fs.mkdirSync(binDir, { recursive: true });
167
+ }
168
+
169
+ fs.copyFileSync(extractedBinary, destPath);
170
+
171
+ if (os.platform() !== "win32") {
172
+ fs.chmodSync(destPath, 0o755);
173
+ }
174
+
175
+ // Clean up
176
+ fs.rmSync(tmpDir, { recursive: true, force: true });
177
+
178
+ console.log(`foundry ${version} installed successfully.`);
179
+ }
180
+
181
+ main().catch((err) => {
182
+ console.error(`Failed to install foundry: ${err.message}`);
183
+ console.error("You can install manually from: https://github.com/context-foundry/context-foundry/releases");
184
+ process.exit(1);
185
+ });
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "context-foundry",
3
+ "version": "0.7.9",
4
+ "description": "Autonomous build loop that plans, builds, reviews, and learns. npm wrapper that installs the Foundry binary.",
5
+ "author": "Context Foundry",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/context-foundry/context-foundry"
10
+ },
11
+ "homepage": "https://github.com/context-foundry/context-foundry",
12
+ "bugs": {
13
+ "url": "https://github.com/context-foundry/context-foundry/issues"
14
+ },
15
+ "keywords": [
16
+ "ai",
17
+ "agents",
18
+ "claude",
19
+ "automation",
20
+ "build-loop",
21
+ "foundry",
22
+ "context-foundry",
23
+ "tui"
24
+ ],
25
+ "bin": {
26
+ "foundry": "bin/foundry"
27
+ },
28
+ "scripts": {
29
+ "postinstall": "node install.js"
30
+ },
31
+ "os": [
32
+ "darwin",
33
+ "linux",
34
+ "win32"
35
+ ],
36
+ "cpu": [
37
+ "x64",
38
+ "arm64"
39
+ ],
40
+ "engines": {
41
+ "node": ">=16"
42
+ },
43
+ "files": [
44
+ "bin/",
45
+ "install.js",
46
+ "README.md"
47
+ ]
48
+ }