unfairly 0.5.1 → 0.6.1

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 (47) hide show
  1. package/CHANGELOG.md +15 -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 +267 -87
  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-code.d.ts +48 -10
  22. package/dist/hosts/claude-code.d.ts.map +1 -1
  23. package/dist/hosts/claude-code.js +102 -29
  24. package/dist/hosts/claude-code.js.map +1 -1
  25. package/dist/hosts/claude-desktop.d.ts +47 -0
  26. package/dist/hosts/claude-desktop.d.ts.map +1 -0
  27. package/dist/hosts/claude-desktop.js +88 -0
  28. package/dist/hosts/claude-desktop.js.map +1 -0
  29. package/dist/index.js +58 -27
  30. package/dist/index.js.map +1 -1
  31. package/dist/sync/repo-root.d.ts +7 -0
  32. package/dist/sync/repo-root.d.ts.map +1 -0
  33. package/dist/sync/repo-root.js +24 -0
  34. package/dist/sync/repo-root.js.map +1 -0
  35. package/dist/sync/stitch-claude-md.d.ts +9 -0
  36. package/dist/sync/stitch-claude-md.d.ts.map +1 -0
  37. package/dist/sync/stitch-claude-md.js +48 -0
  38. package/dist/sync/stitch-claude-md.js.map +1 -0
  39. package/dist/ui/colors.d.ts +17 -0
  40. package/dist/ui/colors.d.ts.map +1 -0
  41. package/dist/ui/colors.js +28 -0
  42. package/dist/ui/colors.js.map +1 -0
  43. package/dist/ui/screens.d.ts +44 -0
  44. package/dist/ui/screens.d.ts.map +1 -0
  45. package/dist/ui/screens.js +135 -0
  46. package/dist/ui/screens.js.map +1 -0
  47. package/package.json +32 -7
@@ -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"}
@@ -1,8 +1,6 @@
1
1
  export type ClaudeCodeResult = {
2
2
  status: "configured";
3
- message: string;
4
- } | {
5
- status: "already-registered";
3
+ path: string;
6
4
  message: string;
7
5
  } | {
8
6
  status: "not-installed";
@@ -10,14 +8,54 @@ export type ClaudeCodeResult = {
10
8
  status: "error";
11
9
  message: string;
12
10
  };
11
+ export type ClaudeCodeEntry = {
12
+ type: "http";
13
+ url: string;
14
+ headers: {
15
+ Authorization: string;
16
+ };
17
+ };
18
+ type ClaudeConfig = {
19
+ mcpServers?: Record<string, unknown>;
20
+ projects?: Record<string, {
21
+ mcpServers?: Record<string, unknown>;
22
+ }>;
23
+ [key: string]: unknown;
24
+ };
25
+ /**
26
+ * Path to Claude Code's user-level config. Returns null on Linux only if
27
+ * HOME is unset (effectively never).
28
+ */
29
+ export declare function configPath(): string;
30
+ /**
31
+ * Build the canonical user-scope unfairly entry. Inlines the literal token —
32
+ * matches the Claude Desktop pattern. Keeps the token out of any process
33
+ * argv (the previous `claude mcp add --header=…` form leaked it via
34
+ * `/proc/<pid>/cmdline` for the lifetime of the subprocess).
35
+ */
36
+ export declare function buildEntry(apiUrl: string, token: string): ClaudeCodeEntry;
37
+ /**
38
+ * Merge our canonical unfairly entry into ~/.claude.json:
39
+ * - Writes the user-scope entry at root `mcpServers.unfairly`.
40
+ * - Strips any project-scoped `projects[<cwd>].mcpServers.unfairly` left over
41
+ * from previous local-scope runs of setup. Without this, a stale entry in
42
+ * the active project would shadow the user-scope one and silently keep an
43
+ * old (or empty) bearer.
44
+ * - Preserves all unrelated keys.
45
+ */
46
+ export declare function mergeIntoConfig(existing: ClaudeConfig, apiUrl: string, token: string): ClaudeConfig;
13
47
  /**
14
- * Register Unfairly with Claude Code via `claude mcp add`. Non-destructive:
15
- * if a server named `unfairly` already exists we don't remove it (the user
16
- * may have a custom config). Instead we tolerate the "already exists" error
17
- * and report `already-registered`.
48
+ * Wire Unfairly into Claude Code by mutating ~/.claude.json directly. We
49
+ * intentionally do NOT shell out to `claude mcp add --header=…` — that form
50
+ * exposes the bearer token to `ps aux` and `/proc/<pid>/cmdline` for the
51
+ * duration of the subprocess. Same threat model as Claude Desktop, same
52
+ * mitigation: write the JSON ourselves.
18
53
  *
19
- * Skips silently if the `claude` binary is not in PATH (most CLI users have
20
- * one host installed, not both).
54
+ * Skips silently only when the `claude` binary is not in PATH. If the binary
55
+ * exists but `~/.claude.json` doesn't yet (fresh install, before first
56
+ * launch of Claude Code), we create the file with our entry — that's what
57
+ * `claude mcp add` would have done implicitly.
21
58
  */
22
- export declare function configureClaudeCode(apiUrl: string): Promise<ClaudeCodeResult>;
59
+ export declare function configureClaudeCode(apiUrl: string, token: string): Promise<ClaudeCodeResult>;
60
+ export {};
23
61
  //# sourceMappingURL=claude-code.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"claude-code.d.ts","sourceRoot":"","sources":["../../src/hosts/claude-code.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,gBAAgB,GACxB;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACzC;IAAE,MAAM,EAAE,oBAAoB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACjD;IAAE,MAAM,EAAE,eAAe,CAAA;CAAE,GAC3B;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzC;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,gBAAgB,CAAC,CA2C3B"}
1
+ {"version":3,"file":"claude-code.d.ts","sourceRoot":"","sources":["../../src/hosts/claude-code.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,gBAAgB,GACxB;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,MAAM,EAAE,eAAe,CAAA;CAAE,GAC3B;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzC,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE;QAAE,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC;CACpC,CAAC;AAEF,KAAK,YAAY,GAAG;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CAAC;IACpE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAEF;;;GAGG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,eAAe,CAMzE;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,YAAY,EACtB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,YAAY,CAuBd;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,gBAAgB,CAAC,CA6C3B"}
@@ -1,44 +1,117 @@
1
1
  import { spawnSync } from "node:child_process";
2
+ import fs from "node:fs/promises";
3
+ import os from "node:os";
4
+ import path from "node:path";
2
5
  /**
3
- * Register Unfairly with Claude Code via `claude mcp add`. Non-destructive:
4
- * if a server named `unfairly` already exists we don't remove it (the user
5
- * may have a custom config). Instead we tolerate the "already exists" error
6
- * and report `already-registered`.
6
+ * Path to Claude Code's user-level config. Returns null on Linux only if
7
+ * HOME is unset (effectively never).
8
+ */
9
+ export function configPath() {
10
+ return path.join(os.homedir(), ".claude.json");
11
+ }
12
+ /**
13
+ * Build the canonical user-scope unfairly entry. Inlines the literal token —
14
+ * matches the Claude Desktop pattern. Keeps the token out of any process
15
+ * argv (the previous `claude mcp add --header=…` form leaked it via
16
+ * `/proc/<pid>/cmdline` for the lifetime of the subprocess).
17
+ */
18
+ export function buildEntry(apiUrl, token) {
19
+ return {
20
+ type: "http",
21
+ url: `${apiUrl.replace(/\/$/, "")}/api/mcp`,
22
+ headers: { Authorization: `Bearer ${token}` },
23
+ };
24
+ }
25
+ /**
26
+ * Merge our canonical unfairly entry into ~/.claude.json:
27
+ * - Writes the user-scope entry at root `mcpServers.unfairly`.
28
+ * - Strips any project-scoped `projects[<cwd>].mcpServers.unfairly` left over
29
+ * from previous local-scope runs of setup. Without this, a stale entry in
30
+ * the active project would shadow the user-scope one and silently keep an
31
+ * old (or empty) bearer.
32
+ * - Preserves all unrelated keys.
33
+ */
34
+ export function mergeIntoConfig(existing, apiUrl, token) {
35
+ const next = { ...existing };
36
+ const servers = { ...(existing.mcpServers ?? {}) };
37
+ servers.unfairly = buildEntry(apiUrl, token);
38
+ next.mcpServers = servers;
39
+ if (existing.projects) {
40
+ const projects = {};
41
+ for (const [k, v] of Object.entries(existing.projects)) {
42
+ // Only touch the project entry when it actually has an `unfairly`
43
+ // mcpServer to strip. Preserves the original shape (including the
44
+ // absence of `mcpServers` entirely) for unrelated projects.
45
+ if (v.mcpServers && "unfairly" in v.mcpServers) {
46
+ const ps = { ...v.mcpServers };
47
+ delete ps.unfairly;
48
+ projects[k] = { ...v, mcpServers: ps };
49
+ }
50
+ else {
51
+ projects[k] = v;
52
+ }
53
+ }
54
+ next.projects = projects;
55
+ }
56
+ return next;
57
+ }
58
+ /**
59
+ * Wire Unfairly into Claude Code by mutating ~/.claude.json directly. We
60
+ * intentionally do NOT shell out to `claude mcp add --header=…` — that form
61
+ * exposes the bearer token to `ps aux` and `/proc/<pid>/cmdline` for the
62
+ * duration of the subprocess. Same threat model as Claude Desktop, same
63
+ * mitigation: write the JSON ourselves.
7
64
  *
8
- * Skips silently if the `claude` binary is not in PATH (most CLI users have
9
- * one host installed, not both).
65
+ * Skips silently only when the `claude` binary is not in PATH. If the binary
66
+ * exists but `~/.claude.json` doesn't yet (fresh install, before first
67
+ * launch of Claude Code), we create the file with our entry — that's what
68
+ * `claude mcp add` would have done implicitly.
10
69
  */
11
- export async function configureClaudeCode(apiUrl) {
12
- const url = `${apiUrl.replace(/\/$/, "")}/api/mcp`;
13
- const result = spawnSync("claude", ["mcp", "add", "unfairly", "--transport", "http", url], { encoding: "utf-8" });
14
- if (result.error) {
15
- const e = result.error;
16
- if (e.code === "ENOENT") {
70
+ export async function configureClaudeCode(apiUrl, token) {
71
+ const probe = spawnSync("claude", ["--version"], { encoding: "utf-8" });
72
+ if (probe.error) {
73
+ const e = probe.error;
74
+ if (e.code === "ENOENT")
17
75
  return { status: "not-installed" };
18
- }
19
76
  return { status: "error", message: e.message };
20
77
  }
21
- const stderr = (result.stderr ?? "").toString();
22
- const stdout = (result.stdout ?? "").toString();
23
- const combined = `${stderr}\n${stdout}`.toLowerCase();
24
- if (result.status === 0) {
25
- return {
26
- status: "configured",
27
- message: "registered (Claude Code will pop OAuth on first call)",
28
- };
78
+ const cfgPath = configPath();
79
+ let raw;
80
+ try {
81
+ raw = await fs.readFile(cfgPath, "utf8");
82
+ }
83
+ catch (err) {
84
+ const e = err;
85
+ if (e.code === "ENOENT") {
86
+ // Fresh Claude Code install — binary exists but config not yet
87
+ // created. Treat as empty and let the writeFile below create it.
88
+ raw = "";
89
+ }
90
+ else {
91
+ return { status: "error", message: `Could not read ${cfgPath}: ${e.message}` };
92
+ }
29
93
  }
30
- // Claude CLI exits non-zero with a stderr message containing "already
31
- // exists" (or similar) when the server name is taken. Don't destroy the
32
- // user's existing config — surface as already-registered.
33
- if (/already exists|already configured|duplicate/.test(combined)) {
94
+ let parsed;
95
+ try {
96
+ parsed = raw.trim() === "" ? {} : JSON.parse(raw);
97
+ }
98
+ catch (err) {
34
99
  return {
35
- status: "already-registered",
36
- message: "already registered (left as-is)",
100
+ status: "error",
101
+ message: `Refusing to overwrite — config is not valid JSON: ${err.message}`,
37
102
  };
38
103
  }
104
+ const merged = mergeIntoConfig(parsed, apiUrl, token);
105
+ try {
106
+ await fs.writeFile(cfgPath, JSON.stringify(merged, null, 2) + "\n", "utf8");
107
+ }
108
+ catch (err) {
109
+ return { status: "error", message: err.message };
110
+ }
39
111
  return {
40
- status: "error",
41
- message: stderr.trim() || `claude mcp add exited ${result.status}`,
112
+ status: "configured",
113
+ path: cfgPath,
114
+ message: "wired unfairly into ~/.claude.json (user scope, literal token)",
42
115
  };
43
116
  }
44
117
  //# sourceMappingURL=claude-code.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../src/hosts/claude-code.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAQ/C;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,MAAc;IAEd,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC;IACnD,MAAM,MAAM,GAAG,SAAS,CACtB,QAAQ,EACR,CAAC,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,CAAC,EACtD,EAAE,QAAQ,EAAE,OAAO,EAAE,CACtB,CAAC;IAEF,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,MAAM,CAAC,GAAG,MAAM,CAAC,KAA8B,CAAC;QAChD,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACxB,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;QACrC,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;IACjD,CAAC;IAED,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IAChD,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IAChD,MAAM,QAAQ,GAAG,GAAG,MAAM,KAAK,MAAM,EAAE,CAAC,WAAW,EAAE,CAAC;IAEtD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO;YACL,MAAM,EAAE,YAAY;YACpB,OAAO,EAAE,uDAAuD;SACjE,CAAC;IACJ,CAAC;IAED,sEAAsE;IACtE,wEAAwE;IACxE,0DAA0D;IAC1D,IACE,6CAA6C,CAAC,IAAI,CAAC,QAAQ,CAAC,EAC5D,CAAC;QACD,OAAO;YACL,MAAM,EAAE,oBAAoB;YAC5B,OAAO,EAAE,iCAAiC;SAC3C,CAAC;IACJ,CAAC;IAED,OAAO;QACL,MAAM,EAAE,OAAO;QACf,OAAO,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,yBAAyB,MAAM,CAAC,MAAM,EAAE;KACnE,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../src/hosts/claude-code.ts"],"names":[],"mappings":"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"}
@@ -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, token: string): UnfairlyEntry;
30
+ /**
31
+ * Merge our canonical unfairly entry into an existing config object.
32
+ * - Preserves other mcpServers
33
+ * - Replaces any existing unfairly entry (including stale tokens / placeholder)
34
+ * - Preserves all unrelated top-level keys
35
+ */
36
+ export declare function mergeIntoConfig(existing: ConfigShape, apiUrl: string, token: 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, token: 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,EAAE,KAAK,EAAE,MAAM,GAAG,aAAa,CAYvE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,WAAW,EACrB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ;IAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAAG,WAAW,CAMvD;AAED;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,mBAAmB,CAAC,CAqC9B"}
@@ -0,0 +1,88 @@
1
+ import fs from "node:fs/promises";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ /**
5
+ * Path to Claude Desktop's config file by platform. Returns null on Linux
6
+ * (Claude Desktop is Mac/Windows only per official docs).
7
+ */
8
+ export function configPath() {
9
+ const home = os.homedir();
10
+ if (process.platform === "darwin") {
11
+ return path.join(home, "Library", "Application Support", "Claude", "claude_desktop_config.json");
12
+ }
13
+ if (process.platform === "win32") {
14
+ const appdata = process.env.APPDATA ?? path.join(home, "AppData", "Roaming");
15
+ return path.join(appdata, "Claude", "claude_desktop_config.json");
16
+ }
17
+ return null;
18
+ }
19
+ export function buildEntry(apiUrl, token) {
20
+ const url = `${apiUrl.replace(/\/$/, "")}/api/mcp`;
21
+ // Inline the literal token. macOS GUI apps don't inherit env vars from
22
+ // ~/.zshenv (only LaunchAgent env via `launchctl setenv`), so the
23
+ // `${UNFAIRLY_MCP_TOKEN}` placeholder pattern silently fails. Claude Desktop
24
+ // already stores credentials on disk for other MCP servers — this is the
25
+ // standard pattern.
26
+ return {
27
+ type: "http",
28
+ url,
29
+ headers: { Authorization: `Bearer ${token}` },
30
+ };
31
+ }
32
+ /**
33
+ * Merge our canonical unfairly entry into an existing config object.
34
+ * - Preserves other mcpServers
35
+ * - Replaces any existing unfairly entry (including stale tokens / placeholder)
36
+ * - Preserves all unrelated top-level keys
37
+ */
38
+ export function mergeIntoConfig(existing, apiUrl, token) {
39
+ const next = { ...existing };
40
+ const servers = { ...(existing.mcpServers ?? {}) };
41
+ servers.unfairly = buildEntry(apiUrl, token);
42
+ next.mcpServers = servers;
43
+ return next;
44
+ }
45
+ /**
46
+ * Patch Claude Desktop's config to wire the Unfairly MCP server.
47
+ * - If config file does not exist → not-installed (do NOT create).
48
+ * - If file exists but is malformed JSON → error (don't overwrite precious config).
49
+ * - Otherwise → merge canonical block, write back.
50
+ */
51
+ export async function configureClaudeDesktop(apiUrl, token) {
52
+ const cfgPath = configPath();
53
+ if (!cfgPath) {
54
+ return { status: "not-installed", path: "(Claude Desktop not available on this platform)" };
55
+ }
56
+ let existing;
57
+ try {
58
+ existing = await fs.readFile(cfgPath, "utf8");
59
+ }
60
+ catch (err) {
61
+ const e = err;
62
+ if (e.code === "ENOENT")
63
+ return { status: "not-installed", path: cfgPath };
64
+ return { status: "error", path: cfgPath, message: `Could not read ${cfgPath}: ${e.message}` };
65
+ }
66
+ let parsed;
67
+ try {
68
+ parsed = existing.trim() === "" ? {} : JSON.parse(existing);
69
+ }
70
+ catch (err) {
71
+ return {
72
+ status: "error",
73
+ path: cfgPath,
74
+ message: `Refusing to overwrite — config is not valid JSON: ${err.message}`,
75
+ };
76
+ }
77
+ const had = parsed.mcpServers && parsed.mcpServers.unfairly !== undefined;
78
+ const merged = mergeIntoConfig(parsed, apiUrl, token);
79
+ const serialized = JSON.stringify(merged, null, 2) + "\n";
80
+ try {
81
+ await fs.writeFile(cfgPath, serialized, "utf8");
82
+ }
83
+ catch (err) {
84
+ return { status: "error", path: cfgPath, message: err.message };
85
+ }
86
+ return { status: "configured", path: cfgPath, action: had ? "updated" : "created" };
87
+ }
88
+ //# sourceMappingURL=claude-desktop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-desktop.js","sourceRoot":"","sources":["../../src/hosts/claude-desktop.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { readFileSync } from "node:fs";
3
+ import { promises as fs } from "node:fs";
3
4
  import { fileURLToPath } from "node:url";
4
5
  import { dirname, join } from "node:path";
5
6
  import yargs from "yargs";
@@ -7,37 +8,28 @@ import { hideBin } from "yargs/helpers";
7
8
  const pkg = JSON.parse(readFileSync(join(dirname(fileURLToPath(import.meta.url)), "..", "package.json"), "utf8"));
8
9
  await yargs(hideBin(process.argv))
9
10
  .scriptName("unfairly")
10
- .usage("$0 <cmd> [args]")
11
+ .usage("$0 [cmd] [args]")
11
12
  .version(pkg.version)
12
- .command("setup", "One-shot: authorize, write shell env, configure Codex + Claude Code", () => { }, async () => {
13
- const { runSetup } = await import("./cmd/setup.js");
14
- await runSetup();
15
- })
16
- .command("login", "Authorize via browser; print export lines for ~/.zshenv (Codex / scripts)", (y) => y.option("quiet", {
13
+ .command("$0", "First-run: wire MCP across hosts, bind workspace if in a repo, show status otherwise", (y) => y.option("yes", {
17
14
  type: "boolean",
18
- alias: "q",
15
+ alias: "y",
19
16
  default: false,
20
- describe: "Print only the export lines (for piping)",
17
+ describe: "Skip confirmation prompts",
21
18
  }), async (argv) => {
22
- const { runLogin } = await import("./cmd/login.js");
23
- await runLogin({ quiet: argv.quiet });
19
+ await runBare({ yes: argv.yes });
24
20
  })
25
- .command("init", "Initialize .unfairly/ in cwd and pull all accessible vaults", (y) => y
26
- .option("token", {
27
- type: "string",
28
- describe: "mcp_* token for non-interactive runs. Or set UNFAIRLY_TOKEN env. Default: browser OAuth.",
21
+ .command("setup", "Wire MCP for Claude Desktop / Claude Code / Codex on this machine", (y) => y.option("yes", { type: "boolean", alias: "y", default: false }), async (argv) => {
22
+ const { runSetup } = await import("./cmd/setup.js");
23
+ await runSetup({ chainInit: false, yes: argv.yes });
29
24
  })
30
- .option("yes", {
31
- type: "boolean",
32
- alias: "y",
33
- default: false,
34
- describe: "Skip the .unfairly/ overwrite confirmation",
25
+ .command("login", "Authorize via browser; print export lines for ~/.zshenv", (y) => y.option("quiet", { type: "boolean", alias: "q", default: false }), async (argv) => {
26
+ const { runLogin } = await import("./cmd/login.js");
27
+ await runLogin({ quiet: argv.quiet });
35
28
  })
36
- .option("no-browser", {
37
- type: "boolean",
38
- default: false,
39
- describe: "Skip browser-based OAuth; prompt for a manual token paste instead.",
40
- }), async (argv) => {
29
+ .command("init", "Bind .unfairly/ to cwd and pull all accessible vaults", (y) => y
30
+ .option("token", { type: "string" })
31
+ .option("yes", { type: "boolean", alias: "y", default: false })
32
+ .option("no-browser", { type: "boolean", default: false }), async (argv) => {
41
33
  const { runInit } = await import("./cmd/init.js");
42
34
  await runInit({
43
35
  token: argv.token,
@@ -61,16 +53,55 @@ await yargs(hideBin(process.argv))
61
53
  const { runResolve } = await import("./cmd/resolve.js");
62
54
  await runResolve(argv.path);
63
55
  })
64
- .command("watch", "Watch .unfairly/ for changes and auto-push", () => { }, async () => {
56
+ .command("watch", "Watch .unfairly/ for changes; debounced auto-push", () => { }, async () => {
65
57
  const { runWatch } = await import("./cmd/watch.js");
66
58
  await runWatch();
67
59
  })
68
- .command("mcp", "Run as a stdio MCP server (for agent host integration)", () => { }, async () => {
60
+ .command("mcp", "Run as stdio MCP server (sync tools)", () => { }, async () => {
69
61
  const { runMcp } = await import("./cmd/mcp.js");
70
62
  await runMcp();
71
63
  })
72
- .demandCommand(1)
73
64
  .strict()
74
65
  .help()
75
66
  .parse();
67
+ async function runBare(opts) {
68
+ const startCwd = process.cwd();
69
+ const { getToken } = await import("./sync/credentials.js");
70
+ const { findRepoRoot } = await import("./sync/repo-root.js");
71
+ const repoRoot = await findRepoRoot(startCwd);
72
+ // If we found a repo root and we're in a subdir, chdir up so init/pull/
73
+ // stitch all see the same .unfairly/ at the repo root. Explicit subcommands
74
+ // (`unfairly init`) keep their existing cwd-relative behavior — only the
75
+ // bare entrypoint promotes to repoRoot.
76
+ if (repoRoot && repoRoot !== startCwd) {
77
+ process.chdir(repoRoot);
78
+ }
79
+ const effectiveCwd = process.cwd();
80
+ const token = await getToken();
81
+ const manifestExists = await pathExists(join(effectiveCwd, ".unfairly", "manifest.json"));
82
+ if (!token) {
83
+ // Cold install — full setup, chain init when in repo
84
+ const { runSetup } = await import("./cmd/setup.js");
85
+ await runSetup({ chainInit: Boolean(repoRoot), yes: opts.yes });
86
+ return;
87
+ }
88
+ if (!manifestExists && repoRoot) {
89
+ // Token exists, no workspace bound, in a repo — offer init only
90
+ const { runInit } = await import("./cmd/init.js");
91
+ await runInit({ yes: opts.yes });
92
+ return;
93
+ }
94
+ // Daily check-in
95
+ const { runStatusCard } = await import("./cmd/status-card.js");
96
+ await runStatusCard();
97
+ }
98
+ async function pathExists(p) {
99
+ try {
100
+ await fs.access(p);
101
+ return true;
102
+ }
103
+ catch {
104
+ return false;
105
+ }
106
+ }
76
107
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Walk up from start until we find a directory containing `.git`. Returns
3
+ * the directory, or null if we reach the filesystem root with no hit.
4
+ * Accepts `.git` as either dir or file (worktrees use a `.git` file).
5
+ */
6
+ export declare function findRepoRoot(start: string): Promise<string | null>;
7
+ //# sourceMappingURL=repo-root.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo-root.d.ts","sourceRoot":"","sources":["../../src/sync/repo-root.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAaxE"}
@@ -0,0 +1,24 @@
1
+ import { promises as fs } from "node:fs";
2
+ import path from "node:path";
3
+ /**
4
+ * Walk up from start until we find a directory containing `.git`. Returns
5
+ * the directory, or null if we reach the filesystem root with no hit.
6
+ * Accepts `.git` as either dir or file (worktrees use a `.git` file).
7
+ */
8
+ export async function findRepoRoot(start) {
9
+ let dir = path.resolve(start);
10
+ while (true) {
11
+ try {
12
+ await fs.stat(path.join(dir, ".git"));
13
+ return dir;
14
+ }
15
+ catch {
16
+ // not here, keep walking
17
+ }
18
+ const parent = path.dirname(dir);
19
+ if (parent === dir)
20
+ return null;
21
+ dir = parent;
22
+ }
23
+ }
24
+ //# sourceMappingURL=repo-root.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo-root.js","sourceRoot":"","sources":["../../src/sync/repo-root.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,KAAa;IAC9C,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC9B,OAAO,IAAI,EAAE,CAAC;QACZ,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC;YACtC,OAAO,GAAG,CAAC;QACb,CAAC;QAAC,MAAM,CAAC;YACP,yBAAyB;QAC3B,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC;QAChC,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,9 @@
1
+ export declare const AUTOLOADER_LINE = "@.unfairly/CLAUDE.md";
2
+ export declare const SENTINEL = "<!-- unfairly: autoloader -->";
3
+ export type StitchResult = {
4
+ action: "created" | "appended" | "noop" | "not-a-repo" | "error";
5
+ path: string;
6
+ message?: string;
7
+ };
8
+ export declare function stitchClaudeMd(repoRoot: string): Promise<StitchResult>;
9
+ //# sourceMappingURL=stitch-claude-md.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stitch-claude-md.d.ts","sourceRoot":"","sources":["../../src/sync/stitch-claude-md.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,eAAe,yBAAyB,CAAC;AACtD,eAAO,MAAM,QAAQ,kCAAkC,CAAC;AAExD,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,YAAY,GAAG,OAAO,CAAC;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAIF,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAwC5E"}