cawide 0.4.5 → 0.4.7
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 +17 -38
- package/bin/cawide.js +64 -157
- package/package.json +17 -6
package/README.md
CHANGED
|
@@ -1,50 +1,29 @@
|
|
|
1
|
-
#
|
|
1
|
+
# cawide
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Mobile remote code editor & AI agent terminal companion.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Control your local development environment, terminals, and AI coding agents (Claude Code, OpenAI Codex, OpenCode, Pi, OMP, Hermes) directly from the Cawide mobile app.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Install
|
|
8
8
|
|
|
9
|
-
```
|
|
10
|
-
# Run directly via npx
|
|
11
|
-
npx cawide start
|
|
12
|
-
|
|
13
|
-
# Or install globally
|
|
9
|
+
```bash
|
|
14
10
|
npm install -g cawide
|
|
15
|
-
cawide start
|
|
16
11
|
```
|
|
17
12
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
| Command | Description |
|
|
21
|
-
|---------|-------------|
|
|
22
|
-
| `cawide start` | Start the daemon in your project directory and display the pairing QR code. |
|
|
23
|
-
| `cawide qr` | Show the pairing QR code for the active workspace. |
|
|
24
|
-
| `cawide status` | Inspect connected sessions, active terminals, and relay status. |
|
|
25
|
-
| `cawide setup [agent]` | Configure hooks and skills for AI agents (Claude, Codex, OpenCode). |
|
|
26
|
-
| `cawide logs` | View daemon logs. |
|
|
27
|
-
| `cawide stop` | Stop the background daemon. |
|
|
28
|
-
|
|
29
|
-
Use `cawide <command> --help` for the options supported by a particular command.
|
|
30
|
-
|
|
31
|
-
## Security & Architecture
|
|
13
|
+
Or run directly without installing:
|
|
32
14
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
## Supported platforms
|
|
38
|
-
|
|
39
|
-
- **macOS** — Apple Silicon & Intel
|
|
40
|
-
- **Linux** — x86_64 & ARM64
|
|
41
|
-
- **Windows** — x86_64 & ARM64
|
|
15
|
+
```bash
|
|
16
|
+
npx cawide --help
|
|
17
|
+
```
|
|
42
18
|
|
|
43
|
-
##
|
|
19
|
+
## Getting Started
|
|
44
20
|
|
|
45
|
-
|
|
46
|
-
|
|
21
|
+
```bash
|
|
22
|
+
# Start the workspace daemon
|
|
23
|
+
cawide start
|
|
47
24
|
|
|
48
|
-
|
|
25
|
+
# Print pairing QR code
|
|
26
|
+
cawide qr
|
|
27
|
+
```
|
|
49
28
|
|
|
50
|
-
|
|
29
|
+
For full documentation, visit [cawide.hermillon.com](https://cawide.hermillon.com).
|
package/bin/cawide.js
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
const fs = require("node:fs");
|
|
4
|
-
const path = require("node:path");
|
|
5
4
|
const os = require("node:os");
|
|
6
|
-
const
|
|
5
|
+
const path = require("node:path");
|
|
7
6
|
const childProcess = require("node:child_process");
|
|
8
|
-
const zlib = require("node:zlib");
|
|
9
7
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
8
|
+
// Maps `${process.platform}-${process.arch}` to the platform-specific npm
|
|
9
|
+
// package that ships the prebuilt binary for it (see
|
|
10
|
+
// scripts/package-npm.js and the six `cawide-<platform>`
|
|
11
|
+
// optionalDependencies in package.json).
|
|
12
|
+
const PLATFORM_PACKAGES = {
|
|
13
|
+
"darwin-arm64": "cawide-darwin-arm64",
|
|
14
|
+
"darwin-x64": "cawide-darwin-x64",
|
|
15
|
+
"linux-x64": "cawide-linux-x64",
|
|
16
|
+
"linux-arm64": "cawide-linux-arm64",
|
|
17
|
+
"win32-x64": "cawide-win32-x64",
|
|
18
|
+
"win32-arm64": "cawide-win32-x64",
|
|
19
19
|
};
|
|
20
20
|
const SIGNAL_EXIT_CODES = { SIGINT: 130, SIGTERM: 143 };
|
|
21
21
|
|
|
@@ -23,9 +23,21 @@ function executableName() {
|
|
|
23
23
|
return process.platform === "win32" ? "cawide.exe" : "cawide";
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
function platformKey() {
|
|
27
|
+
return `${process.platform}-${process.arch}`;
|
|
28
|
+
}
|
|
29
|
+
|
|
26
30
|
function localBinary() {
|
|
27
31
|
const repositoryRoot = path.resolve(__dirname, "../../..");
|
|
28
|
-
|
|
32
|
+
const cargoTomlPath = path.join(repositoryRoot, "Cargo.toml");
|
|
33
|
+
if (!fs.existsSync(cargoTomlPath)) return null;
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
const cargoToml = fs.readFileSync(cargoTomlPath, "utf8");
|
|
37
|
+
if (!cargoToml.includes("cawide")) return null;
|
|
38
|
+
} catch {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
29
41
|
|
|
30
42
|
for (const profile of ["release", "debug"]) {
|
|
31
43
|
const candidate = path.join(repositoryRoot, "target", profile, executableName());
|
|
@@ -34,168 +46,63 @@ function localBinary() {
|
|
|
34
46
|
return null;
|
|
35
47
|
}
|
|
36
48
|
|
|
37
|
-
function
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
? process.env.LOCALAPPDATA || path.join(os.homedir(), "AppData", "Local")
|
|
41
|
-
: path.join(os.homedir(), ".cache");
|
|
42
|
-
return path.join(cacheRoot, "cawide", "bin", `v${VERSION}`, executableName());
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function platformTargets() {
|
|
46
|
-
const targets = TARGETS[`${process.platform}-${process.arch}`];
|
|
47
|
-
if (!targets) {
|
|
49
|
+
function platformPackageName() {
|
|
50
|
+
const packageName = PLATFORM_PACKAGES[platformKey()];
|
|
51
|
+
if (!packageName) {
|
|
48
52
|
throw new Error(
|
|
49
|
-
`Cawide does not provide a binary for ${process.platform}/${process.arch}. Supported platforms:
|
|
53
|
+
`Cawide does not provide a binary for ${process.platform}/${process.arch}. Supported platforms: ${Object.keys(
|
|
54
|
+
PLATFORM_PACKAGES
|
|
55
|
+
).join(", ")}.`
|
|
50
56
|
);
|
|
51
57
|
}
|
|
52
|
-
return
|
|
58
|
+
return packageName;
|
|
53
59
|
}
|
|
54
60
|
|
|
55
|
-
function
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
resolve(download(new URL(response.headers.location, url).toString(), redirectsLeft - 1));
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
if (status !== 200) {
|
|
72
|
-
response.resume();
|
|
73
|
-
const error = new Error(`Download failed with HTTP ${status}: ${url}`);
|
|
74
|
-
error.statusCode = status;
|
|
75
|
-
reject(error);
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const chunks = [];
|
|
80
|
-
response.on("data", (chunk) => chunks.push(chunk));
|
|
81
|
-
response.on("end", () => resolve(Buffer.concat(chunks)));
|
|
82
|
-
response.on("error", reject);
|
|
83
|
-
}
|
|
84
|
-
);
|
|
85
|
-
request.on("error", reject);
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
function tarBinary(archive) {
|
|
90
|
-
const tar = zlib.gunzipSync(archive);
|
|
91
|
-
let offset = 0;
|
|
92
|
-
while (offset + 512 <= tar.length) {
|
|
93
|
-
const header = tar.subarray(offset, offset + 512);
|
|
94
|
-
if (header.every((byte) => byte === 0)) break;
|
|
95
|
-
const name = header.subarray(0, 100).toString("utf8").replace(/\0.*$/, "");
|
|
96
|
-
const sizeText = header.subarray(124, 136).toString("ascii").replace(/\0.*$/, "").trim();
|
|
97
|
-
const size = Number.parseInt(sizeText || "0", 8);
|
|
98
|
-
const dataStart = offset + 512;
|
|
99
|
-
if (!Number.isFinite(size) || dataStart + size > tar.length) {
|
|
100
|
-
throw new Error("Downloaded tar archive is corrupt");
|
|
61
|
+
function resolvePlatformBinary() {
|
|
62
|
+
const packageName = platformPackageName();
|
|
63
|
+
|
|
64
|
+
let packageJsonPath;
|
|
65
|
+
try {
|
|
66
|
+
packageJsonPath = require.resolve(`${packageName}/package.json`);
|
|
67
|
+
} catch (error) {
|
|
68
|
+
if (error.code === "MODULE_NOT_FOUND") {
|
|
69
|
+
throw new Error(
|
|
70
|
+
`Cawide could not find the "${packageName}" platform package for ${platformKey()}.\nThis usually happens when the package was installed with --no-optional/--omit=optional, npm skipped optional dependencies, or the platform is unsupported.\nTry reinstalling without skipping optional dependencies: npm install -g cawide`
|
|
71
|
+
);
|
|
101
72
|
}
|
|
102
|
-
|
|
103
|
-
offset = dataStart + Math.ceil(size / 512) * 512;
|
|
73
|
+
throw error;
|
|
104
74
|
}
|
|
105
|
-
throw new Error("Downloaded archive does not contain the cawide binary");
|
|
106
|
-
}
|
|
107
75
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
let endOffset = -1;
|
|
114
|
-
for (let offset = archive.length - 22; offset >= searchStart; offset -= 1) {
|
|
115
|
-
if (archive.readUInt32LE(offset) === endSignature) {
|
|
116
|
-
endOffset = offset;
|
|
117
|
-
break;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
if (endOffset < 0) throw new Error("Downloaded zip archive is corrupt");
|
|
121
|
-
|
|
122
|
-
const entryCount = archive.readUInt16LE(endOffset + 10);
|
|
123
|
-
let offset = archive.readUInt32LE(endOffset + 16);
|
|
124
|
-
for (let index = 0; index < entryCount; index += 1) {
|
|
125
|
-
if (archive.readUInt32LE(offset) !== centralSignature) {
|
|
126
|
-
throw new Error("Downloaded zip archive has an invalid directory");
|
|
127
|
-
}
|
|
128
|
-
const method = archive.readUInt16LE(offset + 10);
|
|
129
|
-
const compressedSize = archive.readUInt32LE(offset + 20);
|
|
130
|
-
const fileNameLength = archive.readUInt16LE(offset + 28);
|
|
131
|
-
const extraLength = archive.readUInt16LE(offset + 30);
|
|
132
|
-
const commentLength = archive.readUInt16LE(offset + 32);
|
|
133
|
-
const localOffset = archive.readUInt32LE(offset + 42);
|
|
134
|
-
const name = archive.subarray(offset + 46, offset + 46 + fileNameLength).toString("utf8");
|
|
135
|
-
|
|
136
|
-
if (path.posix.basename(name.replace(/\\/g, "/")) === "cawide.exe") {
|
|
137
|
-
if (archive.readUInt32LE(localOffset) !== localSignature) {
|
|
138
|
-
throw new Error("Downloaded zip archive has an invalid entry");
|
|
139
|
-
}
|
|
140
|
-
const localNameLength = archive.readUInt16LE(localOffset + 26);
|
|
141
|
-
const localExtraLength = archive.readUInt16LE(localOffset + 28);
|
|
142
|
-
const dataStart = localOffset + 30 + localNameLength + localExtraLength;
|
|
143
|
-
const compressed = archive.subarray(dataStart, dataStart + compressedSize);
|
|
144
|
-
if (method === 0) return compressed;
|
|
145
|
-
if (method === 8) return zlib.inflateRawSync(compressed);
|
|
146
|
-
throw new Error(`Downloaded zip uses unsupported compression method ${method}`);
|
|
147
|
-
}
|
|
148
|
-
offset += 46 + fileNameLength + extraLength + commentLength;
|
|
149
|
-
}
|
|
150
|
-
throw new Error("Downloaded archive does not contain cawide.exe");
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
async function installBinary(destination) {
|
|
154
|
-
const extension = process.platform === "win32" ? "zip" : "tar.gz";
|
|
155
|
-
let lastError;
|
|
156
|
-
for (const target of platformTargets()) {
|
|
157
|
-
const asset = `cawide-${target}.${extension}`;
|
|
158
|
-
const url = `${RELEASE_BASE}/${asset}`;
|
|
159
|
-
try {
|
|
160
|
-
process.stderr.write(`Downloading Cawide v${VERSION} for ${target}...\n`);
|
|
161
|
-
const archive = await download(url);
|
|
162
|
-
const binary = extension === "zip" ? zipBinary(archive) : tarBinary(archive);
|
|
163
|
-
fs.mkdirSync(path.dirname(destination), { recursive: true });
|
|
164
|
-
const temporary = `${destination}.${process.pid}.tmp`;
|
|
165
|
-
try {
|
|
166
|
-
fs.writeFileSync(temporary, binary, { mode: 0o755 });
|
|
167
|
-
fs.chmodSync(temporary, 0o755);
|
|
168
|
-
fs.renameSync(temporary, destination);
|
|
169
|
-
} finally {
|
|
170
|
-
if (fs.existsSync(temporary)) fs.unlinkSync(temporary);
|
|
171
|
-
}
|
|
172
|
-
return;
|
|
173
|
-
} catch (error) {
|
|
174
|
-
lastError = error;
|
|
175
|
-
if (error.statusCode !== 404) break;
|
|
176
|
-
}
|
|
76
|
+
const binaryPath = path.join(path.dirname(packageJsonPath), "bin", executableName());
|
|
77
|
+
if (!fs.existsSync(binaryPath)) {
|
|
78
|
+
throw new Error(
|
|
79
|
+
`The "${packageName}" platform package is installed but is missing its binary at ${binaryPath}. Try reinstalling: npm install -g cawide`
|
|
80
|
+
);
|
|
177
81
|
}
|
|
178
|
-
|
|
82
|
+
return binaryPath;
|
|
179
83
|
}
|
|
180
84
|
|
|
181
85
|
function run(binaryPath) {
|
|
182
86
|
const result = childProcess.spawnSync(binaryPath, process.argv.slice(2), { stdio: "inherit" });
|
|
183
87
|
if (result.error) throw result.error;
|
|
184
|
-
if (result.signal
|
|
185
|
-
|
|
88
|
+
if (result.signal) {
|
|
89
|
+
const signalCode =
|
|
90
|
+
SIGNAL_EXIT_CODES[result.signal] ||
|
|
91
|
+
(process.platform !== "win32" && os.constants?.signals?.[result.signal]
|
|
92
|
+
? 128 + os.constants.signals[result.signal]
|
|
93
|
+
: 1);
|
|
94
|
+
process.exit(signalCode);
|
|
95
|
+
}
|
|
186
96
|
process.exit(result.status ?? 0);
|
|
187
97
|
}
|
|
188
98
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
if (local) run(local);
|
|
192
|
-
|
|
193
|
-
const cached = cacheBinary();
|
|
194
|
-
if (!fs.existsSync(cached)) await installBinary(cached);
|
|
195
|
-
run(cached);
|
|
99
|
+
function main() {
|
|
100
|
+
run(localBinary() || resolvePlatformBinary());
|
|
196
101
|
}
|
|
197
102
|
|
|
198
|
-
|
|
103
|
+
try {
|
|
104
|
+
main();
|
|
105
|
+
} catch (error) {
|
|
199
106
|
process.stderr.write(`cawide: ${error.message}\n`);
|
|
200
107
|
process.exit(1);
|
|
201
|
-
}
|
|
108
|
+
}
|
package/package.json
CHANGED
|
@@ -1,17 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cawide",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.7",
|
|
4
4
|
"description": "Mobile remote code editor & AI agent terminal companion",
|
|
5
|
-
"homepage": "https://cawide.
|
|
6
|
-
"bugs": "https://
|
|
5
|
+
"homepage": "https://cawide.hermillon.com",
|
|
6
|
+
"bugs": "https://github.com/Hermillon/cawide/issues",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/Hermillon/cawide.git"
|
|
10
|
+
},
|
|
7
11
|
"bin": {
|
|
8
|
-
"cawide": "
|
|
12
|
+
"cawide": "bin/cawide.js"
|
|
9
13
|
},
|
|
10
14
|
"files": ["bin/", "README.md"],
|
|
11
15
|
"engines": {
|
|
12
16
|
"node": ">=16.0.0"
|
|
13
17
|
},
|
|
14
18
|
"keywords": ["cawide", "terminal", "ai-agent", "remote-editor", "mobile", "editor"],
|
|
15
|
-
"author": "Cawide Team",
|
|
16
|
-
"license": "MIT"
|
|
19
|
+
"author": "Cawide Team <support@hermillon.com>",
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"optionalDependencies": {
|
|
22
|
+
"cawide-darwin-arm64": "0.4.7",
|
|
23
|
+
"cawide-darwin-x64": "0.4.7",
|
|
24
|
+
"cawide-linux-x64": "0.4.7",
|
|
25
|
+
"cawide-linux-arm64": "0.4.7",
|
|
26
|
+
"cawide-win32-x64": "0.4.7"
|
|
27
|
+
}
|
|
17
28
|
}
|