@globant/coda 1.0.0

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,105 @@
1
+ <div align="center">
2
+
3
+ # CODA
4
+
5
+ CODA is Globant's AI coding agent, powered by the Glob.AI OS platform. You
6
+ describe what you want to accomplish in plain language — CODA reads your
7
+ codebase, figures out what needs to change, and gets it done, while you stay in
8
+ control of every step.
9
+
10
+ Developed by [Globant](https://www.globant.com)
11
+
12
+ </div>
13
+
14
+ ---
15
+
16
+ ## Get Started
17
+
18
+ Learn more about [glob.ai](https://glob.ai/) and access CODA's latest
19
+ [documentation](https://docs.globant.ai/g-coda).
20
+
21
+ ### macOS & Linux
22
+
23
+ ```bash
24
+ curl -fsSL https://docs.globant.ai/en/filedownload?4622,12 | bash
25
+ ```
26
+
27
+ ### Windows (PowerShell 7)
28
+
29
+ ```powershell
30
+ irm 'https://docs.globant.ai/en/filedownload?5346,6' | iex
31
+ ```
32
+
33
+ Alternatively, you can install via npm. Note this requires Node.js, whereas the
34
+ install script above does not:
35
+
36
+ ```bash
37
+ npm i -g @globant/coda
38
+ ```
39
+
40
+ To access the application, type `coda` in your terminal and the TUI should open.
41
+ You may also run CODA in headless mode — read `coda --help` for more
42
+ information.
43
+
44
+ ### Supported platforms
45
+
46
+ | OS | Architectures |
47
+ |----|---------------|
48
+ | macOS | `arm64`, `x64` |
49
+ | Linux | `x64`, `arm64` (glibc and musl) |
50
+ | Windows | `x64` |
51
+
52
+ macOS binaries are signed + notarized; Windows binaries are Authenticode-signed.
53
+
54
+ ## Why CODA
55
+
56
+ ### Rebuilt TUI for your workflows
57
+ A rich, terminal-native experience with an **agentic edit loop**, built-in
58
+ tools, and approvals & safety baked in — so the agent acts, but you stay in
59
+ control.
60
+
61
+ ### Powered by Glob.AI OS
62
+ Access major frontier model provider and local models in one application.
63
+ Have access to your favorite models from alternative providers.
64
+
65
+ - Anthropic
66
+ - OpenAI
67
+ - Vertex-AI
68
+ - AWS Bedrock
69
+ - OpenAI Compatible Models
70
+ - Local Models via Ollama
71
+
72
+ ### Batteries included
73
+ A whole team's worth of superpowers:
74
+
75
+ - **Parallel & background subagents** — delegate exploration and validation,
76
+ like a team lead.
77
+ - **Checkpoints, time-travel & memory** — every prompt auto-snapshots the
78
+ worktree, so you can rewind anytime.
79
+
80
+ ### Extensible by design
81
+ Make it yours. Create your own **tools, commands, and hooks**, and plug into the
82
+ wider ecosystem:
83
+
84
+ - **Skills & Plugins** — load project-aware playbooks on demand.
85
+ - **MCP servers** — connect external tools and data sources.
86
+ - **Hooks & Extensions** — customize behavior at every lifecycle step.
87
+ - **Workflows** — orchestrate fleets of subagents through deterministic,
88
+ multi-step pipelines that run themselves.
89
+
90
+ ## Terms & licensing
91
+
92
+ Use of CODA is governed by Globant's terms of use. By installing or using this
93
+ package you agree to those terms:
94
+
95
+ **https://www.globant.com/globai-os/terms-of-use**
96
+
97
+ ---
98
+
99
+ <div align="center">
100
+
101
+ Your codebase, your terminal, **your AI pair.**
102
+
103
+ Frontier coding agent · by **Globant**
104
+
105
+ </div>
package/bin/coda.exe ADDED
@@ -0,0 +1,4 @@
1
+ echo "Error: coda native binary not installed." >&2
2
+ echo "postinstall may have been skipped (--ignore-scripts / --omit=optional)." >&2
3
+ echo "Run: node node_modules/@globant/coda/install.cjs (or reinstall)" >&2
4
+ exit 1
@@ -0,0 +1,113 @@
1
+ #!/usr/bin/env node
2
+ // Fallback launcher for @globant/coda. Used ONLY when the postinstall
3
+ // (install.cjs) did not run — e.g. `npm install --ignore-scripts`. Resolves the
4
+ // matching native binary from the installed optional platform package and
5
+ // spawns it, inheriting stdio and propagating exit status / signals.
6
+ //
7
+ // NOTE: the PLATFORMS map + detection here intentionally duplicate install.cjs
8
+ // (and a simpler subset of packages/cli/src/update/platform-detect.ts). The npm
9
+ // path never selects baseline variants — npm ships the AVX2 default.
10
+ const { spawnSync } = require("node:child_process");
11
+ const { existsSync } = require("node:fs");
12
+ const { arch } = require("node:os");
13
+ const path = require("node:path");
14
+
15
+ const PACKAGE_PREFIX = "@globant/coda";
16
+ const WRAPPER_NAME = require("./package.json").name;
17
+
18
+ const PLATFORMS = {
19
+ "darwin-arm64": { pkg: `${PACKAGE_PREFIX}-darwin-arm64`, bin: "coda" },
20
+ "darwin-x64": { pkg: `${PACKAGE_PREFIX}-darwin-x64`, bin: "coda" },
21
+ "linux-arm64": { pkg: `${PACKAGE_PREFIX}-linux-arm64`, bin: "coda" },
22
+ "linux-x64": { pkg: `${PACKAGE_PREFIX}-linux-x64`, bin: "coda" },
23
+ "linux-arm64-musl": {
24
+ pkg: `${PACKAGE_PREFIX}-linux-arm64-musl`,
25
+ bin: "coda",
26
+ },
27
+ "linux-x64-musl": { pkg: `${PACKAGE_PREFIX}-linux-x64-musl`, bin: "coda" },
28
+ "windows-arm64": { pkg: `${PACKAGE_PREFIX}-windows-arm64`, bin: "coda.exe" },
29
+ "windows-x64": { pkg: `${PACKAGE_PREFIX}-windows-x64`, bin: "coda.exe" },
30
+ };
31
+
32
+ function detectMusl() {
33
+ if (process.platform !== "linux") return false;
34
+ const report =
35
+ typeof process.report?.getReport === "function"
36
+ ? process.report.getReport()
37
+ : null;
38
+ return report != null && report.header?.glibcVersionRuntime === undefined;
39
+ }
40
+
41
+ function platformKey() {
42
+ let cpu = arch();
43
+ if (process.platform === "win32") return `windows-${cpu}`;
44
+ if (process.platform === "linux") {
45
+ return `linux-${cpu}${detectMusl() ? "-musl" : ""}`;
46
+ }
47
+ if (process.platform === "darwin") {
48
+ if (cpu === "x64") {
49
+ const result = spawnSync("sysctl", ["-n", "sysctl.proc_translated"], {
50
+ encoding: "utf8",
51
+ });
52
+ if (result.stdout?.trim() === "1") cpu = "arm64";
53
+ }
54
+ return `darwin-${cpu}`;
55
+ }
56
+ return `${process.platform}-${cpu}`;
57
+ }
58
+
59
+ function resolvePlatform() {
60
+ const info = PLATFORMS[platformKey()];
61
+ if (!info) {
62
+ throw new Error(`Unsupported platform: ${platformKey()}`);
63
+ }
64
+ const pkgDir = path.dirname(require.resolve(`${info.pkg}/package.json`));
65
+ return {
66
+ binary: path.join(pkgDir, info.bin),
67
+ libDir: path.join(pkgDir, "lib"),
68
+ assetsDir: path.join(pkgDir, "assets"),
69
+ };
70
+ }
71
+
72
+ function main() {
73
+ let resolved;
74
+ try {
75
+ resolved = resolvePlatform();
76
+ } catch (err) {
77
+ console.error(
78
+ `[${WRAPPER_NAME}] Could not locate native binary: ${err.message}`,
79
+ );
80
+ process.exit(1);
81
+ }
82
+ // The binary runs from the platform package root (lib/ and assets/ are
83
+ // siblings, not ../lib and ../assets), so point the sidecar + asset resolvers
84
+ // at the right dirs for this layout.
85
+ const env = { ...process.env };
86
+ if (existsSync(resolved.libDir)) {
87
+ env.CODA_SIDECAR_LIB_DIR = resolved.libDir;
88
+ }
89
+ if (existsSync(resolved.assetsDir)) {
90
+ env.CODA_ASSETS_DIR = resolved.assetsDir;
91
+ }
92
+ const result = spawnSync(resolved.binary, process.argv.slice(2), {
93
+ stdio: "inherit",
94
+ env,
95
+ });
96
+ if (result.error) {
97
+ console.error(
98
+ `[${WRAPPER_NAME}] Failed to launch: ${result.error.message}`,
99
+ );
100
+ process.exit(1);
101
+ }
102
+ if (typeof result.status === "number") {
103
+ process.exit(result.status);
104
+ }
105
+ if (result.signal) {
106
+ // Mimic the shell convention: 128 + signal number.
107
+ const signals = { SIGINT: 2, SIGTERM: 15, SIGKILL: 9, SIGHUP: 1 };
108
+ process.exit(128 + (signals[result.signal] ?? 0));
109
+ }
110
+ process.exit(0);
111
+ }
112
+
113
+ main();
package/install.cjs ADDED
@@ -0,0 +1,208 @@
1
+ #!/usr/bin/env node
2
+ // Postinstall for @globant/coda. Detects the platform, finds the matching
3
+ // native package from optionalDependencies, and hardlinks (copy fallback) its
4
+ // binary over bin/coda.exe so `coda` execs natively with no resident Node
5
+ // process. Mirrors @anthropic-ai/claude-code's install.cjs, adapted to our
6
+ // `windows` package naming and 8-package optional set.
7
+ //
8
+ // NOTE: this platform detection is a deliberate (simpler) duplicate of the
9
+ // TypeScript logic in packages/cli/src/update/platform-detect.ts. The npm path
10
+ // never selects baseline (non-AVX2) variants — npm ships the AVX2 default — so
11
+ // this file only needs glibc/musl + arch + Rosetta handling.
12
+ const { spawnSync } = require("node:child_process");
13
+ const {
14
+ linkSync,
15
+ copyFileSync,
16
+ unlinkSync,
17
+ chmodSync,
18
+ cpSync,
19
+ existsSync,
20
+ rmSync,
21
+ } = require("node:fs");
22
+ const { arch } = require("node:os");
23
+ const path = require("node:path");
24
+
25
+ const PACKAGE_PREFIX = "@globant/coda";
26
+ // Resolved at install time from the published launcher package. Falls back to
27
+ // the package name when `./package.json` is absent (e.g. unit tests that import
28
+ // this file only for its helpers, before the launcher is staged).
29
+ let WRAPPER_NAME = PACKAGE_PREFIX;
30
+ try {
31
+ WRAPPER_NAME = require("./package.json").name;
32
+ } catch {
33
+ /* keep fallback */
34
+ }
35
+
36
+ // key → { pkg, bin }. Keys use OUR `windows` naming; resolution uses
37
+ // process.platform (`win32`) mapped to `windows`.
38
+ const PLATFORMS = {
39
+ "darwin-arm64": { pkg: `${PACKAGE_PREFIX}-darwin-arm64`, bin: "coda" },
40
+ "darwin-x64": { pkg: `${PACKAGE_PREFIX}-darwin-x64`, bin: "coda" },
41
+ "linux-arm64": { pkg: `${PACKAGE_PREFIX}-linux-arm64`, bin: "coda" },
42
+ "linux-x64": { pkg: `${PACKAGE_PREFIX}-linux-x64`, bin: "coda" },
43
+ "linux-arm64-musl": {
44
+ pkg: `${PACKAGE_PREFIX}-linux-arm64-musl`,
45
+ bin: "coda",
46
+ },
47
+ "linux-x64-musl": { pkg: `${PACKAGE_PREFIX}-linux-x64-musl`, bin: "coda" },
48
+ "windows-arm64": { pkg: `${PACKAGE_PREFIX}-windows-arm64`, bin: "coda.exe" },
49
+ "windows-x64": { pkg: `${PACKAGE_PREFIX}-windows-x64`, bin: "coda.exe" },
50
+ };
51
+
52
+ function detectMusl() {
53
+ if (process.platform !== "linux") return false;
54
+ const report =
55
+ typeof process.report?.getReport === "function"
56
+ ? process.report.getReport()
57
+ : null;
58
+ return report != null && report.header?.glibcVersionRuntime === undefined;
59
+ }
60
+
61
+ function platformKey() {
62
+ let cpu = arch();
63
+ if (process.platform === "win32") return `windows-${cpu}`;
64
+ if (process.platform === "linux") {
65
+ return `linux-${cpu}${detectMusl() ? "-musl" : ""}`;
66
+ }
67
+ if (process.platform === "darwin") {
68
+ if (cpu === "x64") {
69
+ const result = spawnSync("sysctl", ["-n", "sysctl.proc_translated"], {
70
+ encoding: "utf8",
71
+ });
72
+ // Rosetta → prefer the arm64 build (the darwin-x64 build needs AVX,
73
+ // which Rosetta does not emulate).
74
+ if (result.stdout?.trim() === "1") cpu = "arm64";
75
+ }
76
+ return `darwin-${cpu}`;
77
+ }
78
+ return `${process.platform}-${cpu}`;
79
+ }
80
+
81
+ function placeBinary(src, dest) {
82
+ try {
83
+ linkSync(src, dest);
84
+ } catch (err) {
85
+ if (err.code === "EEXIST") {
86
+ unlinkSync(dest);
87
+ try {
88
+ linkSync(src, dest);
89
+ } catch {
90
+ copyFileSync(src, dest);
91
+ }
92
+ } else if (err.code === "EXDEV" || err.code === "EPERM") {
93
+ copyFileSync(src, dest);
94
+ } else {
95
+ throw err;
96
+ }
97
+ }
98
+ if (process.platform !== "win32") chmodSync(dest, 0o755);
99
+ }
100
+
101
+ // Copies the platform package's `lib/` sidecar tree (keytar, opentui, ripgrep)
102
+ // into the launcher root so the compiled binary finds it at `../lib/<name>`,
103
+ // matching the script-installer layout. Idempotent and non-fatal: a failure
104
+ // degrades sidecars exactly as before (binary still runs). `libParent` defaults
105
+ // to the launcher dir; tests pass a temp dir.
106
+ function stageSidecars(platformPkgDir, libParent = __dirname) {
107
+ const libSrc = path.join(platformPkgDir, "lib");
108
+ if (!existsSync(libSrc)) return; // older platform pkg without sidecars
109
+ const libDest = path.join(libParent, "lib");
110
+ // Remove any stale tree from a previous install so re-runs are clean.
111
+ if (existsSync(libDest)) {
112
+ rmSync(libDest, { recursive: true, force: true });
113
+ }
114
+ cpSync(libSrc, libDest, { recursive: true });
115
+ // CI artifact round-trips / cpSync edge cases can drop the exec bit; the
116
+ // bundled ripgrep binary must stay executable on POSIX (keytar.node and
117
+ // libopentui.* are dlopen'd, not exec'd, so they need read perms only).
118
+ if (process.platform !== "win32") {
119
+ const rg = path.join(libDest, "ripgrep", "rg");
120
+ if (existsSync(rg)) chmodSync(rg, 0o755);
121
+ }
122
+ }
123
+
124
+ // Copies the platform package's `assets/` tree (docs, agents, skills) into the
125
+ // launcher root so the compiled binary finds it at `../assets` (the
126
+ // `bin/coda → ../assets` probe in core's resolveAssetsDir), matching the
127
+ // script-installer layout. Idempotent and non-fatal: a failure degrades to no
128
+ // synced docs/agents/skills (binary still runs). `assetsParent` defaults to the
129
+ // launcher dir; tests pass a temp dir.
130
+ function stageAssets(platformPkgDir, assetsParent = __dirname) {
131
+ const assetsSrc = path.join(platformPkgDir, "assets");
132
+ if (!existsSync(assetsSrc)) return; // older platform pkg without assets
133
+ const assetsDest = path.join(assetsParent, "assets");
134
+ // Remove any stale tree from a previous install so re-runs are clean.
135
+ if (existsSync(assetsDest)) {
136
+ rmSync(assetsDest, { recursive: true, force: true });
137
+ }
138
+ cpSync(assetsSrc, assetsDest, { recursive: true });
139
+ }
140
+
141
+ function main() {
142
+ const key = platformKey();
143
+ const info = PLATFORMS[key];
144
+ const optional = require("./package.json").optionalDependencies || {};
145
+ if (!info || !optional[info.pkg]) {
146
+ console.error(
147
+ `[${WRAPPER_NAME}] No native binary for ${key} on this channel. ` +
148
+ `Available: ${Object.keys(optional)
149
+ .map((p) => p.replace(`${PACKAGE_PREFIX}-`, ""))
150
+ .join(", ")}`,
151
+ );
152
+ return; // leave stub; `coda` will print guidance
153
+ }
154
+ let platformPkgDir;
155
+ try {
156
+ platformPkgDir = path.dirname(require.resolve(`${info.pkg}/package.json`));
157
+ } catch {
158
+ console.error(
159
+ `[${WRAPPER_NAME}] Native package "${info.pkg}" not installed ` +
160
+ `(--omit=optional or download failed). Fallback: node ${path.join(
161
+ __dirname,
162
+ "cli-wrapper.cjs",
163
+ )}`,
164
+ );
165
+ return;
166
+ }
167
+
168
+ const src = path.join(platformPkgDir, info.bin);
169
+ try {
170
+ placeBinary(src, path.join(__dirname, "bin", "coda.exe"));
171
+ } catch (err) {
172
+ console.error(`[${WRAPPER_NAME}] Failed to place binary: ${err.message}`);
173
+ process.exitCode = 1;
174
+ return; // no point staging sidecars if the binary failed
175
+ }
176
+
177
+ // Stage keytar/opentui/ripgrep so auth + bundled tools work on npm installs.
178
+ try {
179
+ stageSidecars(platformPkgDir);
180
+ } catch (err) {
181
+ // Non-fatal: binary runs; sidecars degrade (auth → file storage,
182
+ // ripgrep → PATH rg, opentui → default rendering). Surface it so the
183
+ // keyring regression is not silent.
184
+ console.error(
185
+ `[${WRAPPER_NAME}] Failed to stage native sidecars ` +
186
+ `(OS keyring / bundled ripgrep may be unavailable): ${err.message}`,
187
+ );
188
+ }
189
+
190
+ // Stage docs/agents/skills so syncBuiltinAssets() populates ~/.coda on npm.
191
+ try {
192
+ stageAssets(platformPkgDir);
193
+ } catch (err) {
194
+ // Non-fatal: binary runs; the built-in docs/agents/skills simply are not
195
+ // synced to ~/.coda. Surface it so the regression is not silent.
196
+ console.error(
197
+ `[${WRAPPER_NAME}] Failed to stage builtin assets ` +
198
+ `(docs/agents/skills may be unavailable): ${err.message}`,
199
+ );
200
+ }
201
+ }
202
+
203
+ // Run only when executed directly (npm postinstall), not when required by tests.
204
+ if (require.main === module) {
205
+ main();
206
+ }
207
+
208
+ module.exports = { stageSidecars, stageAssets, platformKey, placeBinary };
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@globant/coda",
3
+ "version": "1.0.0",
4
+ "description": "Coda CLI — agentic coding assistant (native binary launcher)",
5
+ "bin": {
6
+ "coda": "bin/coda.exe"
7
+ },
8
+ "scripts": {
9
+ "postinstall": "node install.cjs"
10
+ },
11
+ "optionalDependencies": {
12
+ "@globant/coda-darwin-arm64": "1.0.0",
13
+ "@globant/coda-linux-arm64": "1.0.0",
14
+ "@globant/coda-linux-arm64-musl": "1.0.0",
15
+ "@globant/coda-linux-x64-musl": "1.0.0",
16
+ "@globant/coda-linux-x64": "1.0.0",
17
+ "@globant/coda-darwin-x64": "1.0.0",
18
+ "@globant/coda-windows-arm64": "1.0.0",
19
+ "@globant/coda-windows-x64": "1.0.0"
20
+ },
21
+ "files": [
22
+ "bin",
23
+ "lib",
24
+ "assets",
25
+ "install.cjs",
26
+ "cli-wrapper.cjs",
27
+ "README.md"
28
+ ],
29
+ "license": "SEE LICENSE IN README.md",
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "https://github.com/5G-AGE009-HZ/g-coda.git",
33
+ "directory": "packages/cli"
34
+ },
35
+ "publishConfig": {
36
+ "registry": "https://registry.npmjs.org/",
37
+ "access": "public"
38
+ }
39
+ }