@cerulin/chell 0.2.5

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.
Files changed (53) hide show
  1. package/README.md +75 -0
  2. package/bin/chell-mcp.mjs +33 -0
  3. package/bin/chell.mjs +37 -0
  4. package/dist/codex/chellMcpStdioBridge.cjs +80 -0
  5. package/dist/codex/chellMcpStdioBridge.d.cts +2 -0
  6. package/dist/codex/chellMcpStdioBridge.d.mts +2 -0
  7. package/dist/codex/chellMcpStdioBridge.mjs +78 -0
  8. package/dist/index-B443j7JQ.mjs +6714 -0
  9. package/dist/index-qS668VWY.cjs +6730 -0
  10. package/dist/index.cjs +42 -0
  11. package/dist/index.d.cts +1 -0
  12. package/dist/index.d.mts +1 -0
  13. package/dist/index.mjs +39 -0
  14. package/dist/lib.cjs +32 -0
  15. package/dist/lib.d.cts +891 -0
  16. package/dist/lib.d.mts +891 -0
  17. package/dist/lib.mjs +22 -0
  18. package/dist/runCodex-DHtm7TWT.cjs +2020 -0
  19. package/dist/runCodex-DLbjgnc4.mjs +2017 -0
  20. package/dist/runGemini-C03RUmvr.mjs +788 -0
  21. package/dist/runGemini-fdb5jxAA.cjs +791 -0
  22. package/dist/types-DBjv5m4J.cjs +2499 -0
  23. package/dist/types-fM_iFuNp.mjs +2452 -0
  24. package/package.json +131 -0
  25. package/scripts/claude_local_launcher.cjs +98 -0
  26. package/scripts/claude_remote_launcher.cjs +13 -0
  27. package/scripts/codex_local_launcher.cjs +155 -0
  28. package/scripts/codex_preload.cjs +56 -0
  29. package/scripts/codex_remote_launcher.cjs +129 -0
  30. package/scripts/obfuscate-dist.mjs +73 -0
  31. package/scripts/pack-chell.cjs +32 -0
  32. package/scripts/publish-scoped.ps1 +58 -0
  33. package/scripts/ripgrep_launcher.cjs +33 -0
  34. package/scripts/unpack-tools.cjs +163 -0
  35. package/tools/archives/difftastic-LICENSE +21 -0
  36. package/tools/archives/difftastic-arm64-darwin.tar.gz +0 -0
  37. package/tools/archives/difftastic-arm64-linux.tar.gz +0 -0
  38. package/tools/archives/difftastic-x64-darwin.tar.gz +0 -0
  39. package/tools/archives/difftastic-x64-linux.tar.gz +0 -0
  40. package/tools/archives/difftastic-x64-win32.tar.gz +0 -0
  41. package/tools/archives/ripgrep-LICENSE +3 -0
  42. package/tools/archives/ripgrep-arm64-darwin.tar.gz +0 -0
  43. package/tools/archives/ripgrep-arm64-linux.tar.gz +0 -0
  44. package/tools/archives/ripgrep-x64-darwin.tar.gz +0 -0
  45. package/tools/archives/ripgrep-x64-linux.tar.gz +0 -0
  46. package/tools/archives/ripgrep-x64-win32.tar.gz +0 -0
  47. package/tools/licenses/difftastic-LICENSE +21 -0
  48. package/tools/licenses/ripgrep-LICENSE +3 -0
  49. package/tools/unpacked/difft +0 -0
  50. package/tools/unpacked/difft.exe +0 -0
  51. package/tools/unpacked/rg +0 -0
  52. package/tools/unpacked/rg.exe +0 -0
  53. package/tools/unpacked/ripgrep.node +0 -0
package/package.json ADDED
@@ -0,0 +1,131 @@
1
+ {
2
+ "name": "@cerulin/chell",
3
+ "version": "0.2.5",
4
+ "description": "Mobile and Web client for Claude Code and Codex",
5
+ "author": "Cerulin",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "homepage": "https://github.com/cerulin/chell-cli",
9
+ "bugs": "https://github.com/cerulin/chell-cli/issues",
10
+ "repository": "cerulin/chell-cli",
11
+ "bin": {
12
+ "happy": "./bin/chell.mjs",
13
+ "happy-mcp": "./bin/chell-mcp.mjs",
14
+ "chell": "./bin/chell.mjs",
15
+ "chell-mcp": "./bin/chell-mcp.mjs"
16
+ },
17
+ "main": "./dist/index.cjs",
18
+ "module": "./dist/index.mjs",
19
+ "types": "./dist/index.d.cts",
20
+ "exports": {
21
+ ".": {
22
+ "require": {
23
+ "types": "./dist/index.d.cts",
24
+ "default": "./dist/index.cjs"
25
+ },
26
+ "import": {
27
+ "types": "./dist/index.d.mts",
28
+ "default": "./dist/index.mjs"
29
+ }
30
+ },
31
+ "./lib": {
32
+ "require": {
33
+ "types": "./dist/lib.d.cts",
34
+ "default": "./dist/lib.cjs"
35
+ },
36
+ "import": {
37
+ "types": "./dist/lib.d.mts",
38
+ "default": "./dist/lib.mjs"
39
+ }
40
+ },
41
+ "./codex/chellMcpStdioBridge": {
42
+ "require": {
43
+ "types": "./dist/codex/chellMcpStdioBridge.d.cts",
44
+ "default": "./dist/codex/chellMcpStdioBridge.cjs"
45
+ },
46
+ "import": {
47
+ "types": "./dist/codex/chellMcpStdioBridge.d.mts",
48
+ "default": "./dist/codex/chellMcpStdioBridge.mjs"
49
+ }
50
+ }
51
+ },
52
+ "files": [
53
+ "dist",
54
+ "bin",
55
+ "scripts",
56
+ "tools",
57
+ "package.json"
58
+ ],
59
+ "scripts": {
60
+ "why do we need to build before running tests / dev?": "We need the binary to be built so we run daemon commands which directly run the binary - we don't want them to go out of sync or have custom spawn logic depending how we started happy",
61
+ "typecheck": "tsc --noEmit",
62
+ "build": "shx rm -rf dist && npx tsc --noEmit && pkgroll",
63
+ "obfuscate": "shx rm -rf dist.obf && javascript-obfuscator dist --output dist.obf --compact true --self-defending false --control-flow-flattening true --string-array true --string-array-encoding base64 --identifier-names-generator mangled && shx cp -r dist/*.d.* dist.obf 2>nul && shx rm -rf dist && shx mv dist.obf dist",
64
+ "build:obf": "yarn build && yarn obfuscate",
65
+ "pack:chell": "node scripts/pack-chell.cjs",
66
+ "test": "yarn build && tsx --env-file .env.integration-test node_modules/.bin/vitest run",
67
+ "start": "yarn build && ./bin/chell.mjs",
68
+ "dev": "yarn build && tsx --env-file .env.dev src/index.ts",
69
+ "dev:local-server": "yarn build && tsx --env-file .env.dev-local-server src/index.ts",
70
+ "dev:integration-test-env": "yarn build && tsx --env-file .env.integration-test src/index.ts",
71
+ "prepublishOnly": "yarn build && yarn test",
72
+ "release": "release-it",
73
+ "postinstall": "node scripts/unpack-tools.cjs"
74
+ },
75
+ "dependencies": {
76
+ "@anthropic-ai/claude-code": "^2.0.14",
77
+ "@anthropic-ai/sdk": "^0.56.0",
78
+ "@modelcontextprotocol/sdk": "^1.15.1",
79
+ "@openai/codex": "^0.50.0",
80
+ "@stablelib/base64": "^2.0.1",
81
+ "@types/cross-spawn": "^6.0.6",
82
+ "@types/http-proxy": "^1.17.16",
83
+ "@types/ps-list": "^6.2.1",
84
+ "@types/qrcode-terminal": "^0.12.2",
85
+ "@types/react": "^19.1.9",
86
+ "axios": "^1.10.0",
87
+ "chalk": "^5.4.1",
88
+ "chell": "^1.0.4",
89
+ "cross-spawn": "^7.0.6",
90
+ "expo-server-sdk": "^3.15.0",
91
+ "fastify": "^5.5.0",
92
+ "fastify-type-provider-zod": "4.0.2",
93
+ "http-proxy": "^1.18.1",
94
+ "http-proxy-middleware": "^3.0.5",
95
+ "ink": "^6.1.0",
96
+ "node-pty": "1.0.0",
97
+ "open": "^10.2.0",
98
+ "ps-list": "^8.1.1",
99
+ "qrcode-terminal": "^0.12.0",
100
+ "react": "^19.1.1",
101
+ "socket.io-client": "^4.8.1",
102
+ "tar": "^7.4.3",
103
+ "tweetnacl": "^1.0.3",
104
+ "zod": "^3.23.8"
105
+ },
106
+ "devDependencies": {
107
+ "@eslint/compat": "^1",
108
+ "@types/node": ">=20",
109
+ "cross-env": "^10.0.0",
110
+ "dotenv": "^16.6.1",
111
+ "eslint": "^9",
112
+ "eslint-config-prettier": "^10",
113
+ "javascript-obfuscator": "4",
114
+ "pkgroll": "^2.14.2",
115
+ "release-it": "^19.0.4",
116
+ "shx": "^0.3.3",
117
+ "ts-node": "^10",
118
+ "tsx": "^4.20.3",
119
+ "typescript": "^5",
120
+ "vitest": "^3.2.4"
121
+ },
122
+ "resolutions": {
123
+ "whatwg-url": "14.2.0",
124
+ "parse-path": "7.0.3",
125
+ "@types/parse-path": "7.0.3"
126
+ },
127
+ "publishConfig": {
128
+ "registry": "https://registry.npmjs.org"
129
+ },
130
+ "packageManager": "yarn@1.22.22"
131
+ }
@@ -0,0 +1,98 @@
1
+ const crypto = require('crypto');
2
+ const fs = require('fs');
3
+
4
+ // Disable autoupdater (never works really)
5
+ process.env.DISABLE_AUTOUPDATER = '1';
6
+
7
+ // Helper to write JSON messages to fd 3
8
+ function writeMessage(message) {
9
+ try {
10
+ fs.writeSync(3, JSON.stringify(message) + '\n');
11
+ } catch (err) {
12
+ // fd 3 not available, ignore
13
+ }
14
+ }
15
+
16
+ // Intercept crypto.randomUUID
17
+ const originalRandomUUID = crypto.randomUUID;
18
+ Object.defineProperty(global, 'crypto', {
19
+ configurable: true,
20
+ enumerable: true,
21
+ get() {
22
+ return {
23
+ randomUUID: () => {
24
+ const uuid = originalRandomUUID();
25
+ writeMessage({ type: 'uuid', value: uuid });
26
+ return uuid;
27
+ }
28
+ };
29
+ }
30
+ });
31
+ Object.defineProperty(crypto, 'randomUUID', {
32
+ configurable: true,
33
+ enumerable: true,
34
+ get() {
35
+ return () => {
36
+ const uuid = originalRandomUUID();
37
+ writeMessage({ type: 'uuid', value: uuid });
38
+ return uuid;
39
+ }
40
+ }
41
+ });
42
+
43
+ // Intercept fetch to track activity
44
+ const originalFetch = global.fetch;
45
+ let fetchCounter = 0;
46
+
47
+ global.fetch = function(...args) {
48
+ const id = ++fetchCounter;
49
+ const url = typeof args[0] === 'string' ? args[0] : args[0]?.url || '';
50
+ const method = args[1]?.method || 'GET';
51
+
52
+ // Parse URL for privacy
53
+ let hostname = '';
54
+ let path = '';
55
+ try {
56
+ const urlObj = new URL(url, 'http://localhost');
57
+ hostname = urlObj.hostname;
58
+ path = urlObj.pathname;
59
+ } catch (e) {
60
+ // If URL parsing fails, use defaults
61
+ hostname = 'unknown';
62
+ path = url;
63
+ }
64
+
65
+ // Send fetch start event
66
+ writeMessage({
67
+ type: 'fetch-start',
68
+ id,
69
+ hostname,
70
+ path,
71
+ method,
72
+ timestamp: Date.now()
73
+ });
74
+
75
+ // Execute the original fetch immediately
76
+ const fetchPromise = originalFetch(...args);
77
+
78
+ // Attach handlers to send fetch end event
79
+ const sendEnd = () => {
80
+ writeMessage({
81
+ type: 'fetch-end',
82
+ id,
83
+ timestamp: Date.now()
84
+ });
85
+ };
86
+
87
+ // Send end event on both success and failure
88
+ fetchPromise.then(sendEnd, sendEnd);
89
+
90
+ // Return the original promise unchanged
91
+ return fetchPromise;
92
+ };
93
+
94
+ // Preserve fetch properties
95
+ Object.defineProperty(global.fetch, 'name', { value: 'fetch' });
96
+ Object.defineProperty(global.fetch, 'length', { value: originalFetch.length });
97
+
98
+ import('@anthropic-ai/claude-code/cli.js')
@@ -0,0 +1,13 @@
1
+ // Intercept setTimeout for the Claude Code SDK
2
+ const originalSetTimeout = global.setTimeout;
3
+
4
+ global.setTimeout = function(callback, delay, ...args) {
5
+ // Just wrap and call the original setTimeout
6
+ return originalSetTimeout(callback, delay, ...args);
7
+ };
8
+
9
+ // Preserve setTimeout properties
10
+ Object.defineProperty(global.setTimeout, 'name', { value: 'setTimeout' });
11
+ Object.defineProperty(global.setTimeout, 'length', { value: originalSetTimeout.length });
12
+
13
+ import('@anthropic-ai/claude-code/cli.js')
@@ -0,0 +1,155 @@
1
+ const crypto = require('crypto');
2
+ const fs = require('fs');
3
+
4
+ // Disable autoupdater if Codex has one
5
+ process.env.DISABLE_AUTOUPDATER = '1';
6
+
7
+ // Helper to write JSON messages to fd 3
8
+ function writeMessage(message) {
9
+ try {
10
+ fs.writeSync(3, JSON.stringify(message) + '\n');
11
+ } catch (err) {
12
+ // fd 3 not available, ignore
13
+ }
14
+ }
15
+
16
+ // Intercept crypto.randomUUID
17
+ const originalRandomUUID = crypto.randomUUID;
18
+ Object.defineProperty(global, 'crypto', {
19
+ configurable: true,
20
+ enumerable: true,
21
+ get() {
22
+ return {
23
+ randomUUID: () => {
24
+ const uuid = originalRandomUUID();
25
+ writeMessage({ type: 'uuid', value: uuid });
26
+ return uuid;
27
+ }
28
+ };
29
+ }
30
+ });
31
+ Object.defineProperty(crypto, 'randomUUID', {
32
+ configurable: true,
33
+ enumerable: true,
34
+ get() {
35
+ return () => {
36
+ const uuid = originalRandomUUID();
37
+ writeMessage({ type: 'uuid', value: uuid });
38
+ return uuid;
39
+ }
40
+ }
41
+ });
42
+
43
+ // Intercept fetch to track activity
44
+ const originalFetch = global.fetch;
45
+ let fetchCounter = 0;
46
+
47
+ global.fetch = function(...args) {
48
+ const id = ++fetchCounter;
49
+ const url = typeof args[0] === 'string' ? args[0] : args[0]?.url || '';
50
+ const method = args[1]?.method || 'GET';
51
+
52
+ // Parse URL for privacy
53
+ let hostname = '';
54
+ let path = '';
55
+ try {
56
+ const urlObj = new URL(url, 'http://localhost');
57
+ hostname = urlObj.hostname;
58
+ path = urlObj.pathname;
59
+ } catch (e) {
60
+ // If URL parsing fails, use defaults
61
+ hostname = 'unknown';
62
+ path = url;
63
+ }
64
+
65
+ // Send fetch start event
66
+ writeMessage({
67
+ type: 'fetch-start',
68
+ id,
69
+ hostname,
70
+ path,
71
+ method,
72
+ timestamp: Date.now()
73
+ });
74
+
75
+ // Execute the original fetch immediately
76
+ const fetchPromise = originalFetch(...args);
77
+
78
+ // Attach handlers to send fetch end event
79
+ const sendEnd = () => {
80
+ writeMessage({
81
+ type: 'fetch-end',
82
+ id,
83
+ timestamp: Date.now()
84
+ });
85
+ };
86
+
87
+ // Send end event on both success and failure
88
+ fetchPromise.then(sendEnd, sendEnd);
89
+
90
+ // Return the original promise unchanged
91
+ return fetchPromise;
92
+ };
93
+
94
+ // Preserve fetch properties
95
+ Object.defineProperty(global.fetch, 'name', { value: 'fetch' });
96
+ Object.defineProperty(global.fetch, 'length', { value: originalFetch.length });
97
+
98
+ // Log startup to fd3
99
+ writeMessage({ type: 'launcher_start', timestamp: Date.now() });
100
+
101
+ // Import Codex CLI
102
+ // Try different entry points based on how OpenAI packages Codex
103
+ (async () => {
104
+ try {
105
+ // Try with .js extension first (Node ESM requires explicit extensions)
106
+ writeMessage({ type: 'import_attempt', path: '@openai/codex/bin/codex.js' });
107
+ await import('@openai/codex/bin/codex.js');
108
+ writeMessage({ type: 'import_success', path: '@openai/codex/bin/codex.js' });
109
+ } catch (err1) {
110
+ try {
111
+ // Try CLI entry point
112
+ writeMessage({ type: 'import_attempt', path: '@openai/codex/cli.js' });
113
+ await import('@openai/codex/cli.js');
114
+ writeMessage({ type: 'import_success', path: '@openai/codex/cli.js' });
115
+ } catch (err2) {
116
+ try {
117
+ // Try main export
118
+ writeMessage({ type: 'import_attempt', path: '@openai/codex' });
119
+ await import('@openai/codex');
120
+ writeMessage({ type: 'import_success', path: '@openai/codex' });
121
+ } catch (err3) {
122
+ try {
123
+ // Try bin without extension (for older Node versions)
124
+ writeMessage({ type: 'import_attempt', path: '@openai/codex/bin/codex' });
125
+ await import('@openai/codex/bin/codex');
126
+ writeMessage({ type: 'import_success', path: '@openai/codex/bin/codex' });
127
+ } catch (err4) {
128
+ try {
129
+ // Try dist/bin/codex.js (common build output location)
130
+ writeMessage({ type: 'import_attempt', path: '@openai/codex/dist/bin/codex.js' });
131
+ await import('@openai/codex/dist/bin/codex.js');
132
+ writeMessage({ type: 'import_success', path: '@openai/codex/dist/bin/codex.js' });
133
+ } catch (err5) {
134
+ writeMessage({ type: 'import_failed', error: err5.message });
135
+ console.error('❌ Failed to load Codex CLI from any known entry point');
136
+ console.error('Attempted paths:');
137
+ console.error(' - @openai/codex/bin/codex.js');
138
+ console.error(' - @openai/codex/cli.js');
139
+ console.error(' - @openai/codex');
140
+ console.error(' - @openai/codex/bin/codex');
141
+ console.error(' - @openai/codex/dist/bin/codex.js');
142
+ console.error('');
143
+ console.error('Last error:', err5.message);
144
+ console.error('');
145
+ console.error('This is likely a bundling issue. The @openai/codex package should be');
146
+ console.error('included in chell dependencies and bundled during npm pack.');
147
+ process.exit(1);
148
+ }
149
+ }
150
+ }
151
+ }
152
+ }
153
+ })();
154
+
155
+
@@ -0,0 +1,56 @@
1
+ const fs = require('fs');
2
+ const crypto = require('crypto');
3
+
4
+ // Helper to write JSON messages to fd 3
5
+ function writeMessage(message) {
6
+ try {
7
+ fs.writeSync(3, JSON.stringify(message) + '\n');
8
+ } catch (_) {
9
+ // fd3 not available; ignore
10
+ }
11
+ }
12
+
13
+ // Log preload activation
14
+ writeMessage({ type: 'launcher_start', timestamp: Date.now(), preload: true });
15
+
16
+ // Intercept crypto.randomUUID to surface session UUIDs
17
+ try {
18
+ const originalRandomUUID = crypto.randomUUID;
19
+ Object.defineProperty(crypto, 'randomUUID', {
20
+ configurable: true,
21
+ enumerable: true,
22
+ value: () => {
23
+ const uuid = originalRandomUUID();
24
+ writeMessage({ type: 'uuid', value: uuid });
25
+ return uuid;
26
+ }
27
+ });
28
+ } catch (_) {}
29
+
30
+ // Intercept global.fetch to track thinking
31
+ try {
32
+ const originalFetch = global.fetch;
33
+ if (typeof originalFetch === 'function') {
34
+ let fetchCounter = 0;
35
+ global.fetch = function(...args) {
36
+ const id = ++fetchCounter;
37
+ const url = typeof args[0] === 'string' ? args[0] : args[0]?.url || '';
38
+ let hostname = '';
39
+ let path = '';
40
+ try {
41
+ const urlObj = new URL(url, 'http://localhost');
42
+ hostname = urlObj.hostname;
43
+ path = urlObj.pathname;
44
+ } catch {}
45
+ writeMessage({ type: 'fetch-start', id, hostname, path, timestamp: Date.now() });
46
+ const p = originalFetch.apply(this, args);
47
+ const sendEnd = () => writeMessage({ type: 'fetch-end', id, timestamp: Date.now() });
48
+ p.then(sendEnd, sendEnd);
49
+ return p;
50
+ }
51
+ }
52
+ } catch (_) {}
53
+
54
+ // Disable any autoupdater behavior in codex if present
55
+ process.env.DISABLE_AUTOUPDATER = '1';
56
+
@@ -0,0 +1,129 @@
1
+ const crypto = require('crypto');
2
+ const fs = require('fs');
3
+
4
+ // Disable autoupdater if Codex has one
5
+ process.env.DISABLE_AUTOUPDATER = '1';
6
+
7
+ // Helper to write JSON messages to fd 3
8
+ function writeMessage(message) {
9
+ try {
10
+ fs.writeSync(3, JSON.stringify(message) + '\n');
11
+ } catch (err) {
12
+ // fd 3 not available, ignore
13
+ }
14
+ }
15
+
16
+ // Intercept crypto.randomUUID
17
+ const originalRandomUUID = crypto.randomUUID;
18
+ Object.defineProperty(global, 'crypto', {
19
+ configurable: true,
20
+ enumerable: true,
21
+ get() {
22
+ return {
23
+ randomUUID: () => {
24
+ const uuid = originalRandomUUID();
25
+ writeMessage({ type: 'uuid', value: uuid });
26
+ return uuid;
27
+ }
28
+ };
29
+ }
30
+ });
31
+ Object.defineProperty(crypto, 'randomUUID', {
32
+ configurable: true,
33
+ enumerable: true,
34
+ get() {
35
+ return () => {
36
+ const uuid = originalRandomUUID();
37
+ writeMessage({ type: 'uuid', value: uuid });
38
+ return uuid;
39
+ }
40
+ }
41
+ });
42
+
43
+ // Intercept fetch to track activity
44
+ const originalFetch = global.fetch;
45
+ let fetchCounter = 0;
46
+
47
+ global.fetch = function(...args) {
48
+ const id = ++fetchCounter;
49
+ const url = typeof args[0] === 'string' ? args[0] : args[0]?.url || '';
50
+ const method = args[1]?.method || 'GET';
51
+
52
+ // Parse URL for privacy
53
+ let hostname = '';
54
+ let path = '';
55
+ try {
56
+ const urlObj = new URL(url, 'http://localhost');
57
+ hostname = urlObj.hostname;
58
+ path = urlObj.pathname;
59
+ } catch (e) {
60
+ // If URL parsing fails, use defaults
61
+ hostname = 'unknown';
62
+ path = url;
63
+ }
64
+
65
+ // Send fetch start event
66
+ writeMessage({
67
+ type: 'fetch-start',
68
+ id,
69
+ hostname,
70
+ path,
71
+ method,
72
+ timestamp: Date.now()
73
+ });
74
+
75
+ // Execute the original fetch immediately
76
+ const fetchPromise = originalFetch(...args);
77
+
78
+ // Attach handlers to send fetch end event
79
+ const sendEnd = () => {
80
+ writeMessage({
81
+ type: 'fetch-end',
82
+ id,
83
+ timestamp: Date.now()
84
+ });
85
+ };
86
+
87
+ // Send end event on both success and failure
88
+ fetchPromise.then(sendEnd, sendEnd);
89
+
90
+ // Return the original promise unchanged
91
+ return fetchPromise;
92
+ };
93
+
94
+ // Preserve fetch properties
95
+ Object.defineProperty(global.fetch, 'name', { value: 'fetch' });
96
+ Object.defineProperty(global.fetch, 'length', { value: originalFetch.length });
97
+
98
+ // Import Codex SDK for remote control
99
+ // Try different entry points based on how OpenAI packages Codex
100
+ (async () => {
101
+ try {
102
+ // Try SDK entry point first (for remote/programmatic control)
103
+ await import('@openai/codex/sdk.js');
104
+ } catch (err1) {
105
+ try {
106
+ // Try CLI as fallback (can also be used remotely)
107
+ await import('@openai/codex/cli.js');
108
+ } catch (err2) {
109
+ try {
110
+ // Try main export
111
+ await import('@openai/codex');
112
+ } catch (err3) {
113
+ console.error('❌ Failed to load Codex from any known entry point');
114
+ console.error('Attempted paths:');
115
+ console.error(' - @openai/codex/sdk.js');
116
+ console.error(' - @openai/codex/cli.js');
117
+ console.error(' - @openai/codex');
118
+ console.error('');
119
+ console.error('Error details:', err3.message);
120
+ console.error('');
121
+ console.error('Please ensure @openai/codex is installed correctly:');
122
+ console.error(' npm install @openai/codex');
123
+ console.error(' or check https://github.com/openai/codex for installation instructions');
124
+ process.exit(1);
125
+ }
126
+ }
127
+ }
128
+ })();
129
+
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { fileURLToPath } from 'url';
4
+ import { dirname, join, relative, extname, basename } from 'path';
5
+ import { readFileSync, writeFileSync, mkdirSync, readdirSync, statSync, copyFileSync } from 'fs';
6
+ import JavaScriptObfuscator from 'javascript-obfuscator';
7
+
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = dirname(__filename);
10
+ const rootDir = join(__dirname, '..');
11
+ const distDir = join(rootDir, 'dist');
12
+ const distObfDir = join(rootDir, 'dist.obf');
13
+
14
+ const obfuscatorOptions = {
15
+ compact: true,
16
+ selfDefending: false,
17
+ controlFlowFlattening: true,
18
+ stringArray: true,
19
+ stringArrayEncoding: ['base64'],
20
+ identifierNamesGenerator: 'mangled'
21
+ };
22
+
23
+ function getAllFiles(dir, fileList = []) {
24
+ const files = readdirSync(dir);
25
+
26
+ files.forEach(file => {
27
+ const filePath = join(dir, file);
28
+ if (statSync(filePath).isDirectory()) {
29
+ getAllFiles(filePath, fileList);
30
+ } else {
31
+ fileList.push(filePath);
32
+ }
33
+ });
34
+
35
+ return fileList;
36
+ }
37
+
38
+ function obfuscateFile(inputPath, outputPath) {
39
+ const ext = extname(inputPath);
40
+
41
+ // Only obfuscate .cjs and .mjs files
42
+ if (ext === '.cjs' || ext === '.mjs') {
43
+ console.log(`Obfuscating: ${relative(rootDir, inputPath)}`);
44
+ const code = readFileSync(inputPath, 'utf8');
45
+ const obfuscated = JavaScriptObfuscator.obfuscate(code, obfuscatorOptions);
46
+
47
+ // Create output directory if it doesn't exist
48
+ const outputDir = dirname(outputPath);
49
+ mkdirSync(outputDir, { recursive: true });
50
+
51
+ writeFileSync(outputPath, obfuscated.getObfuscatedCode(), 'utf8');
52
+ } else {
53
+ // Copy type definition files and other files as-is
54
+ console.log(`Copying: ${relative(rootDir, inputPath)}`);
55
+ const outputDir = dirname(outputPath);
56
+ mkdirSync(outputDir, { recursive: true });
57
+ copyFileSync(inputPath, outputPath);
58
+ }
59
+ }
60
+
61
+ console.log('Starting obfuscation...');
62
+
63
+ // Get all files from dist
64
+ const allFiles = getAllFiles(distDir);
65
+
66
+ // Process each file
67
+ allFiles.forEach(inputPath => {
68
+ const relativePath = relative(distDir, inputPath);
69
+ const outputPath = join(distObfDir, relativePath);
70
+ obfuscateFile(inputPath, outputPath);
71
+ });
72
+
73
+ console.log(`Obfuscation complete! Output in ${relative(rootDir, distObfDir)}`);
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env node
2
+ const { execSync } = require('node:child_process');
3
+ const { existsSync, unlinkSync, renameSync } = require('node:fs');
4
+ const { join } = require('node:path');
5
+
6
+ try {
7
+ const outName = 'chell.tgz';
8
+ const outPath = join(process.cwd(), outName);
9
+
10
+ if (existsSync(outPath)) {
11
+ unlinkSync(outPath);
12
+ }
13
+
14
+ // Run npm pack and capture the produced filename
15
+ const result = execSync('npm pack --silent', { stdio: ['ignore', 'pipe', 'inherit'] })
16
+ .toString()
17
+ .trim();
18
+
19
+ if (!result || !result.endsWith('.tgz')) {
20
+ console.error('Failed to determine pack filename, got:', result);
21
+ process.exit(1);
22
+ }
23
+
24
+ // Rename to chell.tgz
25
+ renameSync(join(process.cwd(), result), outPath);
26
+ console.log(`Created ${outName}`);
27
+ } catch (err) {
28
+ console.error('pack-chell failed:', err?.message || err);
29
+ process.exit(1);
30
+ }
31
+
32
+