unfairly 0.5.1 → 0.6.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.
Files changed (43) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +16 -7
  3. package/dist/cmd/init.d.ts +2 -3
  4. package/dist/cmd/init.d.ts.map +1 -1
  5. package/dist/cmd/init.js +60 -44
  6. package/dist/cmd/init.js.map +1 -1
  7. package/dist/cmd/pull.d.ts.map +1 -1
  8. package/dist/cmd/pull.js +16 -2
  9. package/dist/cmd/pull.js.map +1 -1
  10. package/dist/cmd/setup.d.ts +19 -19
  11. package/dist/cmd/setup.d.ts.map +1 -1
  12. package/dist/cmd/setup.js +143 -84
  13. package/dist/cmd/setup.js.map +1 -1
  14. package/dist/cmd/status-card.d.ts +2 -0
  15. package/dist/cmd/status-card.d.ts.map +1 -0
  16. package/dist/cmd/status-card.js +156 -0
  17. package/dist/cmd/status-card.js.map +1 -0
  18. package/dist/cmd/status.d.ts.map +1 -1
  19. package/dist/cmd/status.js +3 -0
  20. package/dist/cmd/status.js.map +1 -1
  21. package/dist/hosts/claude-desktop.d.ts +47 -0
  22. package/dist/hosts/claude-desktop.d.ts.map +1 -0
  23. package/dist/hosts/claude-desktop.js +83 -0
  24. package/dist/hosts/claude-desktop.js.map +1 -0
  25. package/dist/index.js +58 -27
  26. package/dist/index.js.map +1 -1
  27. package/dist/sync/repo-root.d.ts +7 -0
  28. package/dist/sync/repo-root.d.ts.map +1 -0
  29. package/dist/sync/repo-root.js +24 -0
  30. package/dist/sync/repo-root.js.map +1 -0
  31. package/dist/sync/stitch-claude-md.d.ts +9 -0
  32. package/dist/sync/stitch-claude-md.d.ts.map +1 -0
  33. package/dist/sync/stitch-claude-md.js +48 -0
  34. package/dist/sync/stitch-claude-md.js.map +1 -0
  35. package/dist/ui/colors.d.ts +17 -0
  36. package/dist/ui/colors.d.ts.map +1 -0
  37. package/dist/ui/colors.js +28 -0
  38. package/dist/ui/colors.js.map +1 -0
  39. package/dist/ui/screens.d.ts +44 -0
  40. package/dist/ui/screens.d.ts.map +1 -0
  41. package/dist/ui/screens.js +135 -0
  42. package/dist/ui/screens.js.map +1 -0
  43. package/package.json +32 -7
package/dist/cmd/setup.js CHANGED
@@ -2,117 +2,178 @@ import { browserAuthFlow } from "../auth/browser-flow.js";
2
2
  import { setToken } from "../sync/credentials.js";
3
3
  import { writeShellEnv } from "../hosts/shell-env.js";
4
4
  import { configureCodex } from "../hosts/codex.js";
5
- import { configureClaudeCode, } from "../hosts/claude-code.js";
5
+ import { configureClaudeCode } from "../hosts/claude-code.js";
6
+ import { configureClaudeDesktop } from "../hosts/claude-desktop.js";
7
+ import { banner, stepHeader, result, divider, defaultOpts } from "../ui/screens.js";
8
+ import { brand } from "../ui/colors.js";
6
9
  const DEFAULT_API = "https://app.unfairly.ai";
7
- /**
8
- * `unfairly setup` — one-shot agent host installer.
9
- *
10
- * 1. Browser OAuth → mint mcp_* token, cache in keychain.
11
- * 2. Append/replace a sentinel-marked block in the user's shell rcfile
12
- * (~/.zshenv on zsh, ~/.bash_profile on bash) with UNFAIRLY_MCP_TOKEN
13
- * + UNFAIRLY_TOKEN exports.
14
- * 3. Patch ~/.codex/config.toml with [mcp_servers.unfairly] including
15
- * bearer_token_env_var. Skips silently if Codex isn't installed.
16
- * 4. Register with Claude Code via `claude mcp add` if the binary is
17
- * in PATH. Non-destructive — tolerates "already exists" as success.
18
- * 5. Verify the new token works by calling /api/mcp with it. If the
19
- * handshake fails, print clear remediation instructions instead of
20
- * declaring victory.
21
- *
22
- * Idempotent — safe to re-run any time. Each write replaces in place
23
- * rather than duplicating.
24
- */
25
- export async function runSetup() {
10
+ export async function runSetup(opts = {}) {
26
11
  const apiUrl = process.env.UNFAIRLY_API_URL ?? DEFAULT_API;
27
- console.error("✦ unfairly setup");
28
- console.error("");
29
- // Step 1: browser auth
30
- console.error("[1/4] Authorizing in browser...");
12
+ const ui = defaultOpts();
13
+ const c = brand({ enabled: ui.color });
14
+ const write = (s) => process.stderr.write(`${s}\n`);
15
+ write(banner(ui));
16
+ write("");
17
+ write(`${c.coral("▶")} player 2 booting…`);
18
+ write("");
19
+ // [1/5] AUTH
20
+ write(stepHeader(1, 5, "AUTH", ui));
21
+ write(result("progress", "browser opening — click to authorize", ui));
31
22
  const token = await browserAuthFlow(apiUrl, { tokenName: "unfairly setup" });
32
23
  if (!token) {
33
- console.error(" ✗ Browser flow timed out or was cancelled. Run `unfairly setup` again.");
24
+ write(result("err", "browser flow cancelled or timed out. Run `unfairly` again.", ui));
34
25
  process.exit(1);
35
26
  }
36
27
  await setToken(token);
37
- console.error(" ✓ Token minted and cached in keychain");
38
- console.error("");
39
- // Step 2: shell env
40
- console.error("[2/4] Writing shell config...");
28
+ write(result("ok", `token minted (${token.slice(0, 8)}…) · cached in keychain`, ui));
29
+ write("");
30
+ // [2/5] SHELL ENV
31
+ write(stepHeader(2, 5, "SHELL ENV", ui));
41
32
  const env = await writeShellEnv(token);
42
33
  if (env.shell === "unknown") {
43
- console.error(" ⚠ Couldn't detect your shell ($SHELL is empty or non-zsh/bash).");
44
- console.error(" Add this to your shell config manually:");
45
- console.error(` export UNFAIRLY_MCP_TOKEN=${token}`);
34
+ write(result("warn", "couldn't detect $SHELL — add manually: export UNFAIRLY_MCP_TOKEN=…", ui));
46
35
  }
47
36
  else {
48
- console.error(` ✓ ${env.path} (${env.action}) [${env.shell}]`);
37
+ write(result("ok", `${env.path} · added UNFAIRLY_MCP_TOKEN`, ui));
49
38
  }
50
- console.error("");
51
- // Step 3: hosts
52
- console.error("[3/4] Configuring agent hosts...");
53
- const codex = await configureCodex(apiUrl);
54
- console.error(` ${formatCodex(codex)}`);
39
+ write("");
40
+ // [3/5] CLAUDE DESKTOP
41
+ // We track host-write errors but DON'T early-exit — a user with a malformed
42
+ // Claude Desktop config should still get Claude Code + Codex wired (the
43
+ // partial success path is far better than zero hosts). We exit non-zero
44
+ // at the end of setup so the user knows something needs attention.
45
+ write(stepHeader(3, 5, "CLAUDE DESKTOP", ui));
46
+ const cd = await configureClaudeDesktop(apiUrl);
47
+ write(formatClaudeDesktop(cd, ui));
48
+ write("");
49
+ // [4/5] CLAUDE CODE · CODEX
50
+ write(stepHeader(4, 5, "CLAUDE CODE · CODEX", ui));
55
51
  const cc = await configureClaudeCode(apiUrl);
56
- console.error(` ${formatClaudeCode(cc)}`);
57
- console.error("");
58
- // Step 4: verify
59
- console.error("[4/4] Verifying token works against /api/mcp...");
52
+ write(formatClaudeCode(cc, ui));
53
+ const codex = await configureCodex(apiUrl);
54
+ write(formatCodex(codex, ui));
55
+ write("");
56
+ // [5/5] HANDSHAKE
57
+ write(stepHeader(5, 5, "HANDSHAKE", ui));
60
58
  const verified = await verifyToken(apiUrl, token);
61
- if (verified.ok) {
62
- console.error(" ✓ MCP handshake succeeded");
63
- }
64
- else {
65
- console.error(` ✗ MCP handshake FAILED — ${verified.message}`);
66
- console.error(" The token was saved, but something is wrong. Check that you signed in");
67
- console.error(" as an internal-team member (anyone outside the allowlist gets denied).");
59
+ if (!verified.ok) {
60
+ write(result("err", `/api/mcp rejected the token — ${verified.message}`, ui));
68
61
  process.exit(2);
69
62
  }
70
- console.error("");
71
- // Next steps
72
- console.error("✓ Setup complete.");
73
- console.error("");
74
- console.error("Next:");
75
- console.error(" 1. Open a NEW terminal (existing shells don't have $UNFAIRLY_MCP_TOKEN yet).");
76
- if (codex.status === "configured" || cc.status === "configured") {
77
- console.error(" 2. Restart any running agent host (Codex, Claude Code) so it reloads the MCP config.");
78
- console.error(" 3. Send any prompt — the agent will auto-fire `enter_org` and show your vaults.");
63
+ write(result("ok", "/api/mcp accepted the token", ui));
64
+ write("");
65
+ write(divider(ui));
66
+ write("");
67
+ // If any host write surfaced a real error (not "not-installed"), warn the
68
+ // user clearly and defer a non-zero exit until after init has had a chance
69
+ // to run — that way they at least get a wired token + workspace bind even
70
+ // if one host is busted. The exit happens at the very end of runSetup.
71
+ const hostErrors = [];
72
+ if (cd.status === "error")
73
+ hostErrors.push(`Claude Desktop: ${cd.message}`);
74
+ if (cc.status === "error")
75
+ hostErrors.push(`Claude Code: ${cc.message}`);
76
+ if (codex.status === "error")
77
+ hostErrors.push(`Codex: ${codex.message}`);
78
+ if (hostErrors.length > 0) {
79
+ write(result("warn", `${hostErrors.length} host(s) failed to wire — fix and re-run \`unfairly setup\`:`, ui));
80
+ for (const m of hostErrors)
81
+ write(result("warn", ` ${m}`, ui));
82
+ write("");
79
83
  }
80
- else {
81
- console.error(" 2. Install Codex or Claude Code, then re-run `unfairly setup` to wire them up.");
84
+ // Chain into init when caller asked AND cwd is a repo.
85
+ let workspaceBound = null;
86
+ if (opts.chainInit) {
87
+ const { findRepoRoot } = await import("../sync/repo-root.js");
88
+ const repoRoot = await findRepoRoot(process.cwd());
89
+ if (repoRoot) {
90
+ write(`${c.coral("▶")} repo detected: ${c.dim(repoRoot)}`);
91
+ let shouldBind = Boolean(opts.yes);
92
+ if (!opts.yes) {
93
+ const { createInterface } = await import("node:readline/promises");
94
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
95
+ const ans = await rl.question(` ${c.dim("◆")} Bind .unfairly/ here? [Y/n] `);
96
+ rl.close();
97
+ const v = ans.trim().toLowerCase();
98
+ shouldBind = v === "" || v === "y" || v === "yes";
99
+ }
100
+ if (shouldBind) {
101
+ const { runInit } = await import("./init.js");
102
+ await runInit({ assumeAuthed: true, yes: true, token });
103
+ try {
104
+ const { readManifest } = await import("../sync/manifest.js");
105
+ const m = await readManifest(process.cwd());
106
+ if (m) {
107
+ const vaultCount = Object.keys(m.vaults).length;
108
+ const docCount = Object.values(m.vaults).reduce((s, v) => s + Object.keys(v.docs).length, 0);
109
+ workspaceBound = { vaultCount, docCount };
110
+ }
111
+ }
112
+ catch {
113
+ // best-effort summary
114
+ }
115
+ }
116
+ else {
117
+ write(result("skip", "skipped workspace bind — re-run `unfairly` in any repo to bind later", ui));
118
+ }
119
+ }
120
+ }
121
+ // Hand-off card
122
+ const { handoffCard } = await import("../ui/screens.js");
123
+ const card = handoffCard({
124
+ vaultCount: workspaceBound?.vaultCount ?? 0,
125
+ docCount: workspaceBound?.docCount ?? 0,
126
+ recentMove: null,
127
+ hint: "open Claude Desktop — say anything",
128
+ }, ui);
129
+ write(card);
130
+ write("");
131
+ write(` ${c.dim("re-run")} ${c.bold("unfairly")} ${c.dim("anytime to see what your team's up to.")}`);
132
+ // Deferred non-zero exit if any host failed to write. The user got the
133
+ // partial-success card with errors listed above; CI/scripts can still
134
+ // detect the failure via the exit code.
135
+ if (hostErrors.length > 0) {
136
+ process.exit(2);
82
137
  }
83
- console.error("");
84
- console.error("Optional — pull all vaults to local markdown for fast filesystem reads:");
85
- console.error(" cd <your-workspace> && unfairly init");
138
+ return {
139
+ ok: true,
140
+ token,
141
+ hosts: { claudeDesktop: cd, claudeCode: cc, codex },
142
+ };
86
143
  }
87
- function formatCodex(r) {
144
+ // --- formatters ---
145
+ function formatClaudeDesktop(r, ui) {
88
146
  switch (r.status) {
89
147
  case "configured":
90
- return `✓ Codex (${r.path}) — ${r.action}`;
148
+ return result("ok", `${r.path}`, ui);
91
149
  case "not-installed":
92
- return `· Codex not detected at ${r.path} (skipped — install Codex and re-run if you want it)`;
150
+ return result("skip", `Claude Desktop not detected (${r.path}) — install and re-run`, ui);
93
151
  case "error":
94
- return `✗ Codex — ${r.message}`;
152
+ return result("err", `${r.path} — ${r.message}`, ui);
95
153
  }
96
154
  }
97
- function formatClaudeCode(r) {
155
+ function formatClaudeCode(r, ui) {
98
156
  switch (r.status) {
99
157
  case "configured":
100
- return `✓ Claude Code — ${r.message}`;
158
+ return result("ok", "claude mcp add unfairly", ui);
101
159
  case "already-registered":
102
- return `· Claude Code — ${r.message}`;
160
+ return result("skip", "claude mcp · already registered (left as-is)", ui);
103
161
  case "not-installed":
104
- return "· Claude Code CLI not detected (skipped)";
162
+ return result("skip", "Claude Code (`claude` binary) not detected", ui);
105
163
  case "error":
106
- return `✗ Claude Code — ${r.message}`;
164
+ return result("err", `claude mcp add — ${r.message}`, ui);
165
+ }
166
+ }
167
+ function formatCodex(r, ui) {
168
+ switch (r.status) {
169
+ case "configured":
170
+ return result("ok", `${r.path}`, ui);
171
+ case "not-installed":
172
+ return result("skip", `Codex not detected at ${r.path}`, ui);
173
+ case "error":
174
+ return result("err", `${r.path} — ${r.message}`, ui);
107
175
  }
108
176
  }
109
- /**
110
- * Hit /api/mcp with the new token to confirm the full chain works:
111
- * token row written, /api/mcp accepts it, handshake completes.
112
- *
113
- * We do an MCP `initialize` — that's the cheapest call that exercises
114
- * the auth path end-to-end without touching DB-heavy tools.
115
- */
116
177
  async function verifyToken(apiUrl, token) {
117
178
  const url = `${apiUrl.replace(/\/$/, "")}/api/mcp`;
118
179
  try {
@@ -130,13 +191,12 @@ async function verifyToken(apiUrl, token) {
130
191
  params: {
131
192
  protocolVersion: "2024-11-05",
132
193
  capabilities: {},
133
- clientInfo: { name: "unfairly-setup", version: "0.3.0" },
194
+ clientInfo: { name: "unfairly-setup", version: "0.6.0" },
134
195
  },
135
196
  }),
136
197
  });
137
- if (res.status !== 200) {
198
+ if (res.status !== 200)
138
199
  return { ok: false, message: `HTTP ${res.status}` };
139
- }
140
200
  const text = await res.text();
141
201
  if (!text.includes('"result"') || !text.includes("protocolVersion")) {
142
202
  return { ok: false, message: "unexpected response shape" };
@@ -144,8 +204,7 @@ async function verifyToken(apiUrl, token) {
144
204
  return { ok: true };
145
205
  }
146
206
  catch (e) {
147
- const err = e;
148
- return { ok: false, message: err.message };
207
+ return { ok: false, message: e.message };
149
208
  }
150
209
  }
151
210
  //# sourceMappingURL=setup.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/cmd/setup.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/cmd/setup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function runStatusCard(): Promise<void>;
2
+ //# sourceMappingURL=status-card.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status-card.d.ts","sourceRoot":"","sources":["../../src/cmd/status-card.ts"],"names":[],"mappings":"AAUA,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CA+BnD"}
@@ -0,0 +1,156 @@
1
+ import { promises as fs } from "node:fs";
2
+ import path from "node:path";
3
+ import os from "node:os";
4
+ import { readManifest } from "../sync/manifest.js";
5
+ import { getToken } from "../sync/credentials.js";
6
+ import { configPath as claudeDesktopPath } from "../hosts/claude-desktop.js";
7
+ import { banner, statusCard, defaultOpts } from "../ui/screens.js";
8
+ const DEFAULT_API = "https://app.unfairly.ai";
9
+ export async function runStatusCard() {
10
+ const cwd = process.cwd();
11
+ const ui = defaultOpts();
12
+ const write = (s) => process.stdout.write(`${s}\n`);
13
+ const apiUrl = process.env.UNFAIRLY_API_URL ?? DEFAULT_API;
14
+ const hosts = {
15
+ claudeDesktop: await checkClaudeDesktop(),
16
+ claudeCode: await checkClaudeCode(),
17
+ codex: await checkCodex(),
18
+ };
19
+ const manifest = await readManifest(cwd);
20
+ const workspace = manifest
21
+ ? {
22
+ cwd,
23
+ vaultCount: Object.keys(manifest.vaults).length,
24
+ docCount: Object.values(manifest.vaults).reduce((s, v) => s + Object.keys(v.docs).length, 0),
25
+ lastPulledAt: latestPullTimestamp(manifest),
26
+ }
27
+ : null;
28
+ // Recent moves: best-effort enter_org. Silent on failure.
29
+ const recent = await fetchRecentMoves(apiUrl).catch(() => []);
30
+ const state = { hosts, workspace, recent };
31
+ write(banner(ui));
32
+ write("");
33
+ write(statusCard(state, ui));
34
+ write("");
35
+ }
36
+ async function checkClaudeDesktop() {
37
+ // "wired" requires the full canonical block: type=http, url ending in
38
+ // /api/mcp, and a bearer-style Authorization header. A stale entry with
39
+ // the right URL but wrong transport or missing auth is "rotted", not wired.
40
+ const p = claudeDesktopPath();
41
+ if (!p)
42
+ return "missing";
43
+ try {
44
+ const raw = await fs.readFile(p, "utf8");
45
+ const parsed = JSON.parse(raw);
46
+ const u = parsed?.mcpServers?.unfairly;
47
+ if (!u)
48
+ return "missing";
49
+ const typeOk = u.type === "http";
50
+ const urlOk = typeof u.url === "string" && u.url.endsWith("/api/mcp");
51
+ const auth = u.headers?.Authorization;
52
+ const authOk = typeof auth === "string" && /^Bearer\s+\S+/.test(auth);
53
+ if (typeOk && urlOk && authOk)
54
+ return "wired";
55
+ return "rotted";
56
+ }
57
+ catch {
58
+ return "missing";
59
+ }
60
+ }
61
+ /**
62
+ * Claude Code stores MCP servers in a per-user JSON config.
63
+ * We do NOT shell out to the claude binary — file inspection is faster and
64
+ * does not depend on the claude binary being on PATH.
65
+ */
66
+ async function checkClaudeCode() {
67
+ // Inspect only:
68
+ // 1. Global mcpServers.unfairly (machine-wide registration)
69
+ // 2. projects[cwd].mcpServers.unfairly (this-workspace registration)
70
+ // Do NOT walk every project entry — a sibling project's "unfairly" entry
71
+ // is not evidence the current workspace is wired.
72
+ const home = os.homedir();
73
+ const cwd = process.cwd();
74
+ const candidates = [
75
+ path.join(home, ".claude.json"),
76
+ path.join(home, ".config", "claude", "config.json"),
77
+ ];
78
+ for (const p of candidates) {
79
+ try {
80
+ const raw = await fs.readFile(p, "utf8");
81
+ const parsed = JSON.parse(raw);
82
+ // Global scope
83
+ if (parsed?.mcpServers?.unfairly)
84
+ return "wired";
85
+ // Workspace scope: keyed by absolute path
86
+ const workspace = parsed?.projects?.[cwd];
87
+ if (workspace?.mcpServers?.unfairly)
88
+ return "wired";
89
+ }
90
+ catch {
91
+ // file missing or unparseable; try next candidate
92
+ }
93
+ }
94
+ return "missing";
95
+ }
96
+ async function checkCodex() {
97
+ const p = path.join(os.homedir(), ".codex", "config.toml");
98
+ try {
99
+ const raw = await fs.readFile(p, "utf8");
100
+ return /^\[mcp_servers\.unfairly\]/m.test(raw) ? "wired" : "missing";
101
+ }
102
+ catch {
103
+ return "missing";
104
+ }
105
+ }
106
+ function latestPullTimestamp(manifest) {
107
+ let latest = null;
108
+ for (const v of Object.values(manifest.vaults)) {
109
+ if (v.last_pulled_at && (!latest || v.last_pulled_at > latest))
110
+ latest = v.last_pulled_at;
111
+ }
112
+ return latest;
113
+ }
114
+ async function fetchRecentMoves(apiUrl) {
115
+ const token = await getToken();
116
+ if (!token)
117
+ return [];
118
+ const url = `${apiUrl.replace(/\/$/, "")}/api/mcp`;
119
+ try {
120
+ const res = await fetch(url, {
121
+ method: "POST",
122
+ headers: {
123
+ Authorization: `Bearer ${token}`,
124
+ "Content-Type": "application/json",
125
+ Accept: "application/json, text/event-stream",
126
+ },
127
+ body: JSON.stringify({
128
+ jsonrpc: "2.0",
129
+ id: 1,
130
+ method: "tools/call",
131
+ params: { name: "enter_org", arguments: {} },
132
+ }),
133
+ });
134
+ if (res.status !== 200)
135
+ return [];
136
+ const text = await res.text();
137
+ // The response is text-formatted. Parse the "RECENT MOVES" block lines like:
138
+ // **bob** · `unfairly-growth` · 1m ago · other
139
+ const moves = [];
140
+ const re = /\*\*(?<who>[^*]+)\*\*\s*·\s*`(?<room>[^`]+)`\s*·\s*(?<ago>[^·\n]+)·/g;
141
+ let m;
142
+ while ((m = re.exec(text)) && moves.length < 5) {
143
+ moves.push({
144
+ who: m.groups.who.trim(),
145
+ room: m.groups.room.trim(),
146
+ ago: m.groups.ago.trim(),
147
+ title: "—",
148
+ });
149
+ }
150
+ return moves;
151
+ }
152
+ catch {
153
+ return [];
154
+ }
155
+ }
156
+ //# sourceMappingURL=status-card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status-card.js","sourceRoot":"","sources":["../../src/cmd/status-card.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/cmd/status.ts"],"names":[],"mappings":"AAIA,wBAAsB,SAAS,kBAqB9B"}
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/cmd/status.ts"],"names":[],"mappings":"AAKA,wBAAsB,SAAS,kBAuB9B"}
@@ -1,7 +1,10 @@
1
1
  import path from "node:path";
2
2
  import { readManifest } from "../sync/manifest.js";
3
3
  import { computeSha, readDocRaw } from "../sync/files.js";
4
+ import { banner, defaultOpts } from "../ui/screens.js";
4
5
  export async function runStatus() {
6
+ const ui = defaultOpts();
7
+ process.stdout.write(`${banner(ui)}\n\n`);
5
8
  const cwd = process.cwd();
6
9
  const manifest = await readManifest(cwd);
7
10
  if (!manifest) {
@@ -1 +1 @@
1
- {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/cmd/status.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE1D,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC,CAAC;IACzC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,CAAC,KAAK,CAAC,iDAAiD,CAAC,CAAC;QACjE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACxD,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,KAAK,MAAM,CAAC,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/C,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;gBACtE,IAAI,UAAU,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,GAAG;oBAAE,QAAQ,EAAE,CAAC;YAChD,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;QACZ,CAAC;QACD,MAAM,MAAM,GAAG,CAAC,CAAC,cAAc,IAAI,OAAO,CAAC;QAC3C,MAAM,MAAM,GAAG,CAAC,CAAC,cAAc,IAAI,OAAO,CAAC;QAC3C,OAAO,CAAC,GAAG,CACT,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,WAAW,MAAM,aAAa,MAAM,eAAe,QAAQ,EAAE,CAChF,CAAC;IACJ,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/cmd/status.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEvD,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,MAAM,EAAE,GAAG,WAAW,EAAE,CAAC;IACzB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;IAC1C,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC,CAAC;IACzC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,CAAC,KAAK,CAAC,iDAAiD,CAAC,CAAC;QACjE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACxD,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,KAAK,MAAM,CAAC,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/C,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;gBACtE,IAAI,UAAU,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,GAAG;oBAAE,QAAQ,EAAE,CAAC;YAChD,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;QACZ,CAAC;QACD,MAAM,MAAM,GAAG,CAAC,CAAC,cAAc,IAAI,OAAO,CAAC;QAC3C,MAAM,MAAM,GAAG,CAAC,CAAC,cAAc,IAAI,OAAO,CAAC;QAC3C,OAAO,CAAC,GAAG,CACT,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,WAAW,MAAM,aAAa,MAAM,eAAe,QAAQ,EAAE,CAChF,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,47 @@
1
+ export type ClaudeDesktopResult = {
2
+ status: "configured";
3
+ path: string;
4
+ action: "created" | "updated";
5
+ } | {
6
+ status: "not-installed";
7
+ path: string;
8
+ } | {
9
+ status: "error";
10
+ path: string;
11
+ message: string;
12
+ };
13
+ export type UnfairlyEntry = {
14
+ type: "http";
15
+ url: string;
16
+ headers: {
17
+ Authorization: string;
18
+ };
19
+ };
20
+ type ConfigShape = {
21
+ mcpServers?: Record<string, unknown>;
22
+ [key: string]: unknown;
23
+ };
24
+ /**
25
+ * Path to Claude Desktop's config file by platform. Returns null on Linux
26
+ * (Claude Desktop is Mac/Windows only per official docs).
27
+ */
28
+ export declare function configPath(): string | null;
29
+ export declare function buildEntry(apiUrl: string): UnfairlyEntry;
30
+ /**
31
+ * Merge our canonical unfairly entry into an existing config object.
32
+ * - Preserves other mcpServers
33
+ * - Replaces any existing unfairly entry
34
+ * - Preserves all unrelated top-level keys
35
+ */
36
+ export declare function mergeIntoConfig(existing: ConfigShape, apiUrl: string): {
37
+ mcpServers: Record<string, unknown>;
38
+ } & ConfigShape;
39
+ /**
40
+ * Patch Claude Desktop's config to wire the Unfairly MCP server.
41
+ * - If config file does not exist → not-installed (do NOT create).
42
+ * - If file exists but is malformed JSON → error (don't overwrite precious config).
43
+ * - Otherwise → merge canonical block, write back.
44
+ */
45
+ export declare function configureClaudeDesktop(apiUrl: string): Promise<ClaudeDesktopResult>;
46
+ export {};
47
+ //# sourceMappingURL=claude-desktop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-desktop.d.ts","sourceRoot":"","sources":["../../src/hosts/claude-desktop.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,mBAAmB,GAC3B;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,SAAS,GAAG,SAAS,CAAA;CAAE,GACrE;IAAE,MAAM,EAAE,eAAe,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACzC;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE;QAAE,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC;CACpC,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAEF;;;GAGG;AACH,wBAAgB,UAAU,IAAI,MAAM,GAAG,IAAI,CAU1C;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CAOxD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,WAAW,EACrB,MAAM,EAAE,MAAM,GACb;IAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAAG,WAAW,CAMvD;AAED;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAqCzF"}