cimux-mcp 0.1.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/LICENSE +21 -0
- package/README.md +133 -0
- package/dist/cli/cimux-cli.d.ts +10 -0
- package/dist/cli/cimux-cli.js +201 -0
- package/dist/cli/cimux-cli.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -0
- package/dist/install/cimux-install-plan.d.ts +29 -0
- package/dist/install/cimux-install-plan.js +187 -0
- package/dist/install/cimux-install-plan.js.map +1 -0
- package/dist/mcp/cimux-mcp-server.d.ts +4 -0
- package/dist/mcp/cimux-mcp-server.js +59 -0
- package/dist/mcp/cimux-mcp-server.js.map +1 -0
- package/dist/model/context-package.d.ts +913 -0
- package/dist/model/context-package.js +153 -0
- package/dist/model/context-package.js.map +1 -0
- package/dist/registration/mailbox-registration.d.ts +30 -0
- package/dist/registration/mailbox-registration.js +48 -0
- package/dist/registration/mailbox-registration.js.map +1 -0
- package/dist/runtime/mailbox-runtime.d.ts +22 -0
- package/dist/runtime/mailbox-runtime.js +50 -0
- package/dist/runtime/mailbox-runtime.js.map +1 -0
- package/dist/service/cimux-mailbox-service.d.ts +87 -0
- package/dist/service/cimux-mailbox-service.js +126 -0
- package/dist/service/cimux-mailbox-service.js.map +1 -0
- package/dist/storage/mailbox-store.d.ts +22 -0
- package/dist/storage/mailbox-store.js +2 -0
- package/dist/storage/mailbox-store.js.map +1 -0
- package/dist/storage/sqlite-cimux-store.d.ts +21 -0
- package/dist/storage/sqlite-cimux-store.js +201 -0
- package/dist/storage/sqlite-cimux-store.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +3 -0
- package/dist/version.js.map +1 -0
- package/docs/mvp-readiness.md +85 -0
- package/package.json +51 -0
- package/scripts/demo-local-handoff.mjs +73 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jack Faulkner
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# Cimux
|
|
2
|
+
|
|
3
|
+
Local-first mailboxes for intentional AI agent context handoffs.
|
|
4
|
+
|
|
5
|
+
Cimux gives concurrent coding agents a simple way to pass context without dumping every detail into every session. A sender creates a structured Context Package, addressed to a mailbox such as `codex/backend-auth` or `claude/frontend-login`. The receiver can preview the inbox cheaply, read the full package only when it matters, and ack it after loading.
|
|
6
|
+
|
|
7
|
+
The product idea is intentionally small:
|
|
8
|
+
|
|
9
|
+
- anyone can send to an existing mailbox
|
|
10
|
+
- only the addressed mailbox should read or ack a package
|
|
11
|
+
- `check_inbox` returns token-aware previews, not full bodies
|
|
12
|
+
- hook notifications emit nothing when the inbox is empty
|
|
13
|
+
- storage is local SQLite
|
|
14
|
+
- the main agent integration is MCP
|
|
15
|
+
|
|
16
|
+
## Current MVP
|
|
17
|
+
|
|
18
|
+
Included now:
|
|
19
|
+
|
|
20
|
+
- Context Package schema
|
|
21
|
+
- SQLite storage
|
|
22
|
+
- mailbox registration and name inference
|
|
23
|
+
- MCP server with mailbox tools
|
|
24
|
+
- zero-token notification command
|
|
25
|
+
- safe installer for Codex and Claude config targets
|
|
26
|
+
- local CLI commands for debugging and demos
|
|
27
|
+
|
|
28
|
+
Not included yet:
|
|
29
|
+
|
|
30
|
+
- hosted SaaS mode
|
|
31
|
+
- vector search or embeddings
|
|
32
|
+
- automatic routing
|
|
33
|
+
- remote auth
|
|
34
|
+
- read-only inspector UI
|
|
35
|
+
|
|
36
|
+
See [docs/mvp-readiness.md](docs/mvp-readiness.md) for the release checklist and known limits.
|
|
37
|
+
|
|
38
|
+
## Install
|
|
39
|
+
|
|
40
|
+
From npm (package `cimux-mcp`, command `cimux`):
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npm install -g cimux-mcp
|
|
44
|
+
cimux install --dry-run
|
|
45
|
+
cimux install
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Install Locally
|
|
49
|
+
|
|
50
|
+
From the repo:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
npm install
|
|
54
|
+
npm run build
|
|
55
|
+
npm link
|
|
56
|
+
cimux install --dry-run
|
|
57
|
+
cimux install
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
`--dry-run` prints the config snippets first. `cimux install` writes the supported config files and creates `.cimux.bak` backups before changing existing files.
|
|
61
|
+
|
|
62
|
+
After installing, restart the agent harness so it reloads MCP and hook config.
|
|
63
|
+
|
|
64
|
+
## Mailbox Names
|
|
65
|
+
|
|
66
|
+
Cimux uses `harness/name` format:
|
|
67
|
+
|
|
68
|
+
- `codex/backend-auth`
|
|
69
|
+
- `claude/frontend-login`
|
|
70
|
+
- `cursor/fix-checkout`
|
|
71
|
+
|
|
72
|
+
For hook checks, users should not have to remember a name. `cimux notify --harness codex` infers the mailbox from the current git branch, falling back to the folder name.
|
|
73
|
+
|
|
74
|
+
## MCP Tools
|
|
75
|
+
|
|
76
|
+
Cimux exposes:
|
|
77
|
+
|
|
78
|
+
- `register_session`
|
|
79
|
+
- `send_context`
|
|
80
|
+
- `check_inbox`
|
|
81
|
+
- `read_context`
|
|
82
|
+
- `ack_context`
|
|
83
|
+
|
|
84
|
+
Typical flow:
|
|
85
|
+
|
|
86
|
+
1. A session registers or infers its mailbox.
|
|
87
|
+
2. Another session sends a Context Package to that mailbox.
|
|
88
|
+
3. The receiver sees a hook notification on the next user prompt if unread mail exists.
|
|
89
|
+
4. The receiver calls `check_inbox` to preview.
|
|
90
|
+
5. The receiver calls `read_context` for the full package.
|
|
91
|
+
6. The receiver calls `ack_context` after loading it.
|
|
92
|
+
|
|
93
|
+
## Local CLI
|
|
94
|
+
|
|
95
|
+
The CLI mirrors the mailbox flow for local proof/debugging:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
cimux register --mailbox codex/backend-auth
|
|
99
|
+
cimux register --mailbox claude/frontend-login
|
|
100
|
+
|
|
101
|
+
cimux send \
|
|
102
|
+
--from codex/backend-auth \
|
|
103
|
+
--to claude/frontend-login \
|
|
104
|
+
--title "Auth handoff" \
|
|
105
|
+
--summary "Frontend should handle the new auth error." \
|
|
106
|
+
--body "validateSession now throws ExpiredSessionError." \
|
|
107
|
+
--tags auth,frontend
|
|
108
|
+
|
|
109
|
+
cimux notify --mailbox claude/frontend-login
|
|
110
|
+
cimux check --mailbox claude/frontend-login
|
|
111
|
+
cimux read --mailbox claude/frontend-login --id <context-id>
|
|
112
|
+
cimux ack --mailbox claude/frontend-login --id <context-id> --note "Loaded."
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Run the full demo:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
npm run demo:local
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Development
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
npm test
|
|
125
|
+
npm run typecheck
|
|
126
|
+
npm run build
|
|
127
|
+
npm run demo:local
|
|
128
|
+
npm pack --dry-run
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## MVP Readiness
|
|
132
|
+
|
|
133
|
+
Before calling a build MVP-complete, run the automated checks and manual harness verification in [docs/mvp-readiness.md](docs/mvp-readiness.md).
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type CimuxCliIo = {
|
|
2
|
+
log(message: string): void;
|
|
3
|
+
error(message: string): void;
|
|
4
|
+
};
|
|
5
|
+
export type CimuxCliEnv = {
|
|
6
|
+
CIMUX_DB_PATH?: string;
|
|
7
|
+
CIMUX_MAILBOX?: string;
|
|
8
|
+
CIMUX_HARNESS?: string;
|
|
9
|
+
};
|
|
10
|
+
export declare function runCimuxCli(argv: string[], env?: CimuxCliEnv, cwd?: string, io?: CimuxCliIo): Promise<number>;
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { applyInstallPlan, createInstallPlan } from "../install/cimux-install-plan.js";
|
|
2
|
+
import { defaultDatabasePath, runCimuxMcpServer } from "../mcp/cimux-mcp-server.js";
|
|
3
|
+
import { resolveRuntimeMailbox } from "../runtime/mailbox-runtime.js";
|
|
4
|
+
import { ackContext, checkInbox, createInboxNotification, readContext, registerSession, sendContext } from "../service/cimux-mailbox-service.js";
|
|
5
|
+
import { SQLiteCimuxStore } from "../storage/sqlite-cimux-store.js";
|
|
6
|
+
import { name, version } from "../version.js";
|
|
7
|
+
export async function runCimuxCli(argv, env = process.env, cwd = process.cwd(), io = console) {
|
|
8
|
+
const command = argv[0];
|
|
9
|
+
try {
|
|
10
|
+
if (!command || command === "help" || command === "--help" || command === "-h") {
|
|
11
|
+
io.log(usage());
|
|
12
|
+
return 0;
|
|
13
|
+
}
|
|
14
|
+
if (command === "version" || command === "--version" || command === "-v") {
|
|
15
|
+
io.log(`${name} ${version}`);
|
|
16
|
+
return 0;
|
|
17
|
+
}
|
|
18
|
+
if (command === "mcp") {
|
|
19
|
+
await runCimuxMcpServer(env.CIMUX_DB_PATH);
|
|
20
|
+
return 0;
|
|
21
|
+
}
|
|
22
|
+
if (command === "notify") {
|
|
23
|
+
return await runNotifyCommand(argv, env, cwd, io);
|
|
24
|
+
}
|
|
25
|
+
if (command === "install") {
|
|
26
|
+
return runInstallCommand(argv, io);
|
|
27
|
+
}
|
|
28
|
+
if (command === "register") {
|
|
29
|
+
return await withStore(env, async (store) => {
|
|
30
|
+
const mailbox = resolveRuntimeMailboxFromArgs(argv, env, cwd);
|
|
31
|
+
const result = await registerSession(store, {
|
|
32
|
+
harness: readArg(argv, "--harness") ?? env.CIMUX_HARNESS ?? "codex",
|
|
33
|
+
...(mailbox.inferredFrom === "explicit"
|
|
34
|
+
? { explicitMailbox: mailbox.mailbox }
|
|
35
|
+
: {
|
|
36
|
+
branchName: mailbox.branchName ?? undefined,
|
|
37
|
+
folderName: mailbox.folderName
|
|
38
|
+
})
|
|
39
|
+
});
|
|
40
|
+
writeJson(io, result);
|
|
41
|
+
return 0;
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
if (command === "send") {
|
|
45
|
+
return await withStore(env, async (store) => {
|
|
46
|
+
const result = await sendContext(store, {
|
|
47
|
+
fromMailbox: requireArg(argv, "--from"),
|
|
48
|
+
toMailbox: requireArg(argv, "--to"),
|
|
49
|
+
title: requireArg(argv, "--title"),
|
|
50
|
+
summary: requireArg(argv, "--summary"),
|
|
51
|
+
body: requireArg(argv, "--body"),
|
|
52
|
+
tags: readCsvArg(argv, "--tags"),
|
|
53
|
+
artifacts: {},
|
|
54
|
+
payload: {}
|
|
55
|
+
});
|
|
56
|
+
writeJson(io, result);
|
|
57
|
+
return 0;
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
if (command === "check") {
|
|
61
|
+
return await withStore(env, async (store) => {
|
|
62
|
+
const result = await checkInbox(store, {
|
|
63
|
+
mailbox: requireArg(argv, "--mailbox"),
|
|
64
|
+
unreadOnly: !argv.includes("--all")
|
|
65
|
+
});
|
|
66
|
+
writeJson(io, result);
|
|
67
|
+
return 0;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
if (command === "read") {
|
|
71
|
+
return await withStore(env, async (store) => {
|
|
72
|
+
const result = await readContext(store, {
|
|
73
|
+
mailbox: requireArg(argv, "--mailbox"),
|
|
74
|
+
id: requireArg(argv, "--id")
|
|
75
|
+
});
|
|
76
|
+
writeJson(io, result);
|
|
77
|
+
return 0;
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
if (command === "ack") {
|
|
81
|
+
return await withStore(env, async (store) => {
|
|
82
|
+
const note = readArg(argv, "--note");
|
|
83
|
+
const result = await ackContext(store, {
|
|
84
|
+
mailbox: requireArg(argv, "--mailbox"),
|
|
85
|
+
id: requireArg(argv, "--id"),
|
|
86
|
+
...(note === undefined ? {} : { note })
|
|
87
|
+
});
|
|
88
|
+
writeJson(io, result);
|
|
89
|
+
return 0;
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
io.error(usage());
|
|
93
|
+
return 1;
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
io.error(error instanceof Error ? error.message : String(error));
|
|
97
|
+
return 1;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
async function runNotifyCommand(argv, env, cwd, io) {
|
|
101
|
+
return withStore(env, async (store) => {
|
|
102
|
+
const { mailbox } = resolveRuntimeMailboxFromArgs(argv, env, cwd);
|
|
103
|
+
// Hook checks also act as a heartbeat for the current local session name.
|
|
104
|
+
// Creation is idempotent, so this does not reset existing mailbox state.
|
|
105
|
+
await store.createMailbox(mailbox);
|
|
106
|
+
const result = await createInboxNotification(store, { mailbox });
|
|
107
|
+
if (result.message) {
|
|
108
|
+
io.log(result.message);
|
|
109
|
+
}
|
|
110
|
+
return 0;
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
function runInstallCommand(argv, io) {
|
|
114
|
+
const plan = createInstallPlan();
|
|
115
|
+
if (!argv.includes("--dry-run")) {
|
|
116
|
+
const results = applyInstallPlan(plan);
|
|
117
|
+
for (const result of results) {
|
|
118
|
+
const backup = result.backupPath ? ` backup: ${result.backupPath}` : "";
|
|
119
|
+
io.log(`${result.status}: ${result.path}${backup}`);
|
|
120
|
+
}
|
|
121
|
+
return 0;
|
|
122
|
+
}
|
|
123
|
+
for (const target of plan.targets) {
|
|
124
|
+
io.log(`# ${target.harness}: ${target.path}`);
|
|
125
|
+
io.log(`# ${target.purpose}`);
|
|
126
|
+
io.log(target.snippet);
|
|
127
|
+
}
|
|
128
|
+
return 0;
|
|
129
|
+
}
|
|
130
|
+
async function withStore(env, callback) {
|
|
131
|
+
const store = new SQLiteCimuxStore(env.CIMUX_DB_PATH ?? defaultDatabasePath());
|
|
132
|
+
try {
|
|
133
|
+
return await callback(store);
|
|
134
|
+
}
|
|
135
|
+
finally {
|
|
136
|
+
store.close();
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
function resolveRuntimeMailboxFromArgs(argv, env, cwd) {
|
|
140
|
+
const explicitMailbox = readArg(argv, "--mailbox") ?? env.CIMUX_MAILBOX;
|
|
141
|
+
const harness = readArg(argv, "--harness") ?? env.CIMUX_HARNESS;
|
|
142
|
+
if (!explicitMailbox && !harness) {
|
|
143
|
+
throw new Error("Expected --mailbox <harness/name> or --harness <name>");
|
|
144
|
+
}
|
|
145
|
+
return resolveRuntimeMailbox({
|
|
146
|
+
...(explicitMailbox === undefined ? {} : { explicitMailbox }),
|
|
147
|
+
...(harness === undefined ? {} : { harness }),
|
|
148
|
+
cwd
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
function readArg(argv, name) {
|
|
152
|
+
const exact = argv.indexOf(name);
|
|
153
|
+
if (exact >= 0) {
|
|
154
|
+
return argv[exact + 1];
|
|
155
|
+
}
|
|
156
|
+
const prefixed = argv.find((arg) => arg.startsWith(`${name}=`));
|
|
157
|
+
return prefixed?.slice(name.length + 1);
|
|
158
|
+
}
|
|
159
|
+
function requireArg(argv, name) {
|
|
160
|
+
const value = readArg(argv, name);
|
|
161
|
+
if (!value) {
|
|
162
|
+
throw new Error(`Expected ${name}`);
|
|
163
|
+
}
|
|
164
|
+
return value;
|
|
165
|
+
}
|
|
166
|
+
function readCsvArg(argv, name) {
|
|
167
|
+
const value = readArg(argv, name);
|
|
168
|
+
if (!value) {
|
|
169
|
+
return [];
|
|
170
|
+
}
|
|
171
|
+
return value
|
|
172
|
+
.split(",")
|
|
173
|
+
.map((item) => item.trim())
|
|
174
|
+
.filter(Boolean);
|
|
175
|
+
}
|
|
176
|
+
function writeJson(io, value) {
|
|
177
|
+
io.log(JSON.stringify(value, null, 2));
|
|
178
|
+
}
|
|
179
|
+
function usage() {
|
|
180
|
+
return [
|
|
181
|
+
`${name} ${version}`,
|
|
182
|
+
"",
|
|
183
|
+
"Local-first mailboxes for intentional AI agent context handoffs.",
|
|
184
|
+
"",
|
|
185
|
+
"Usage:",
|
|
186
|
+
" cimux mcp",
|
|
187
|
+
" cimux install [--dry-run]",
|
|
188
|
+
" cimux notify [--mailbox <harness/name> | --harness <name>]",
|
|
189
|
+
" cimux register [--mailbox <harness/name> | --harness <name>]",
|
|
190
|
+
" cimux send --from <mailbox> --to <mailbox> --title <title> --summary <summary> --body <body> [--tags a,b]",
|
|
191
|
+
" cimux check --mailbox <harness/name> [--all]",
|
|
192
|
+
" cimux read --mailbox <harness/name> --id <context-id>",
|
|
193
|
+
" cimux ack --mailbox <harness/name> --id <context-id> [--note <note>]",
|
|
194
|
+
"",
|
|
195
|
+
"Examples:",
|
|
196
|
+
" cimux install --dry-run",
|
|
197
|
+
" cimux notify --harness codex",
|
|
198
|
+
" cimux check --mailbox claude/frontend-login"
|
|
199
|
+
].join("\n");
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=cimux-cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cimux-cli.js","sourceRoot":"","sources":["../../src/cli/cimux-cli.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
export { name, version } from "./version.js";
|
|
3
|
+
export declare function getProjectStage(): string;
|
|
4
|
+
export type { AckState, Artifacts, CodeSnippetArtifact, CommitArtifact, ContextPackage, ContextPackagePreview, CreateContextPackageInput, FileArtifact, FunctionArtifact, Mailbox, MailboxName, NormalizedCreateContextPackageInput, PullRequestArtifact, UrlArtifact } from "./model/context-package.js";
|
|
5
|
+
export type { AckContextPackageOptions, ContextPackageStore, ListInboxPreviewsOptions, MailboxStore } from "./storage/mailbox-store.js";
|
|
6
|
+
export type { RegisterMailboxInput, RegisterMailboxResult } from "./registration/mailbox-registration.js";
|
|
7
|
+
export { ackStateSchema, artifactsSchema, codeSnippetArtifactSchema, commitArtifactSchema, contextPackagePreviewSchema, contextPackageSchema, createContextPackagePreview, createContextPackageInputSchema, DEFAULT_INBOX_PREVIEW_LIMIT, fileArtifactSchema, functionArtifactSchema, MAX_INBOX_PREVIEW_LIMIT, mailboxNameSchema, mailboxSchema, normalizeInboxPreviewLimit, PREVIEW_SUMMARY_MAX_LENGTH, PREVIEW_TAG_MAX_COUNT, PREVIEW_TITLE_MAX_LENGTH, pullRequestArtifactSchema, urlArtifactSchema } from "./model/context-package.js";
|
|
8
|
+
export { ackContext, checkInbox, ContextPackageNotFoundError, createInboxNotification, MailboxAccessError, readContext, registerSession, sendContext } from "./service/cimux-mailbox-service.js";
|
|
9
|
+
export { runCimuxCli } from "./cli/cimux-cli.js";
|
|
10
|
+
export { applyInstallPlan, createInstallPlan } from "./install/cimux-install-plan.js";
|
|
11
|
+
export { createCimuxMcpServer, defaultDatabasePath, runCimuxMcpServer } from "./mcp/cimux-mcp-server.js";
|
|
12
|
+
export { resolveRuntimeMailbox } from "./runtime/mailbox-runtime.js";
|
|
13
|
+
export { inferMailboxName, registerMailboxInputSchema, registerMailbox } from "./registration/mailbox-registration.js";
|
|
14
|
+
export { SQLiteCimuxStore, UnknownMailboxError } from "./storage/sqlite-cimux-store.js";
|
|
15
|
+
export declare function isCliEntrypoint(argvPath?: string | undefined, modulePath?: string): boolean;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { runCimuxCli } from "./cli/cimux-cli.js";
|
|
5
|
+
export { name, version } from "./version.js";
|
|
6
|
+
export function getProjectStage() {
|
|
7
|
+
return "local-mvp";
|
|
8
|
+
}
|
|
9
|
+
export { ackStateSchema, artifactsSchema, codeSnippetArtifactSchema, commitArtifactSchema, contextPackagePreviewSchema, contextPackageSchema, createContextPackagePreview, createContextPackageInputSchema, DEFAULT_INBOX_PREVIEW_LIMIT, fileArtifactSchema, functionArtifactSchema, MAX_INBOX_PREVIEW_LIMIT, mailboxNameSchema, mailboxSchema, normalizeInboxPreviewLimit, PREVIEW_SUMMARY_MAX_LENGTH, PREVIEW_TAG_MAX_COUNT, PREVIEW_TITLE_MAX_LENGTH, pullRequestArtifactSchema, urlArtifactSchema } from "./model/context-package.js";
|
|
10
|
+
export { ackContext, checkInbox, ContextPackageNotFoundError, createInboxNotification, MailboxAccessError, readContext, registerSession, sendContext } from "./service/cimux-mailbox-service.js";
|
|
11
|
+
export { runCimuxCli } from "./cli/cimux-cli.js";
|
|
12
|
+
export { applyInstallPlan, createInstallPlan } from "./install/cimux-install-plan.js";
|
|
13
|
+
export { createCimuxMcpServer, defaultDatabasePath, runCimuxMcpServer } from "./mcp/cimux-mcp-server.js";
|
|
14
|
+
export { resolveRuntimeMailbox } from "./runtime/mailbox-runtime.js";
|
|
15
|
+
export { inferMailboxName, registerMailboxInputSchema, registerMailbox } from "./registration/mailbox-registration.js";
|
|
16
|
+
export { SQLiteCimuxStore, UnknownMailboxError } from "./storage/sqlite-cimux-store.js";
|
|
17
|
+
if (isCliEntrypoint()) {
|
|
18
|
+
process.exitCode = await runCimuxCli(process.argv.slice(2));
|
|
19
|
+
}
|
|
20
|
+
export function isCliEntrypoint(argvPath = process.argv[1], modulePath = fileURLToPath(import.meta.url)) {
|
|
21
|
+
if (!argvPath) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
// npm link and global installs usually invoke the bin through a symlink.
|
|
25
|
+
// Compare real paths so the published command still reaches runCimuxCli.
|
|
26
|
+
try {
|
|
27
|
+
return fs.realpathSync(argvPath) === fs.realpathSync(modulePath);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
// argv[1] may not be a resolvable path when embedded or bundled.
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGjD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,UAAU,eAAe;IAC7B,OAAO,WAAW,CAAC;AACrB,CAAC;AA6BD,OAAO,EACL,cAAc,EACd,eAAe,EACf,yBAAyB,EACzB,oBAAoB,EACpB,2BAA2B,EAC3B,oBAAoB,EACpB,2BAA2B,EAC3B,+BAA+B,EAC/B,2BAA2B,EAC3B,kBAAkB,EAClB,sBAAsB,EACtB,uBAAuB,EACvB,iBAAiB,EACjB,aAAa,EACb,0BAA0B,EAC1B,0BAA0B,EAC1B,qBAAqB,EACrB,wBAAwB,EACxB,yBAAyB,EACzB,iBAAiB,EAClB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,UAAU,EACV,UAAU,EACV,2BAA2B,EAC3B,uBAAuB,EACvB,kBAAkB,EAClB,WAAW,EACX,eAAe,EACf,WAAW,EACZ,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACtF,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EAClB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EACL,gBAAgB,EAChB,0BAA0B,EAC1B,eAAe,EAChB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAExF,IAAI,eAAe,EAAE,EAAE,CAAC;IACtB,OAAO,CAAC,QAAQ,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAC1B,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;IAE3C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,KAAK,CAAC;IACf,CAAC;IAED,yEAAyE;IACzE,yEAAyE;IACzE,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;IACnE,CAAC;IAAC,MAAM,CAAC;QACP,iEAAiE;QACjE,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const installPlanInputSchema: z.ZodObject<{
|
|
3
|
+
packageCommand: z.ZodDefault<z.ZodString>;
|
|
4
|
+
homeDirectory: z.ZodDefault<z.ZodString>;
|
|
5
|
+
}, "strip", z.ZodTypeAny, {
|
|
6
|
+
packageCommand: string;
|
|
7
|
+
homeDirectory: string;
|
|
8
|
+
}, {
|
|
9
|
+
packageCommand?: string | undefined;
|
|
10
|
+
homeDirectory?: string | undefined;
|
|
11
|
+
}>;
|
|
12
|
+
export type InstallPlanInput = z.input<typeof installPlanInputSchema>;
|
|
13
|
+
export type InstallPlanTarget = {
|
|
14
|
+
harness: "codex" | "claude";
|
|
15
|
+
path: string;
|
|
16
|
+
purpose: string;
|
|
17
|
+
format: "toml" | "json";
|
|
18
|
+
snippet: string;
|
|
19
|
+
};
|
|
20
|
+
export type InstallPlan = {
|
|
21
|
+
targets: InstallPlanTarget[];
|
|
22
|
+
};
|
|
23
|
+
export type InstallResult = {
|
|
24
|
+
path: string;
|
|
25
|
+
status: "created" | "updated" | "unchanged";
|
|
26
|
+
backupPath: string | null;
|
|
27
|
+
};
|
|
28
|
+
export declare function createInstallPlan(input?: InstallPlanInput): InstallPlan;
|
|
29
|
+
export declare function applyInstallPlan(plan: InstallPlan): InstallResult[];
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
export const installPlanInputSchema = z.object({
|
|
6
|
+
packageCommand: z.string().min(1).default("cimux"),
|
|
7
|
+
homeDirectory: z.string().min(1).default(os.homedir())
|
|
8
|
+
});
|
|
9
|
+
export function createInstallPlan(input = {}) {
|
|
10
|
+
const parsed = installPlanInputSchema.parse(input);
|
|
11
|
+
const codexHome = path.join(parsed.homeDirectory, ".codex");
|
|
12
|
+
const claudeHome = path.join(parsed.homeDirectory, ".claude");
|
|
13
|
+
// Codex has no hook system, so it only gets the MCP server.
|
|
14
|
+
return {
|
|
15
|
+
targets: [
|
|
16
|
+
{
|
|
17
|
+
harness: "codex",
|
|
18
|
+
path: path.join(codexHome, "config.toml"),
|
|
19
|
+
purpose: "Register the Cimux MCP server for Codex.",
|
|
20
|
+
format: "toml",
|
|
21
|
+
snippet: createCodexMcpSnippet(parsed.packageCommand)
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
harness: "claude",
|
|
25
|
+
path: path.join(claudeHome, "settings.json"),
|
|
26
|
+
purpose: "Run a zero-token inbox check on each user prompt. Empty inboxes emit no output.",
|
|
27
|
+
format: "json",
|
|
28
|
+
snippet: createClaudeHookSnippet(parsed.packageCommand)
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
harness: "claude",
|
|
32
|
+
// Claude Code reads user-scope MCP servers from ~/.claude.json.
|
|
33
|
+
path: path.join(parsed.homeDirectory, ".claude.json"),
|
|
34
|
+
purpose: "Register the Cimux MCP server for Claude Code (user scope).",
|
|
35
|
+
format: "json",
|
|
36
|
+
snippet: createClaudeMcpSnippet(parsed.packageCommand)
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export function applyInstallPlan(plan) {
|
|
42
|
+
return plan.targets.map((target) => applyInstallTarget(target));
|
|
43
|
+
}
|
|
44
|
+
function applyInstallTarget(target) {
|
|
45
|
+
fs.mkdirSync(path.dirname(target.path), { recursive: true });
|
|
46
|
+
if (target.format === "toml") {
|
|
47
|
+
return applyTomlTarget(target);
|
|
48
|
+
}
|
|
49
|
+
return applyJsonTarget(target);
|
|
50
|
+
}
|
|
51
|
+
function applyTomlTarget(target) {
|
|
52
|
+
const existing = readTextIfExists(target.path);
|
|
53
|
+
if (existing?.includes("[mcp_servers.cimux]")) {
|
|
54
|
+
return {
|
|
55
|
+
path: target.path,
|
|
56
|
+
status: "unchanged",
|
|
57
|
+
backupPath: null
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
const backupPath = existing === null ? null : writeBackup(target.path, existing);
|
|
61
|
+
const next = existing === null ? target.snippet : appendBlock(existing, target.snippet);
|
|
62
|
+
fs.writeFileSync(target.path, next, "utf8");
|
|
63
|
+
return {
|
|
64
|
+
path: target.path,
|
|
65
|
+
status: existing === null ? "created" : "updated",
|
|
66
|
+
backupPath
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function applyJsonTarget(target) {
|
|
70
|
+
const existingText = readTextIfExists(target.path);
|
|
71
|
+
const existingValue = existingText === null ? {} : parseJsonObject(existingText, target.path);
|
|
72
|
+
const snippetValue = parseJsonObject(target.snippet, target.path);
|
|
73
|
+
const mergedValue = mergeJson(existingValue, snippetValue);
|
|
74
|
+
const nextText = `${JSON.stringify(mergedValue, null, 2)}\n`;
|
|
75
|
+
if (existingText === nextText) {
|
|
76
|
+
return {
|
|
77
|
+
path: target.path,
|
|
78
|
+
status: "unchanged",
|
|
79
|
+
backupPath: null
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
const backupPath = existingText === null ? null : writeBackup(target.path, existingText);
|
|
83
|
+
fs.writeFileSync(target.path, nextText, "utf8");
|
|
84
|
+
return {
|
|
85
|
+
path: target.path,
|
|
86
|
+
status: existingText === null ? "created" : "updated",
|
|
87
|
+
backupPath
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function mergeJson(existing, incoming) {
|
|
91
|
+
const merged = { ...existing };
|
|
92
|
+
for (const [key, incomingValue] of Object.entries(incoming)) {
|
|
93
|
+
const existingValue = merged[key];
|
|
94
|
+
if (isPlainObject(existingValue) && isPlainObject(incomingValue)) {
|
|
95
|
+
merged[key] = mergeJson(existingValue, incomingValue);
|
|
96
|
+
}
|
|
97
|
+
else if (Array.isArray(existingValue) && Array.isArray(incomingValue)) {
|
|
98
|
+
merged[key] = mergeArray(existingValue, incomingValue);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
merged[key] = incomingValue;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return merged;
|
|
105
|
+
}
|
|
106
|
+
function mergeArray(existing, incoming) {
|
|
107
|
+
const merged = [...existing];
|
|
108
|
+
const seen = new Set(existing.map(stableStringify));
|
|
109
|
+
for (const item of incoming) {
|
|
110
|
+
const key = stableStringify(item);
|
|
111
|
+
if (!seen.has(key)) {
|
|
112
|
+
merged.push(item);
|
|
113
|
+
seen.add(key);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return merged;
|
|
117
|
+
}
|
|
118
|
+
function readTextIfExists(filePath) {
|
|
119
|
+
if (!fs.existsSync(filePath)) {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
return fs.readFileSync(filePath, "utf8");
|
|
123
|
+
}
|
|
124
|
+
function parseJsonObject(value, filePath) {
|
|
125
|
+
const parsed = JSON.parse(value);
|
|
126
|
+
if (!isPlainObject(parsed)) {
|
|
127
|
+
throw new Error(`Expected JSON object in ${filePath}`);
|
|
128
|
+
}
|
|
129
|
+
return parsed;
|
|
130
|
+
}
|
|
131
|
+
function writeBackup(filePath, content) {
|
|
132
|
+
const backupPath = `${filePath}.cimux.bak`;
|
|
133
|
+
fs.writeFileSync(backupPath, content, "utf8");
|
|
134
|
+
return backupPath;
|
|
135
|
+
}
|
|
136
|
+
function appendBlock(existing, block) {
|
|
137
|
+
const trimmed = existing.trimEnd();
|
|
138
|
+
return `${trimmed}\n\n${block}`;
|
|
139
|
+
}
|
|
140
|
+
function isPlainObject(value) {
|
|
141
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
142
|
+
}
|
|
143
|
+
function stableStringify(value) {
|
|
144
|
+
if (!isPlainObject(value)) {
|
|
145
|
+
return JSON.stringify(value);
|
|
146
|
+
}
|
|
147
|
+
const sorted = {};
|
|
148
|
+
for (const key of Object.keys(value).sort()) {
|
|
149
|
+
sorted[key] = value[key];
|
|
150
|
+
}
|
|
151
|
+
return JSON.stringify(sorted);
|
|
152
|
+
}
|
|
153
|
+
function createCodexMcpSnippet(packageCommand) {
|
|
154
|
+
return `[mcp_servers.cimux]
|
|
155
|
+
command = "${packageCommand}"
|
|
156
|
+
args = ["mcp"]
|
|
157
|
+
startup_timeout_sec = 10
|
|
158
|
+
tool_timeout_sec = 60
|
|
159
|
+
`;
|
|
160
|
+
}
|
|
161
|
+
function createClaudeHookSnippet(packageCommand) {
|
|
162
|
+
return JSON.stringify({
|
|
163
|
+
hooks: {
|
|
164
|
+
UserPromptSubmit: [
|
|
165
|
+
{
|
|
166
|
+
hooks: [
|
|
167
|
+
{
|
|
168
|
+
type: "command",
|
|
169
|
+
command: `${packageCommand} notify --harness claude`
|
|
170
|
+
}
|
|
171
|
+
]
|
|
172
|
+
}
|
|
173
|
+
]
|
|
174
|
+
}
|
|
175
|
+
}, null, 2);
|
|
176
|
+
}
|
|
177
|
+
function createClaudeMcpSnippet(packageCommand) {
|
|
178
|
+
return JSON.stringify({
|
|
179
|
+
mcpServers: {
|
|
180
|
+
cimux: {
|
|
181
|
+
command: packageCommand,
|
|
182
|
+
args: ["mcp"]
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}, null, 2);
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=cimux-install-plan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cimux-install-plan.js","sourceRoot":"","sources":["../../src/install/cimux-install-plan.ts"],"names":[],"mappings":"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"}
|