ruleshare 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.
Files changed (54) hide show
  1. package/README.md +128 -0
  2. package/dist/cli.d.ts +3 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +94 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/commands/add.d.ts +20 -0
  7. package/dist/commands/add.d.ts.map +1 -0
  8. package/dist/commands/add.js +27 -0
  9. package/dist/commands/add.js.map +1 -0
  10. package/dist/commands/index.d.ts +7 -0
  11. package/dist/commands/index.d.ts.map +1 -0
  12. package/dist/commands/index.js +7 -0
  13. package/dist/commands/index.js.map +1 -0
  14. package/dist/commands/init.d.ts +7 -0
  15. package/dist/commands/init.d.ts.map +1 -0
  16. package/dist/commands/init.js +14 -0
  17. package/dist/commands/init.js.map +1 -0
  18. package/dist/commands/list.d.ts +16 -0
  19. package/dist/commands/list.d.ts.map +1 -0
  20. package/dist/commands/list.js +48 -0
  21. package/dist/commands/list.js.map +1 -0
  22. package/dist/commands/remove.d.ts +10 -0
  23. package/dist/commands/remove.d.ts.map +1 -0
  24. package/dist/commands/remove.js +30 -0
  25. package/dist/commands/remove.js.map +1 -0
  26. package/dist/commands/status.d.ts +8 -0
  27. package/dist/commands/status.d.ts.map +1 -0
  28. package/dist/commands/status.js +83 -0
  29. package/dist/commands/status.js.map +1 -0
  30. package/dist/commands/sync.d.ts +10 -0
  31. package/dist/commands/sync.d.ts.map +1 -0
  32. package/dist/commands/sync.js +52 -0
  33. package/dist/commands/sync.js.map +1 -0
  34. package/dist/config.d.ts +11 -0
  35. package/dist/config.d.ts.map +1 -0
  36. package/dist/config.js +50 -0
  37. package/dist/config.js.map +1 -0
  38. package/dist/fetcher.d.ts +16 -0
  39. package/dist/fetcher.d.ts.map +1 -0
  40. package/dist/fetcher.js +51 -0
  41. package/dist/fetcher.js.map +1 -0
  42. package/dist/index.d.ts +6 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +6 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/resolver.d.ts +11 -0
  47. package/dist/resolver.d.ts.map +1 -0
  48. package/dist/resolver.js +58 -0
  49. package/dist/resolver.js.map +1 -0
  50. package/dist/types.d.ts +39 -0
  51. package/dist/types.d.ts.map +1 -0
  52. package/dist/types.js +2 -0
  53. package/dist/types.js.map +1 -0
  54. package/package.json +44 -0
package/README.md ADDED
@@ -0,0 +1,128 @@
1
+ # ruleshare
2
+
3
+ Sync shared Claude Code rules from remote sources.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g ruleshare
9
+ # or
10
+ npx ruleshare
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ### Initialize
16
+
17
+ Create a `shared.json` config file in `.claude/rules/`:
18
+
19
+ ```bash
20
+ ruleshare init
21
+ ```
22
+
23
+ ### Add Sources
24
+
25
+ Define source aliases to avoid repeating full GitHub paths:
26
+
27
+ ```bash
28
+ ruleshare add source anthropic github:anthropic/claude-rules
29
+ ruleshare add source company github:mycompany/team-rules/rules
30
+ ```
31
+
32
+ ### Add Rules
33
+
34
+ Add rules using source aliases or full paths:
35
+
36
+ ```bash
37
+ # Using alias
38
+ ruleshare add typescript anthropic:typescript.md
39
+ ruleshare add react anthropic:react.md
40
+
41
+ # Using full path
42
+ ruleshare add security github:company/rules/security.md@v2.0.0
43
+
44
+ # With version pinning
45
+ ruleshare add api-design company:backend/api.md@v1.0.0
46
+ ```
47
+
48
+ ### Sync Rules
49
+
50
+ Download all rules to `.claude/rules/shared/`:
51
+
52
+ ```bash
53
+ ruleshare sync
54
+ ```
55
+
56
+ ### Check Status
57
+
58
+ See which rules are outdated:
59
+
60
+ ```bash
61
+ ruleshare status
62
+ ```
63
+
64
+ ### Update Rules
65
+
66
+ Force re-download all rules:
67
+
68
+ ```bash
69
+ ruleshare update
70
+ ```
71
+
72
+ ### List Configuration
73
+
74
+ Show configured sources and rules:
75
+
76
+ ```bash
77
+ ruleshare list
78
+ ```
79
+
80
+ ### Remove Rules
81
+
82
+ ```bash
83
+ ruleshare remove typescript
84
+ ```
85
+
86
+ ## File Structure
87
+
88
+ ```
89
+ .claude/
90
+ └── rules/
91
+ ├── your-team-rules.md # Your own rules (not managed)
92
+ ├── shared.json # Config file (commit this)
93
+ ├── shared.lock # Lock file (commit this)
94
+ └── shared/ # Synced rules
95
+ ├── typescript.md
96
+ └── react.md
97
+ ```
98
+
99
+ ## Config Format
100
+
101
+ `.claude/rules/shared.json`:
102
+
103
+ ```json
104
+ {
105
+ "sources": {
106
+ "anthropic": "github:anthropic/claude-rules",
107
+ "company": "github:mycompany/team-rules/rules"
108
+ },
109
+ "rules": {
110
+ "typescript": "anthropic:typescript.md",
111
+ "react": "anthropic:react.md@v1.0.0",
112
+ "security": "company:security.md"
113
+ }
114
+ }
115
+ ```
116
+
117
+ ## Source Formats
118
+
119
+ | Format | Example |
120
+ |--------|---------|
121
+ | GitHub | `github:owner/repo/path/file.md` |
122
+ | GitHub + version | `github:owner/repo/path/file.md@v1.0.0` |
123
+ | Alias | `alias:path/file.md` |
124
+ | URL | `https://example.com/rules.md` |
125
+
126
+ ## License
127
+
128
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,94 @@
1
+ #!/usr/bin/env node
2
+ import { init, addRule, addSource, sync, status, list, remove, } from "./commands/index.js";
3
+ const commandMap = {
4
+ init: async () => { await init(); },
5
+ add: handleAdd,
6
+ sync: handleSync,
7
+ update: async () => { await sync({ force: true }); },
8
+ status: async () => { await status(); },
9
+ list: async () => { await list(); },
10
+ ls: async () => { await list(); },
11
+ remove: handleRemove,
12
+ rm: handleRemove,
13
+ };
14
+ function isHelpCommand(command) {
15
+ return !command || command === "help" || command === "--help";
16
+ }
17
+ async function executeCommand(command, args) {
18
+ const handler = commandMap[command];
19
+ if (!handler) {
20
+ console.error(`Unknown command: ${command}`);
21
+ printHelp();
22
+ return { exitCode: 1 };
23
+ }
24
+ try {
25
+ await handler(args);
26
+ return { exitCode: 0 };
27
+ }
28
+ catch (error) {
29
+ const message = error instanceof Error ? error.message : String(error);
30
+ console.error(`Error: ${message}`);
31
+ return { exitCode: 1 };
32
+ }
33
+ }
34
+ async function main() {
35
+ const args = process.argv.slice(2);
36
+ const command = args[0];
37
+ if (isHelpCommand(command)) {
38
+ printHelp();
39
+ return { exitCode: 0 };
40
+ }
41
+ return executeCommand(command, args.slice(1));
42
+ }
43
+ async function handleAdd(args) {
44
+ if (args[0] === "source" && args.length >= 3) {
45
+ await addSource({ alias: args[1], source: args[2] });
46
+ return;
47
+ }
48
+ if (args.length >= 2) {
49
+ await addRule({ name: args[0], source: args[1] });
50
+ return;
51
+ }
52
+ console.error("Usage: ruleshare add <name> <source>");
53
+ console.error(" ruleshare add source <alias> <github:owner/repo>");
54
+ }
55
+ async function handleSync(args) {
56
+ const force = args.includes("--force") || args.includes("-f");
57
+ console.log("Syncing rules...");
58
+ await sync({ force });
59
+ }
60
+ async function handleRemove(args) {
61
+ if (args.length < 1) {
62
+ console.error("Usage: ruleshare remove <name>");
63
+ return;
64
+ }
65
+ await remove({ name: args[0] });
66
+ }
67
+ function printHelp() {
68
+ console.log(`
69
+ ruleshare - Sync Claude Code rules from remote sources
70
+
71
+ Usage:
72
+ ruleshare <command> [options]
73
+
74
+ Commands:
75
+ init Create shared.json config file
76
+ add <name> <source> Add a rule
77
+ add source <alias> <source> Add a source alias
78
+ sync [--force] Download rules to .claude/rules/shared/
79
+ update Force update all rules
80
+ status Check for outdated rules
81
+ list, ls List configured rules and sources
82
+ remove, rm <name> Remove a rule
83
+
84
+ Examples:
85
+ ruleshare init
86
+ ruleshare add source anthropic github:anthropic/claude-rules
87
+ ruleshare add typescript anthropic:typescript.md
88
+ ruleshare sync
89
+ `);
90
+ }
91
+ main().then((result) => {
92
+ process.exit(result.exitCode);
93
+ });
94
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ type AddRuleArgs = {
2
+ name: string;
3
+ source: string;
4
+ };
5
+ type AddRuleResult = {
6
+ added: boolean;
7
+ name: string;
8
+ };
9
+ export declare function addRule(args: AddRuleArgs): Promise<AddRuleResult>;
10
+ type AddSourceArgs = {
11
+ alias: string;
12
+ source: string;
13
+ };
14
+ type AddSourceResult = {
15
+ added: boolean;
16
+ alias: string;
17
+ };
18
+ export declare function addSource(args: AddSourceArgs): Promise<AddSourceResult>;
19
+ export {};
20
+ //# sourceMappingURL=add.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"AAEA,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,KAAK,aAAa,GAAG;IACnB,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,wBAAsB,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CAavE;AAED,KAAK,aAAa,GAAG;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,wBAAsB,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,eAAe,CAAC,CAiB7E"}
@@ -0,0 +1,27 @@
1
+ import { readConfig, writeConfig, createEmptyConfig } from "../config.js";
2
+ export async function addRule(args) {
3
+ const { name, source } = args;
4
+ let config = await readConfig();
5
+ if (!config) {
6
+ config = createEmptyConfig();
7
+ }
8
+ config.rules[name] = source;
9
+ await writeConfig(config);
10
+ console.log(`Added rule "${name}" -> ${source}`);
11
+ return { added: true, name };
12
+ }
13
+ export async function addSource(args) {
14
+ const { alias, source } = args;
15
+ let config = await readConfig();
16
+ if (!config) {
17
+ config = createEmptyConfig();
18
+ }
19
+ if (!config.sources) {
20
+ config.sources = {};
21
+ }
22
+ config.sources[alias] = source;
23
+ await writeConfig(config);
24
+ console.log(`Added source alias "${alias}" -> ${source}`);
25
+ return { added: true, alias };
26
+ }
27
+ //# sourceMappingURL=add.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.js","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAY1E,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAiB;IAC7C,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAE9B,IAAI,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;IAChC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,GAAG,iBAAiB,EAAE,CAAC;IAC/B,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC;IAC5B,MAAM,WAAW,CAAC,MAAM,CAAC,CAAC;IAE1B,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,QAAQ,MAAM,EAAE,CAAC,CAAC;IACjD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AAC/B,CAAC;AAYD,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAmB;IACjD,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAE/B,IAAI,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;IAChC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,GAAG,iBAAiB,EAAE,CAAC;IAC/B,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,CAAC,OAAO,GAAG,EAAE,CAAC;IACtB,CAAC;IAED,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC;IAC/B,MAAM,WAAW,CAAC,MAAM,CAAC,CAAC;IAE1B,OAAO,CAAC,GAAG,CAAC,uBAAuB,KAAK,QAAQ,MAAM,EAAE,CAAC,CAAC;IAC1D,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AAChC,CAAC"}
@@ -0,0 +1,7 @@
1
+ export { init } from "./init.js";
2
+ export { addRule, addSource } from "./add.js";
3
+ export { sync } from "./sync.js";
4
+ export { status } from "./status.js";
5
+ export { list } from "./list.js";
6
+ export { remove } from "./remove.js";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,7 @@
1
+ export { init } from "./init.js";
2
+ export { addRule, addSource } from "./add.js";
3
+ export { sync } from "./sync.js";
4
+ export { status } from "./status.js";
5
+ export { list } from "./list.js";
6
+ export { remove } from "./remove.js";
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,7 @@
1
+ type InitResult = {
2
+ created: boolean;
3
+ path: string;
4
+ };
5
+ export declare function init(): Promise<InitResult>;
6
+ export {};
7
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAOA,KAAK,UAAU,GAAG;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,wBAAsB,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC,CAahD"}
@@ -0,0 +1,14 @@
1
+ import { existsSync } from "node:fs";
2
+ import { getConfigPath, writeConfig, createEmptyConfig, } from "../config.js";
3
+ export async function init() {
4
+ const path = getConfigPath();
5
+ if (existsSync(path)) {
6
+ console.log(`Config already exists at ${path}`);
7
+ return { created: false, path };
8
+ }
9
+ const config = createEmptyConfig();
10
+ await writeConfig(config);
11
+ console.log(`Created ${path}`);
12
+ return { created: true, path };
13
+ }
14
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EACL,aAAa,EACb,WAAW,EACX,iBAAiB,GAClB,MAAM,cAAc,CAAC;AAOtB,MAAM,CAAC,KAAK,UAAU,IAAI;IACxB,MAAM,IAAI,GAAG,aAAa,EAAE,CAAC;IAE7B,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACrB,OAAO,CAAC,GAAG,CAAC,4BAA4B,IAAI,EAAE,CAAC,CAAC;QAChD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAClC,CAAC;IAED,MAAM,MAAM,GAAG,iBAAiB,EAAE,CAAC;IACnC,MAAM,WAAW,CAAC,MAAM,CAAC,CAAC;IAE1B,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;IAC/B,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACjC,CAAC"}
@@ -0,0 +1,16 @@
1
+ type RuleEntry = {
2
+ name: string;
3
+ source: string;
4
+ synced: boolean;
5
+ };
6
+ type SourceEntry = {
7
+ alias: string;
8
+ url: string;
9
+ };
10
+ type ListOutput = {
11
+ rules: RuleEntry[];
12
+ sources: SourceEntry[];
13
+ };
14
+ export declare function list(): Promise<ListOutput>;
15
+ export {};
16
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAEA,KAAK,SAAS,GAAG;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,KAAK,UAAU,GAAG;IAChB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB,CAAC;AAEF,wBAAsB,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC,CAyBhD"}
@@ -0,0 +1,48 @@
1
+ import { readConfig, readLock } from "../config.js";
2
+ export async function list() {
3
+ const config = await readConfig();
4
+ if (!config) {
5
+ console.log("No shared.json found. Run `ruleshare init` first.");
6
+ return { rules: [], sources: [] };
7
+ }
8
+ const lock = await readLock();
9
+ const rules = Object.entries(config.rules).map(([name, source]) => ({
10
+ name,
11
+ source,
12
+ synced: !!lock?.rules[name],
13
+ }));
14
+ const sources = Object.entries(config.sources || {}).map(([alias, url]) => ({
15
+ alias,
16
+ url,
17
+ }));
18
+ printSources({ sources });
19
+ printRules({ rules });
20
+ printEmptyMessage({ rules, sources });
21
+ return { rules, sources };
22
+ }
23
+ function printSources(args) {
24
+ const { sources } = args;
25
+ if (sources.length === 0)
26
+ return;
27
+ console.log("\nSources:");
28
+ for (const { alias, url } of sources) {
29
+ console.log(` ${alias}: ${url}`);
30
+ }
31
+ }
32
+ function printRules(args) {
33
+ const { rules } = args;
34
+ if (rules.length === 0)
35
+ return;
36
+ console.log("\nRules:");
37
+ for (const { name, source, synced } of rules) {
38
+ const marker = synced ? "✓" : " ";
39
+ console.log(` ${marker} ${name}: ${source}`);
40
+ }
41
+ }
42
+ function printEmptyMessage(args) {
43
+ const { rules, sources } = args;
44
+ if (rules.length === 0 && sources.length === 0) {
45
+ console.log("\nNo rules or sources configured.");
46
+ }
47
+ }
48
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAkBpD,MAAM,CAAC,KAAK,UAAU,IAAI;IACxB,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;IAClC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;QACjE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IACpC,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,QAAQ,EAAE,CAAC;IAE9B,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;QAClE,IAAI;QACJ,MAAM;QACN,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC;KAC5B,CAAC,CAAC,CAAC;IAEJ,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;QAC1E,KAAK;QACL,GAAG;KACJ,CAAC,CAAC,CAAC;IAEJ,YAAY,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IAC1B,UAAU,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACtB,iBAAiB,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;IAEtC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAC5B,CAAC;AAMD,SAAS,YAAY,CAAC,IAAsB;IAC1C,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IACzB,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAEjC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAC1B,KAAK,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,OAAO,EAAE,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,KAAK,GAAG,EAAE,CAAC,CAAC;IACpC,CAAC;AACH,CAAC;AAMD,SAAS,UAAU,CAAC,IAAoB;IACtC,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;IACvB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAE/B,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACxB,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,KAAK,EAAE,CAAC;QAC7C,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC,CAAC;IAChD,CAAC;AACH,CAAC;AAOD,SAAS,iBAAiB,CAAC,IAAoB;IAC7C,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/C,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;IACnD,CAAC;AACH,CAAC"}
@@ -0,0 +1,10 @@
1
+ type RemoveArgs = {
2
+ name: string;
3
+ };
4
+ type RemoveResult = {
5
+ removed: boolean;
6
+ name: string;
7
+ };
8
+ export declare function remove(args: RemoveArgs): Promise<RemoveResult>;
9
+ export {};
10
+ //# sourceMappingURL=remove.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remove.d.ts","sourceRoot":"","sources":["../../src/commands/remove.ts"],"names":[],"mappings":"AAWA,KAAK,UAAU,GAAG;IAChB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,KAAK,YAAY,GAAG;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,wBAAsB,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC,CA8BpE"}
@@ -0,0 +1,30 @@
1
+ import { unlink } from "node:fs/promises";
2
+ import { existsSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { readConfig, writeConfig, readLock, writeLock, getSharedDir, } from "../config.js";
5
+ export async function remove(args) {
6
+ const { name } = args;
7
+ const config = await readConfig();
8
+ if (!config) {
9
+ console.error("No shared.json found.");
10
+ return { removed: false, name };
11
+ }
12
+ if (!config.rules[name]) {
13
+ console.error(`Rule "${name}" not found.`);
14
+ return { removed: false, name };
15
+ }
16
+ delete config.rules[name];
17
+ await writeConfig(config);
18
+ const lock = await readLock();
19
+ if (lock?.rules[name]) {
20
+ delete lock.rules[name];
21
+ await writeLock(lock);
22
+ }
23
+ const filePath = join(getSharedDir(), `${name}.md`);
24
+ if (existsSync(filePath)) {
25
+ await unlink(filePath);
26
+ }
27
+ console.log(`Removed rule "${name}"`);
28
+ return { removed: true, name };
29
+ }
30
+ //# sourceMappingURL=remove.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remove.js","sourceRoot":"","sources":["../../src/commands/remove.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EACL,UAAU,EACV,WAAW,EACX,QAAQ,EACR,SAAS,EACT,YAAY,GACb,MAAM,cAAc,CAAC;AAWtB,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAgB;IAC3C,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;IAEtB,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;IAClC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;QACvC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAClC,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,OAAO,CAAC,KAAK,CAAC,SAAS,IAAI,cAAc,CAAC,CAAC;QAC3C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAClC,CAAC;IAED,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1B,MAAM,WAAW,CAAC,MAAM,CAAC,CAAC;IAE1B,MAAM,IAAI,GAAG,MAAM,QAAQ,EAAE,CAAC;IAC9B,IAAI,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACxB,MAAM,SAAS,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,EAAE,EAAE,GAAG,IAAI,KAAK,CAAC,CAAC;IACpD,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;IACzB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,GAAG,CAAC,CAAC;IACtC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACjC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { StatusEntry } from "../types.js";
2
+ type StatusOutput = {
3
+ entries: StatusEntry[];
4
+ hasOutdated: boolean;
5
+ };
6
+ export declare function status(): Promise<StatusOutput>;
7
+ export {};
8
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAA4B,MAAM,aAAa,CAAC;AAEzE,KAAK,YAAY,GAAG;IAClB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,WAAW,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,wBAAsB,MAAM,IAAI,OAAO,CAAC,YAAY,CAAC,CAmBpD"}
@@ -0,0 +1,83 @@
1
+ import { readConfig, readLock } from "../config.js";
2
+ import { resolveSource } from "../resolver.js";
3
+ import { checkForUpdate } from "../fetcher.js";
4
+ export async function status() {
5
+ const config = await readConfig();
6
+ if (!config) {
7
+ console.error("No shared.json found. Run `ruleshare init` first.");
8
+ return { entries: [], hasOutdated: false };
9
+ }
10
+ const lock = await readLock();
11
+ if (!lock) {
12
+ console.log("No lock file. Run `ruleshare sync` first.");
13
+ return { entries: [], hasOutdated: false };
14
+ }
15
+ const entries = await collectStatusEntries({ config, lock });
16
+ const hasOutdated = entries.some((e) => e.isOutdated);
17
+ printStatusTable({ entries });
18
+ return { entries, hasOutdated };
19
+ }
20
+ async function collectStatusEntries(args) {
21
+ const { config, lock } = args;
22
+ const entries = [];
23
+ for (const [name, source] of Object.entries(config.rules)) {
24
+ const entry = await checkRuleStatus({ name, source, config, lock });
25
+ entries.push(entry);
26
+ }
27
+ return entries;
28
+ }
29
+ async function checkRuleStatus(args) {
30
+ const { name, source, config, lock } = args;
31
+ const lockEntry = lock.rules[name];
32
+ if (!lockEntry) {
33
+ return createNotSyncedEntry({ name, source });
34
+ }
35
+ return checkRemoteStatus({ name, source, config, lockEntry });
36
+ }
37
+ function createNotSyncedEntry(args) {
38
+ const { name, source } = args;
39
+ return {
40
+ name,
41
+ currentSha: "not synced",
42
+ latestSha: "unknown",
43
+ isOutdated: true,
44
+ source,
45
+ };
46
+ }
47
+ async function checkRemoteStatus(args) {
48
+ const { name, source, config, lockEntry } = args;
49
+ try {
50
+ const resolved = resolveSource({ source, config });
51
+ const { isOutdated, latestSha } = await checkForUpdate({
52
+ resolved: resolved.resolved,
53
+ currentSha: lockEntry.sha,
54
+ });
55
+ return {
56
+ name,
57
+ currentSha: lockEntry.sha.substring(0, 8),
58
+ latestSha: latestSha.substring(0, 8),
59
+ isOutdated,
60
+ source,
61
+ };
62
+ }
63
+ catch {
64
+ return {
65
+ name,
66
+ currentSha: lockEntry.sha.substring(0, 8),
67
+ latestSha: "error",
68
+ isOutdated: false,
69
+ source,
70
+ };
71
+ }
72
+ }
73
+ function printStatusTable(args) {
74
+ const { entries } = args;
75
+ console.log("\nRule Status:");
76
+ console.log("-".repeat(60));
77
+ for (const entry of entries) {
78
+ const marker = entry.isOutdated ? "!" : " ";
79
+ const status = entry.isOutdated ? "outdated" : "current";
80
+ console.log(`${marker} ${entry.name}: ${entry.currentSha} (${status})`);
81
+ }
82
+ }
83
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { SyncResult } from "../types.js";
2
+ type SyncArgs = {
3
+ force?: boolean;
4
+ };
5
+ type SyncOutput = {
6
+ results: SyncResult[];
7
+ };
8
+ export declare function sync(args?: SyncArgs): Promise<SyncOutput>;
9
+ export {};
10
+ //# sourceMappingURL=sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,aAAa,CAAC;AAE1D,KAAK,QAAQ,GAAG;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,KAAK,UAAU,GAAG;IAChB,OAAO,EAAE,UAAU,EAAE,CAAC;CACvB,CAAC;AAEF,wBAAsB,IAAI,CAAC,IAAI,GAAE,QAAa,GAAG,OAAO,CAAC,UAAU,CAAC,CAsBnE"}
@@ -0,0 +1,52 @@
1
+ import { writeFile, mkdir } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { readConfig, readLock, writeLock, getSharedDir, createEmptyLock, } from "../config.js";
4
+ import { resolveSource } from "../resolver.js";
5
+ import { fetchContent } from "../fetcher.js";
6
+ export async function sync(args = {}) {
7
+ const { force = false } = args;
8
+ const config = await readConfig();
9
+ if (!config) {
10
+ console.error("No shared.json found. Run `ruleshare init` first.");
11
+ return { results: [] };
12
+ }
13
+ const lock = (await readLock()) || createEmptyLock();
14
+ const sharedDir = getSharedDir();
15
+ await mkdir(sharedDir, { recursive: true });
16
+ const results = [];
17
+ for (const [name, source] of Object.entries(config.rules)) {
18
+ const result = await syncRule({ name, source, lock, sharedDir, force });
19
+ results.push(result);
20
+ }
21
+ await writeLock(lock);
22
+ return { results };
23
+ }
24
+ async function syncRule(args) {
25
+ const { name, source, lock, sharedDir, force } = args;
26
+ try {
27
+ return await attemptSync({ name, source, lock, sharedDir, force });
28
+ }
29
+ catch (error) {
30
+ const message = error instanceof Error ? error.message : String(error);
31
+ console.error(` ${name}: error - ${message}`);
32
+ return { name, status: "error", error: message };
33
+ }
34
+ }
35
+ async function attemptSync(args) {
36
+ const { name, source, lock, sharedDir, force } = args;
37
+ const config = await readConfig();
38
+ const resolved = resolveSource({ source, config: config });
39
+ const { content, sha } = await fetchContent({ resolved: resolved.resolved });
40
+ const existingEntry = lock.rules[name];
41
+ if (existingEntry?.sha === sha && !force) {
42
+ console.log(` ${name}: unchanged`);
43
+ return { name, status: "unchanged" };
44
+ }
45
+ const filePath = join(sharedDir, `${name}.md`);
46
+ await writeFile(filePath, content, "utf-8");
47
+ lock.rules[name] = { source, sha, updated: new Date().toISOString() };
48
+ const status = existingEntry ? "updated" : "created";
49
+ console.log(` ${name}: ${status}`);
50
+ return { name, status };
51
+ }
52
+ //# sourceMappingURL=sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { SharedConfig, SharedLock } from "./types.js";
2
+ export declare function getConfigPath(): string;
3
+ export declare function getLockPath(): string;
4
+ export declare function getSharedDir(): string;
5
+ export declare function readConfig(): Promise<SharedConfig | null>;
6
+ export declare function writeConfig(config: SharedConfig): Promise<void>;
7
+ export declare function readLock(): Promise<SharedLock | null>;
8
+ export declare function writeLock(lock: SharedLock): Promise<void>;
9
+ export declare function createEmptyConfig(): SharedConfig;
10
+ export declare function createEmptyLock(): SharedLock;
11
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAM3D,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAO/D;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAKrE;AAED,wBAAsB,QAAQ,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAO3D;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAK/D;AAED,wBAAgB,iBAAiB,IAAI,YAAY,CAEhD;AAED,wBAAgB,eAAe,IAAI,UAAU,CAE5C"}
package/dist/config.js ADDED
@@ -0,0 +1,50 @@
1
+ import { readFile, writeFile, mkdir } from "node:fs/promises";
2
+ import { existsSync } from "node:fs";
3
+ import { dirname, join } from "node:path";
4
+ const CONFIG_FILE = "shared.json";
5
+ const LOCK_FILE = "shared.lock";
6
+ const RULES_DIR = ".claude/rules";
7
+ export function getConfigPath() {
8
+ return join(process.cwd(), RULES_DIR, CONFIG_FILE);
9
+ }
10
+ export function getLockPath() {
11
+ return join(process.cwd(), RULES_DIR, LOCK_FILE);
12
+ }
13
+ export function getSharedDir() {
14
+ return join(process.cwd(), RULES_DIR, "shared");
15
+ }
16
+ export async function readConfig() {
17
+ const path = getConfigPath();
18
+ if (!existsSync(path)) {
19
+ return null;
20
+ }
21
+ const content = await readFile(path, "utf-8");
22
+ return JSON.parse(content);
23
+ }
24
+ export async function writeConfig(config) {
25
+ const path = getConfigPath();
26
+ await mkdir(dirname(path), { recursive: true });
27
+ const content = JSON.stringify(config, null, 2);
28
+ await writeFile(path, content, "utf-8");
29
+ }
30
+ export async function readLock() {
31
+ const path = getLockPath();
32
+ if (!existsSync(path)) {
33
+ return null;
34
+ }
35
+ const content = await readFile(path, "utf-8");
36
+ return JSON.parse(content);
37
+ }
38
+ export async function writeLock(lock) {
39
+ const path = getLockPath();
40
+ await mkdir(dirname(path), { recursive: true });
41
+ const content = JSON.stringify(lock, null, 2);
42
+ await writeFile(path, content, "utf-8");
43
+ }
44
+ export function createEmptyConfig() {
45
+ return { sources: {}, rules: {} };
46
+ }
47
+ export function createEmptyLock() {
48
+ return { version: 1, rules: {} };
49
+ }
50
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAG1C,MAAM,WAAW,GAAG,aAAa,CAAC;AAClC,MAAM,SAAS,GAAG,aAAa,CAAC;AAChC,MAAM,SAAS,GAAG,eAAe,CAAC;AAElC,MAAM,UAAU,aAAa;IAC3B,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,IAAI,GAAG,aAAa,EAAE,CAAC;IAC7B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC9C,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAiB,CAAC;AAC7C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAAoB;IACpD,MAAM,IAAI,GAAG,aAAa,EAAE,CAAC;IAC7B,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAChD,MAAM,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ;IAC5B,MAAM,IAAI,GAAG,WAAW,EAAE,CAAC;IAC3B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC9C,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAe,CAAC;AAC3C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAgB;IAC9C,MAAM,IAAI,GAAG,WAAW,EAAE,CAAC;IAC3B,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC9C,MAAM,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;AACnC,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { ResolvedSource, FetchResult } from "./types.js";
2
+ type FetchArgs = {
3
+ resolved: ResolvedSource;
4
+ };
5
+ export declare function fetchContent(args: FetchArgs): Promise<FetchResult>;
6
+ type CheckUpdateArgs = {
7
+ resolved: ResolvedSource;
8
+ currentSha: string;
9
+ };
10
+ type CheckUpdateResult = {
11
+ isOutdated: boolean;
12
+ latestSha: string;
13
+ };
14
+ export declare function checkForUpdate(args: CheckUpdateArgs): Promise<CheckUpdateResult>;
15
+ export {};
16
+ //# sourceMappingURL=fetcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetcher.d.ts","sourceRoot":"","sources":["../src/fetcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9D,KAAK,SAAS,GAAG;IACf,QAAQ,EAAE,cAAc,CAAC;CAC1B,CAAC;AAEF,wBAAsB,YAAY,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAQxE;AAiED,KAAK,eAAe,GAAG;IACrB,QAAQ,EAAE,cAAc,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,KAAK,iBAAiB,GAAG;IACvB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,wBAAsB,cAAc,CAClC,IAAI,EAAE,eAAe,GACpB,OAAO,CAAC,iBAAiB,CAAC,CAI5B"}
@@ -0,0 +1,51 @@
1
+ export async function fetchContent(args) {
2
+ const { resolved } = args;
3
+ if (resolved.type === "url") {
4
+ return fetchFromUrl({ url: resolved.url });
5
+ }
6
+ return fetchFromGitHub({ resolved });
7
+ }
8
+ async function fetchFromUrl(args) {
9
+ const { url } = args;
10
+ const response = await fetch(url);
11
+ if (!response.ok) {
12
+ throw new Error(`Failed to fetch ${url}: ${response.statusText}`);
13
+ }
14
+ const content = await response.text();
15
+ const sha = await computeHash({ content });
16
+ return { content, sha };
17
+ }
18
+ async function fetchFromGitHub(args) {
19
+ const { resolved } = args;
20
+ const { owner, repo, path, ref } = resolved;
21
+ const branch = ref || "main";
22
+ const url = `https://raw.githubusercontent.com/${owner}/${repo}/${branch}/${path}`;
23
+ const response = await fetch(url);
24
+ if (!response.ok) {
25
+ const fallbackUrl = url.replace("/main/", "/master/");
26
+ const fallbackResponse = await fetch(fallbackUrl);
27
+ if (!fallbackResponse.ok) {
28
+ throw new Error(`Failed to fetch from GitHub: ${response.statusText}`);
29
+ }
30
+ const content = await fallbackResponse.text();
31
+ const sha = await computeHash({ content });
32
+ return { content, sha };
33
+ }
34
+ const content = await response.text();
35
+ const sha = await computeHash({ content });
36
+ return { content, sha };
37
+ }
38
+ async function computeHash(args) {
39
+ const { content } = args;
40
+ const encoder = new TextEncoder();
41
+ const data = encoder.encode(content);
42
+ const hashBuffer = await crypto.subtle.digest("SHA-256", data);
43
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
44
+ return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
45
+ }
46
+ export async function checkForUpdate(args) {
47
+ const { resolved, currentSha } = args;
48
+ const { sha: latestSha } = await fetchContent({ resolved });
49
+ return { isOutdated: currentSha !== latestSha, latestSha };
50
+ }
51
+ //# sourceMappingURL=fetcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetcher.js","sourceRoot":"","sources":["../src/fetcher.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAe;IAChD,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IAE1B,IAAI,QAAQ,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;QAC5B,OAAO,YAAY,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAI,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,OAAO,eAAe,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;AACvC,CAAC;AAMD,KAAK,UAAU,YAAY,CAAC,IAAkB;IAC5C,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IACrB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;IAElC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,mBAAmB,GAAG,KAAK,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;IACpE,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACtC,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IAE3C,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AAC1B,CAAC;AAMD,KAAK,UAAU,eAAe,CAAC,IAAqB;IAClD,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,QAAQ,CAAC;IAE5C,MAAM,MAAM,GAAG,GAAG,IAAI,MAAM,CAAC;IAC7B,MAAM,GAAG,GAAG,qCAAqC,KAAK,IAAI,IAAI,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;IAEnF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;IAElC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QACtD,MAAM,gBAAgB,GAAG,MAAM,KAAK,CAAC,WAAW,CAAC,CAAC;QAElD,IAAI,CAAC,gBAAgB,CAAC,EAAE,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,gCAAgC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;QACzE,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,gBAAgB,CAAC,IAAI,EAAE,CAAC;QAC9C,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;QAC3C,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;IAC1B,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACtC,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IAE3C,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AAC1B,CAAC;AAMD,KAAK,UAAU,WAAW,CAAC,IAAc;IACvC,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IACzB,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACrC,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAC/D,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;IACzD,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACxE,CAAC;AAYD,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,IAAqB;IAErB,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;IACtC,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,MAAM,YAAY,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC5D,OAAO,EAAE,UAAU,EAAE,UAAU,KAAK,SAAS,EAAE,SAAS,EAAE,CAAC;AAC7D,CAAC"}
@@ -0,0 +1,6 @@
1
+ export * from "./types.js";
2
+ export * from "./config.js";
3
+ export * from "./resolver.js";
4
+ export * from "./fetcher.js";
5
+ export * from "./commands/index.js";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export * from "./types.js";
2
+ export * from "./config.js";
3
+ export * from "./resolver.js";
4
+ export * from "./fetcher.js";
5
+ export * from "./commands/index.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { ResolvedSource, SharedConfig } from "./types.js";
2
+ type ResolveArgs = {
3
+ source: string;
4
+ config: SharedConfig;
5
+ };
6
+ type ResolveResult = {
7
+ resolved: ResolvedSource;
8
+ };
9
+ export declare function resolveSource(args: ResolveArgs): ResolveResult;
10
+ export {};
11
+ //# sourceMappingURL=resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../src/resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/D,KAAK,WAAW,GAAG;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,YAAY,CAAC;CACtB,CAAC;AAEF,KAAK,aAAa,GAAG;IACnB,QAAQ,EAAE,cAAc,CAAC;CAC1B,CAAC;AAEF,wBAAgB,aAAa,CAAC,IAAI,EAAE,WAAW,GAAG,aAAa,CAY9D"}
@@ -0,0 +1,58 @@
1
+ export function resolveSource(args) {
2
+ const { source, config } = args;
3
+ if (source.startsWith("https://") || source.startsWith("http://")) {
4
+ return { resolved: { type: "url", path: source, url: source } };
5
+ }
6
+ if (source.startsWith("github:")) {
7
+ return { resolved: parseGitHubSource({ source }) };
8
+ }
9
+ return resolveAlias({ source, config });
10
+ }
11
+ function resolveAlias(args) {
12
+ const { source, config } = args;
13
+ const aliasMatch = source.match(/^([^:]+):(.+)$/);
14
+ const hasAlias = aliasMatch && config.sources?.[aliasMatch[1]];
15
+ if (!hasAlias) {
16
+ throw new Error(`Invalid source format: ${source}`);
17
+ }
18
+ const alias = aliasMatch[1];
19
+ const filePath = aliasMatch[2];
20
+ const baseSource = config.sources[alias];
21
+ const combined = combineSourceAndPath({ baseSource, filePath });
22
+ return resolveSource({ source: combined, config });
23
+ }
24
+ function parseGitHubSource(args) {
25
+ const { source } = args;
26
+ const withoutPrefix = source.replace("github:", "");
27
+ const { ref, pathPart } = extractRef({ source: withoutPrefix });
28
+ const parts = pathPart.split("/");
29
+ if (parts.length < 3) {
30
+ throw new Error(`Invalid GitHub source: ${source}`);
31
+ }
32
+ return {
33
+ type: "github",
34
+ owner: parts[0],
35
+ repo: parts[1],
36
+ path: parts.slice(2).join("/"),
37
+ ref,
38
+ };
39
+ }
40
+ function extractRef(args) {
41
+ const { source } = args;
42
+ const atIndex = source.lastIndexOf("@");
43
+ const hasRef = atIndex > 0 && !source.substring(atIndex).includes("/");
44
+ if (!hasRef) {
45
+ return { ref: undefined, pathPart: source };
46
+ }
47
+ return {
48
+ ref: source.substring(atIndex + 1),
49
+ pathPart: source.substring(0, atIndex),
50
+ };
51
+ }
52
+ function combineSourceAndPath(args) {
53
+ const { baseSource, filePath } = args;
54
+ const { ref, pathPart: cleanFilePath } = extractRef({ source: filePath });
55
+ const combined = `${baseSource}/${cleanFilePath}`;
56
+ return ref ? `${combined}@${ref}` : combined;
57
+ }
58
+ //# sourceMappingURL=resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolver.js","sourceRoot":"","sources":["../src/resolver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ export type SharedConfig = {
2
+ sources?: Record<string, string>;
3
+ rules: Record<string, string>;
4
+ };
5
+ export type LockEntry = {
6
+ source: string;
7
+ sha: string;
8
+ tag?: string;
9
+ updated: string;
10
+ };
11
+ export type SharedLock = {
12
+ version: number;
13
+ rules: Record<string, LockEntry>;
14
+ };
15
+ export type ResolvedSource = {
16
+ type: "github" | "url";
17
+ owner?: string;
18
+ repo?: string;
19
+ path: string;
20
+ ref?: string;
21
+ url?: string;
22
+ };
23
+ export type FetchResult = {
24
+ content: string;
25
+ sha: string;
26
+ };
27
+ export type SyncResult = {
28
+ name: string;
29
+ status: "created" | "updated" | "unchanged" | "error";
30
+ error?: string;
31
+ };
32
+ export type StatusEntry = {
33
+ name: string;
34
+ currentSha: string;
35
+ latestSha: string;
36
+ isOutdated: boolean;
37
+ source: string;
38
+ };
39
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,QAAQ,GAAG,KAAK,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,OAAO,CAAC;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "ruleshare",
3
+ "version": "0.1.0",
4
+ "description": "Sync shared Claude Code rules from remote sources",
5
+ "type": "module",
6
+ "bin": {
7
+ "ruleshare": "./dist/cli.js"
8
+ },
9
+ "main": "./dist/index.js",
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/kevincrabbe/ruleshare.git"
16
+ },
17
+ "scripts": {
18
+ "build": "tsc",
19
+ "dev": "tsc --watch",
20
+ "start": "node ./dist/cli.js",
21
+ "lint": "eslint src/",
22
+ "lint:fix": "eslint src/ --fix",
23
+ "typecheck": "tsc --noEmit"
24
+ },
25
+ "keywords": [
26
+ "claude",
27
+ "claude-code",
28
+ "rules",
29
+ "ai",
30
+ "sync"
31
+ ],
32
+ "author": "",
33
+ "license": "MIT",
34
+ "devDependencies": {
35
+ "@eslint/js": "^9.0.0",
36
+ "@types/node": "^20.0.0",
37
+ "eslint": "^9.0.0",
38
+ "typescript": "^5.0.0",
39
+ "typescript-eslint": "^8.0.0"
40
+ },
41
+ "engines": {
42
+ "node": ">=18.0.0"
43
+ }
44
+ }