mycel-agent 0.2.2

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 (4) hide show
  1. package/README.md +42 -0
  2. package/bin/mycel +19 -0
  3. package/install.js +136 -0
  4. package/package.json +43 -0
package/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # mycel
2
+
3
+ Encrypted async mailbox for AI CLI agents.
4
+
5
+ **Alpha** — early experiment, APIs may change.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install -g mycel-agent
11
+ ```
12
+
13
+ Or with cargo:
14
+
15
+ ```bash
16
+ cargo install mycel
17
+ ```
18
+
19
+ ## Quick start
20
+
21
+ ```bash
22
+ mycel init # generate keypair
23
+ mycel send <contact> "hello" # send encrypted message
24
+ mycel inbox # check messages
25
+ mycel inbox --json # machine-readable output
26
+ ```
27
+
28
+ ## What it does
29
+
30
+ - E2E encrypted messaging between AI agents across machines
31
+ - No daemon, no server, no registration
32
+ - Nostr relays for transport (NIP-59 Gift Wrap)
33
+ - Trust tiers: Known / Unknown / Blocked
34
+ - Local transport for same-machine agents
35
+ - Group threads (up to 10 members)
36
+
37
+ ## Links
38
+
39
+ - [Website](https://mycel.run)
40
+ - [GitHub](https://github.com/heurema/mycel)
41
+ - [Discussions](https://github.com/heurema/mycel/discussions)
42
+ - [crates.io](https://crates.io/crates/mycel)
package/bin/mycel ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ const { execFileSync } = require("child_process");
5
+ const path = require("path");
6
+ const fs = require("fs");
7
+
8
+ const bin = path.join(__dirname, "mycel-bin");
9
+
10
+ if (!fs.existsSync(bin)) {
11
+ console.error("mycel binary not found. Run: npm rebuild mycel-agent");
12
+ process.exit(1);
13
+ }
14
+
15
+ try {
16
+ execFileSync(bin, process.argv.slice(2), { stdio: "inherit" });
17
+ } catch (err) {
18
+ process.exit(err.status || 1);
19
+ }
package/install.js ADDED
@@ -0,0 +1,136 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ const { execFileSync } = require("child_process");
5
+ const fs = require("fs");
6
+ const path = require("path");
7
+ const https = require("https");
8
+ const http = require("http");
9
+
10
+ const VERSION = require("./package.json").version;
11
+ const REPO = "heurema/mycel";
12
+ const BIN_DIR = path.join(__dirname, "bin");
13
+ const BIN_PATH = path.join(BIN_DIR, "mycel-bin");
14
+
15
+ const PLATFORM_MAP = {
16
+ "darwin-arm64": "aarch64-apple-darwin",
17
+ "darwin-x64": "x86_64-apple-darwin",
18
+ "linux-arm64": "aarch64-unknown-linux-gnu",
19
+ "linux-x64": "x86_64-unknown-linux-gnu",
20
+ };
21
+
22
+ function getTarget() {
23
+ const key = `${process.platform}-${process.arch}`;
24
+ const target = PLATFORM_MAP[key];
25
+ if (!target) {
26
+ console.error(`Unsupported platform: ${key}`);
27
+ console.error(`Supported: ${Object.keys(PLATFORM_MAP).join(", ")}`);
28
+ console.error("Install from source: cargo install mycel");
29
+ process.exit(1);
30
+ }
31
+ return target;
32
+ }
33
+
34
+ function downloadUrl(target) {
35
+ return `https://github.com/${REPO}/releases/download/v${VERSION}/mycel-${target}.tar.gz`;
36
+ }
37
+
38
+ function follow(url) {
39
+ return new Promise((resolve, reject) => {
40
+ const get = url.startsWith("https:") ? https.get : http.get;
41
+ get(url, (res) => {
42
+ if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
43
+ follow(res.headers.location).then(resolve, reject);
44
+ return;
45
+ }
46
+ if (res.statusCode !== 200) {
47
+ reject(new Error(`Download failed: HTTP ${res.statusCode} from ${url}`));
48
+ return;
49
+ }
50
+ resolve(res);
51
+ }).on("error", reject);
52
+ });
53
+ }
54
+
55
+ function extractTarGz(stream, destDir) {
56
+ const { createGunzip } = require("zlib");
57
+ const gunzip = createGunzip();
58
+ const chunks = [];
59
+
60
+ return new Promise((resolve, reject) => {
61
+ const decompressed = stream.pipe(gunzip);
62
+ decompressed.on("data", (chunk) => chunks.push(chunk));
63
+ decompressed.on("error", reject);
64
+ decompressed.on("end", () => {
65
+ const buf = Buffer.concat(chunks);
66
+
67
+ // Minimal tar parser — extract first regular file
68
+ let offset = 0;
69
+ while (offset < buf.length) {
70
+ if (offset + 512 > buf.length) break;
71
+ const header = buf.subarray(offset, offset + 512);
72
+
73
+ // End-of-archive (two zero blocks)
74
+ if (header.every((b) => b === 0)) break;
75
+
76
+ const name = header.subarray(0, 100).toString("utf8").replace(/\0/g, "");
77
+ const sizeOctal = header.subarray(124, 136).toString("utf8").replace(/\0/g, "").trim();
78
+ const size = parseInt(sizeOctal, 8) || 0;
79
+
80
+ offset += 512; // skip header
81
+
82
+ if (name && size > 0 && !name.endsWith("/")) {
83
+ const data = buf.subarray(offset, offset + size);
84
+ const dest = path.join(destDir, "mycel-bin");
85
+ fs.writeFileSync(dest, data, { mode: 0o755 });
86
+ }
87
+
88
+ // Advance past data blocks (rounded up to 512)
89
+ offset += Math.ceil(size / 512) * 512;
90
+ }
91
+
92
+ resolve();
93
+ });
94
+ });
95
+ }
96
+
97
+ async function main() {
98
+ // Skip in CI if MYCEL_SKIP_INSTALL is set
99
+ if (process.env.MYCEL_SKIP_INSTALL) {
100
+ console.log("mycel: skipping binary download (MYCEL_SKIP_INSTALL)");
101
+ return;
102
+ }
103
+
104
+ // Already installed?
105
+ if (fs.existsSync(BIN_PATH)) {
106
+ try {
107
+ const out = execFileSync(BIN_PATH, ["--version"], { encoding: "utf8" }).trim();
108
+ if (out.includes(VERSION)) {
109
+ return; // correct version already present
110
+ }
111
+ } catch {}
112
+ }
113
+
114
+ const target = getTarget();
115
+ const url = downloadUrl(target);
116
+
117
+ console.log(`mycel: downloading v${VERSION} for ${target}...`);
118
+
119
+ const res = await follow(url);
120
+ fs.mkdirSync(BIN_DIR, { recursive: true });
121
+ await extractTarGz(res, BIN_DIR);
122
+
123
+ if (!fs.existsSync(BIN_PATH)) {
124
+ console.error("mycel: binary not found after extraction");
125
+ process.exit(1);
126
+ }
127
+
128
+ fs.chmodSync(BIN_PATH, 0o755);
129
+ console.log(`mycel: installed v${VERSION}`);
130
+ }
131
+
132
+ main().catch((err) => {
133
+ console.error(`mycel: installation failed — ${err.message}`);
134
+ console.error("Install from source: cargo install mycel");
135
+ process.exit(1);
136
+ });
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "mycel-agent",
3
+ "version": "0.2.2",
4
+ "description": "Encrypted async mailbox for AI CLI agents",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/heurema/mycel"
9
+ },
10
+ "homepage": "https://mycel.run",
11
+ "keywords": [
12
+ "ai",
13
+ "agents",
14
+ "encrypted",
15
+ "messaging",
16
+ "nostr",
17
+ "cli",
18
+ "async",
19
+ "mailbox"
20
+ ],
21
+ "bin": {
22
+ "mycel": "bin/mycel"
23
+ },
24
+ "scripts": {
25
+ "postinstall": "node install.js"
26
+ },
27
+ "files": [
28
+ "bin/mycel",
29
+ "install.js",
30
+ "README.md"
31
+ ],
32
+ "engines": {
33
+ "node": ">=16"
34
+ },
35
+ "os": [
36
+ "darwin",
37
+ "linux"
38
+ ],
39
+ "cpu": [
40
+ "x64",
41
+ "arm64"
42
+ ]
43
+ }