cawide 0.4.4 → 0.4.6

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 (3) hide show
  1. package/README.md +39 -42
  2. package/bin/cawide.js +51 -156
  3. package/package.json +26 -10
package/README.md CHANGED
@@ -1,66 +1,63 @@
1
- # Cawide
1
+ # Cawide CLI
2
2
 
3
- The official npm launcher for the Cawide desktop companion daemon. It runs a local development build when used from the Cawide repository; otherwise it downloads the matching Cawide release binary and caches it for later runs.
3
+ **Mobile remote code editor & AI agent terminal companion**
4
4
 
5
- ## Quick start
5
+ Connect your mobile device (iOS & Android) to your desktop or remote server with end-to-end encrypted, zero-trust P2P tunnels. Edit code, view diffs, and control AI coding agents (Claude Code, OpenCode, Codex) directly from your phone.
6
6
 
7
- Run Cawide without installing it globally:
7
+ ## Quick start
8
8
 
9
9
  ```sh
10
+ # Run directly via npx
10
11
  npx cawide start
11
- ```
12
-
13
- Or install the command globally:
14
12
 
15
- ```sh
13
+ # Or install globally
16
14
  npm install -g cawide
17
15
  cawide start
18
16
  ```
19
17
 
20
- All arguments are forwarded to the native Cawide CLI. Common commands include:
18
+ ## Commands
21
19
 
22
- ```sh
23
- cawide --help
24
- cawide start --help
25
- cawide status
26
- cawide qr
27
- cawide logs
28
- cawide stop
29
- ```
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. |
30
28
 
31
29
  Use `cawide <command> --help` for the options supported by a particular command.
32
30
 
33
- ## Supported platforms
34
-
35
- - macOS on Apple Silicon and Intel
36
- - Linux on x64 and ARM64
37
- - Windows on x64 and ARM64
38
-
39
- On first use, the launcher downloads the binary for the current platform from the matching [GitHub release](https://github.com/longd2k3/cawide/releases). The binary is cached at:
40
-
41
- - macOS and Linux: `~/.cache/cawide/bin/v0.4.4/cawide`
42
- - Windows: `%LOCALAPPDATA%\cawide\bin\v0.4.4\cawide.exe`
43
-
44
- ## Troubleshooting
31
+ ## Security & Architecture
45
32
 
46
- ### The download fails
33
+ - **Peer-to-peer QUIC / UDP** direct connection with automatic relay fallback.
34
+ - **Ed25519** cryptographic challenge-response authentication.
35
+ - **End-to-end encrypted** transport — your code never passes through third-party servers unencrypted.
47
36
 
48
- Check that GitHub Releases is reachable from your network and that release `v0.4.4` contains an artifact for your platform. A proxy or firewall may block redirected downloads from GitHub's asset host.
49
-
50
- ### The cached binary is damaged
37
+ ## Supported platforms
51
38
 
52
- Remove the versioned cache directory shown above and run the command again. Cawide will download a fresh copy.
39
+ The right prebuilt binary is installed automatically as an optional dependency
40
+ of this package (the same approach used by esbuild and `@biomejs/biome`) — no
41
+ extra download step at runtime.
53
42
 
54
- ### Permission denied on macOS or Linux
43
+ | Platform | Package |
44
+ |----------|---------|
45
+ | macOS (Apple Silicon) | [`cawide-darwin-arm64`](https://www.npmjs.com/package/cawide-darwin-arm64) |
46
+ | macOS (Intel) | [`cawide-darwin-x64`](https://www.npmjs.com/package/cawide-darwin-x64) |
47
+ | Linux (x86_64) | [`cawide-linux-x64`](https://www.npmjs.com/package/cawide-linux-x64) |
48
+ | Linux (ARM64) | [`cawide-linux-arm64`](https://www.npmjs.com/package/cawide-linux-arm64) |
49
+ | Windows (x86_64) | [`cawide-win32-x64`](https://www.npmjs.com/package/cawide-win32-x64) |
50
+ | Windows (ARM64) | [`cawide-win32-arm64`](https://www.npmjs.com/package/cawide-win32-arm64) |
55
51
 
56
- The launcher makes the downloaded binary executable automatically. If the cache was copied from another machine, remove it and rerun Cawide so it can be recreated with the correct permissions.
52
+ If `npm install` was run with `--no-optional`/`--omit=optional`, or the
53
+ platform is unsupported, `cawide` prints a clear error explaining how to
54
+ reinstall.
57
55
 
58
- ### macOS blocks the binary
56
+ ## Support
59
57
 
60
- Open **System Settings → Privacy & Security** and allow Cawide if macOS reports that it blocked the downloaded application. Only use binaries from the official Cawide GitHub release.
58
+ - [cawide.dev](https://cawide.dev) — documentation, updates, and community
59
+ - [Support](https://cawide.dev/support) — report issues and get help
61
60
 
62
- ### Show available commands
61
+ ## License
63
62
 
64
- ```sh
65
- cawide --help
66
- ```
63
+ MIT
package/bin/cawide.js CHANGED
@@ -2,20 +2,19 @@
2
2
 
3
3
  const fs = require("node:fs");
4
4
  const path = require("node:path");
5
- const os = require("node:os");
6
- const https = require("node:https");
7
5
  const childProcess = require("node:child_process");
8
- const zlib = require("node:zlib");
9
6
 
10
- const VERSION = "0.4.4";
11
- const RELEASE_BASE = `https://github.com/longd2k3/cawide/releases/download/v${VERSION}`;
12
- const TARGETS = {
13
- "darwin-arm64": ["aarch64-apple-darwin"],
14
- "darwin-x64": ["x86_64-apple-darwin", "aarch64-apple-darwin"],
15
- "linux-x64": ["x86_64-unknown-linux-gnu"],
16
- "linux-arm64": ["aarch64-unknown-linux-gnu"],
17
- "win32-x64": ["x86_64-pc-windows-msvc"],
18
- "win32-arm64": ["aarch64-pc-windows-msvc"],
7
+ // Maps `${process.platform}-${process.arch}` to the platform-specific npm
8
+ // package that ships the prebuilt binary for it (see
9
+ // scripts/build-platforms.js and the six `cawide-<platform>`
10
+ // optionalDependencies in package.json).
11
+ const PLATFORM_PACKAGES = {
12
+ "darwin-arm64": "cawide-darwin-arm64",
13
+ "darwin-x64": "cawide-darwin-x64",
14
+ "linux-x64": "cawide-linux-x64",
15
+ "linux-arm64": "cawide-linux-arm64",
16
+ "win32-x64": "cawide-win32-x64",
17
+ "win32-arm64": "cawide-win32-arm64",
19
18
  };
20
19
  const SIGNAL_EXIT_CODES = { SIGINT: 130, SIGTERM: 143 };
21
20
 
@@ -23,6 +22,10 @@ function executableName() {
23
22
  return process.platform === "win32" ? "cawide.exe" : "cawide";
24
23
  }
25
24
 
25
+ function platformKey() {
26
+ return `${process.platform}-${process.arch}`;
27
+ }
28
+
26
29
  function localBinary() {
27
30
  const repositoryRoot = path.resolve(__dirname, "../../..");
28
31
  if (!fs.existsSync(path.join(repositoryRoot, "Cargo.toml"))) return null;
@@ -34,168 +37,60 @@ function localBinary() {
34
37
  return null;
35
38
  }
36
39
 
37
- function cacheBinary() {
38
- const cacheRoot =
39
- process.platform === "win32"
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) {
40
+ function platformPackageName() {
41
+ const packageName = PLATFORM_PACKAGES[platformKey()];
42
+ if (!packageName) {
48
43
  throw new Error(
49
- `Cawide does not provide a binary for ${process.platform}/${process.arch}. Supported platforms: macOS (arm64, x64), Linux (arm64, x64), and Windows (arm64, x64).`
50
- );
51
- }
52
- return targets;
53
- }
54
-
55
- function download(url, redirectsLeft = 5) {
56
- return new Promise((resolve, reject) => {
57
- const request = https.get(
58
- url,
59
- { headers: { "User-Agent": `cawide-npm/${VERSION}` } },
60
- (response) => {
61
- const status = response.statusCode || 0;
62
- if (status >= 300 && status < 400 && response.headers.location) {
63
- response.resume();
64
- if (redirectsLeft === 0) {
65
- reject(new Error(`Too many redirects while downloading ${url}`));
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
- }
44
+ `Cawide does not provide a binary for ${process.platform}/${process.arch}. Supported platforms: ${Object.keys(
45
+ PLATFORM_PACKAGES
46
+ ).join(", ")}.`
84
47
  );
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");
101
- }
102
- if (path.posix.basename(name) === "cawide") return tar.subarray(dataStart, dataStart + size);
103
- offset = dataStart + Math.ceil(size / 512) * 512;
104
48
  }
105
- throw new Error("Downloaded archive does not contain the cawide binary");
49
+ return packageName;
106
50
  }
107
51
 
108
- function zipBinary(archive) {
109
- const endSignature = 0x06054b50;
110
- const centralSignature = 0x02014b50;
111
- const localSignature = 0x04034b50;
112
- const searchStart = Math.max(0, archive.length - 65557);
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;
52
+ function resolvePlatformBinary() {
53
+ const packageName = platformPackageName();
54
+
55
+ let packageJsonPath;
56
+ try {
57
+ packageJsonPath = require.resolve(`${packageName}/package.json`);
58
+ } catch (error) {
59
+ if (error.code === "MODULE_NOT_FOUND") {
60
+ throw new Error(
61
+ `Cawide could not find the "${packageName}" platform package for ${platformKey()}.\n` +
62
+ "This usually happens when the package was installed with --no-optional/--omit=optional, " +
63
+ "npm skipped optional dependencies, or the platform is unsupported.\n" +
64
+ "Try reinstalling without skipping optional dependencies: npm install -g cawide"
65
+ );
118
66
  }
67
+ throw error;
119
68
  }
120
- if (endOffset < 0) throw new Error("Downloaded zip archive is corrupt");
121
69
 
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
- }
70
+ const binaryPath = path.join(path.dirname(packageJsonPath), "bin", executableName());
71
+ if (!fs.existsSync(binaryPath)) {
72
+ throw new Error(
73
+ `The "${packageName}" platform package is installed but is missing its binary at ${binaryPath}. ` +
74
+ "Try reinstalling: npm install -g cawide"
75
+ );
177
76
  }
178
- throw lastError;
77
+ return binaryPath;
179
78
  }
180
79
 
181
80
  function run(binaryPath) {
182
81
  const result = childProcess.spawnSync(binaryPath, process.argv.slice(2), { stdio: "inherit" });
183
82
  if (result.error) throw result.error;
184
- if (result.signal && SIGNAL_EXIT_CODES[result.signal])
185
- process.exit(SIGNAL_EXIT_CODES[result.signal]);
83
+ if (result.signal && SIGNAL_EXIT_CODES[result.signal]) process.exit(SIGNAL_EXIT_CODES[result.signal]);
186
84
  process.exit(result.status ?? 0);
187
85
  }
188
86
 
189
- async function main() {
190
- const local = localBinary();
191
- if (local) run(local);
192
-
193
- const cached = cacheBinary();
194
- if (!fs.existsSync(cached)) await installBinary(cached);
195
- run(cached);
87
+ function main() {
88
+ run(localBinary() || resolvePlatformBinary());
196
89
  }
197
90
 
198
- main().catch((error) => {
91
+ try {
92
+ main();
93
+ } catch (error) {
199
94
  process.stderr.write(`cawide: ${error.message}\n`);
200
95
  process.exit(1);
201
- });
96
+ }
package/package.json CHANGED
@@ -1,19 +1,35 @@
1
1
  {
2
2
  "name": "cawide",
3
- "version": "0.4.4",
4
- "description": "Desktop companion daemon for Cawide remote coding terminal",
3
+ "version": "0.4.6",
4
+ "description": "Mobile remote code editor & AI agent terminal companion",
5
+ "homepage": "https://cawide.dev",
6
+ "bugs": "https://cawide.dev/support",
5
7
  "bin": {
6
- "cawide": "./bin/cawide.js"
8
+ "cawide": "bin/cawide.js"
7
9
  },
8
- "files": ["bin/", "README.md"],
10
+ "files": [
11
+ "bin/",
12
+ "README.md"
13
+ ],
9
14
  "engines": {
10
15
  "node": ">=16.0.0"
11
16
  },
12
- "repository": {
13
- "type": "git",
14
- "url": "https://github.com/longd2k3/cawide.git"
15
- },
16
- "keywords": ["cawide", "terminal", "ai-agent", "remote-editor", "gpui"],
17
+ "keywords": [
18
+ "cawide",
19
+ "terminal",
20
+ "ai-agent",
21
+ "remote-editor",
22
+ "mobile",
23
+ "editor"
24
+ ],
17
25
  "author": "Cawide Team",
18
- "license": "MIT"
26
+ "license": "MIT",
27
+ "optionalDependencies": {
28
+ "cawide-darwin-arm64": "0.4.6",
29
+ "cawide-darwin-x64": "0.4.6",
30
+ "cawide-linux-x64": "0.4.6",
31
+ "cawide-linux-arm64": "0.4.6",
32
+ "cawide-win32-x64": "0.4.6",
33
+ "cawide-win32-arm64": "0.4.6"
34
+ }
19
35
  }