@madkid/relay-ctx 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 (45) hide show
  1. package/dist/commands/checkpoint.d.ts +18 -0
  2. package/dist/commands/checkpoint.d.ts.map +1 -0
  3. package/dist/commands/checkpoint.js +130 -0
  4. package/dist/commands/checkpoint.js.map +1 -0
  5. package/dist/commands/hooks.d.ts +36 -0
  6. package/dist/commands/hooks.d.ts.map +1 -0
  7. package/dist/commands/hooks.js +226 -0
  8. package/dist/commands/hooks.js.map +1 -0
  9. package/dist/commands/init.d.ts +14 -0
  10. package/dist/commands/init.d.ts.map +1 -0
  11. package/dist/commands/init.js +228 -0
  12. package/dist/commands/init.js.map +1 -0
  13. package/dist/commands/inject.d.ts +20 -0
  14. package/dist/commands/inject.d.ts.map +1 -0
  15. package/dist/commands/inject.js +209 -0
  16. package/dist/commands/inject.js.map +1 -0
  17. package/dist/commands/list.d.ts +2 -0
  18. package/dist/commands/list.d.ts.map +1 -0
  19. package/dist/commands/list.js +174 -0
  20. package/dist/commands/list.js.map +1 -0
  21. package/dist/commands/sync.d.ts +17 -0
  22. package/dist/commands/sync.d.ts.map +1 -0
  23. package/dist/commands/sync.js +239 -0
  24. package/dist/commands/sync.js.map +1 -0
  25. package/dist/core/compressor.d.ts +16 -0
  26. package/dist/core/compressor.d.ts.map +1 -0
  27. package/dist/core/compressor.js +354 -0
  28. package/dist/core/compressor.js.map +1 -0
  29. package/dist/core/scanner.d.ts +40 -0
  30. package/dist/core/scanner.d.ts.map +1 -0
  31. package/dist/core/scanner.js +366 -0
  32. package/dist/core/scanner.js.map +1 -0
  33. package/dist/core/storage.d.ts +39 -0
  34. package/dist/core/storage.d.ts.map +1 -0
  35. package/dist/core/storage.js +122 -0
  36. package/dist/core/storage.js.map +1 -0
  37. package/dist/index.d.ts +3 -0
  38. package/dist/index.d.ts.map +1 -0
  39. package/dist/index.js +57 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/test-relay.d.ts +2 -0
  42. package/dist/test-relay.d.ts.map +1 -0
  43. package/dist/test-relay.js +433 -0
  44. package/dist/test-relay.js.map +1 -0
  45. package/package.json +32 -0
@@ -0,0 +1,18 @@
1
+ /**
2
+ * relay checkpoint <message> — Save a named snapshot of current context.
3
+ *
4
+ * Options:
5
+ * --list List all saved checkpoints
6
+ * --silent Suppress all output (used by git hooks)
7
+ *
8
+ * Flow:
9
+ * 1. Read current PROJECT.md
10
+ * 2. Create snapshot file in projects/{name}/snapshots/
11
+ * 3. Append checkpoint entry to PROJECT.md under "## Checkpoints"
12
+ * 4. Success message (unless --silent)
13
+ */
14
+ export declare function checkpointCommand(message?: string, options?: {
15
+ list?: boolean;
16
+ silent?: boolean;
17
+ }): Promise<void>;
18
+ //# sourceMappingURL=checkpoint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkpoint.d.ts","sourceRoot":"","sources":["../../src/commands/checkpoint.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,CAAC,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAC7C,OAAO,CAAC,IAAI,CAAC,CAsHf"}
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.checkpointCommand = checkpointCommand;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const storage_1 = require("../core/storage");
10
+ /**
11
+ * relay checkpoint <message> — Save a named snapshot of current context.
12
+ *
13
+ * Options:
14
+ * --list List all saved checkpoints
15
+ * --silent Suppress all output (used by git hooks)
16
+ *
17
+ * Flow:
18
+ * 1. Read current PROJECT.md
19
+ * 2. Create snapshot file in projects/{name}/snapshots/
20
+ * 3. Append checkpoint entry to PROJECT.md under "## Checkpoints"
21
+ * 4. Success message (unless --silent)
22
+ */
23
+ async function checkpointCommand(message, options) {
24
+ const projectName = (0, storage_1.getProjectName)();
25
+ const projectPath = (0, storage_1.getProjectPath)();
26
+ const silent = options?.silent ?? false;
27
+ if (!fs_1.default.existsSync(projectPath)) {
28
+ if (silent)
29
+ return;
30
+ console.log('āŒ Relay not initialized for this project. Run `relay init` first.');
31
+ process.exit(1);
32
+ }
33
+ const snapshotsDir = path_1.default.join(projectPath, 'snapshots');
34
+ if (options?.list) {
35
+ if (!fs_1.default.existsSync(snapshotsDir)) {
36
+ if (!silent)
37
+ console.log('No checkpoints found.');
38
+ return;
39
+ }
40
+ const files = fs_1.default.readdirSync(snapshotsDir);
41
+ const mdFiles = files.filter((f) => f.endsWith('.md')).sort();
42
+ if (mdFiles.length === 0) {
43
+ if (!silent)
44
+ console.log('No checkpoints found.');
45
+ return;
46
+ }
47
+ if (silent)
48
+ return;
49
+ console.log(`\nšŸ’¾ Saved checkpoints for "${projectName}":\n`);
50
+ mdFiles.forEach((file) => {
51
+ const datetimePart = file.slice(0, 19); // 2026-06-16T05-30-22
52
+ const dateStr = datetimePart.split('T')[0];
53
+ const timeStr = datetimePart.split('T')[1]?.replace(/-/g, ':') || '';
54
+ const msgStr = file.slice(20, -3).replace(/-/g, ' ');
55
+ console.log(` [${dateStr} ${timeStr}] "${msgStr}"`);
56
+ });
57
+ console.log('');
58
+ return;
59
+ }
60
+ if (!message) {
61
+ if (silent)
62
+ return;
63
+ console.log('āŒ Error: Checkpoint message is required.');
64
+ process.exit(1);
65
+ }
66
+ const projectMd = (0, storage_1.readProjectMd)();
67
+ if (!projectMd) {
68
+ if (silent)
69
+ return;
70
+ console.log('āŒ PROJECT.md is empty. Run `relay sync` first.');
71
+ process.exit(1);
72
+ }
73
+ // 1. Build timestamp
74
+ const now = new Date();
75
+ const dateStr = now.toISOString().split('T')[0]; // 2024-01-15
76
+ const timeStr = now.toTimeString().slice(0, 5); // 14:32
77
+ const fileTimestamp = now.toISOString().replace(/[:.]/g, '-').slice(0, 19); // 2024-01-15T14-32-00
78
+ // 2. Create snapshot file
79
+ fs_1.default.mkdirSync(snapshotsDir, { recursive: true });
80
+ const sanitizedMessage = message
81
+ .toLowerCase()
82
+ .replace(/[^a-z0-9]+/g, '-')
83
+ .replace(/(^-|-$)/g, '');
84
+ const snapshotFilename = `${fileTimestamp}-${sanitizedMessage}.md`;
85
+ const snapshotPath = path_1.default.join(snapshotsDir, snapshotFilename);
86
+ const snapshotContent = `# Checkpoint: ${message}\n\n` +
87
+ `> Saved: ${dateStr} ${timeStr}\n` +
88
+ `> Project: ${projectName}\n\n` +
89
+ `---\n\n` +
90
+ projectMd;
91
+ fs_1.default.writeFileSync(snapshotPath, snapshotContent, 'utf-8');
92
+ // 3. Append checkpoint to PROJECT.md
93
+ const checkpointEntry = `- [${dateStr} ${timeStr}] "${message}"`;
94
+ let updatedMd;
95
+ if (projectMd.includes('## Checkpoints')) {
96
+ // Append to existing checkpoints section
97
+ updatedMd = projectMd.replace(/(## Checkpoints\n)([\s\S]*?)(\n##|\n---|\s*$)/, (match, heading, existing, after) => {
98
+ return `${heading}${existing.trimEnd()}\n${checkpointEntry}\n${after}`;
99
+ });
100
+ // If the regex didn't match (e.g. checkpoints is the last section), try simpler append
101
+ if (updatedMd === projectMd) {
102
+ updatedMd = projectMd.trimEnd() + `\n${checkpointEntry}\n`;
103
+ }
104
+ }
105
+ else {
106
+ // Add new checkpoints section
107
+ updatedMd = projectMd.trimEnd() + `\n\n## Checkpoints\n\n${checkpointEntry}\n`;
108
+ }
109
+ (0, storage_1.writeProjectMd)(updatedMd);
110
+ // Update meta.json
111
+ const metaPath = path_1.default.join(projectPath, 'meta.json');
112
+ let meta = {};
113
+ if (fs_1.default.existsSync(metaPath)) {
114
+ try {
115
+ meta = JSON.parse(fs_1.default.readFileSync(metaPath, 'utf-8'));
116
+ }
117
+ catch {
118
+ // ignore
119
+ }
120
+ }
121
+ meta.name = projectName;
122
+ meta.lastCheckpoint = new Date().toISOString();
123
+ fs_1.default.writeFileSync(metaPath, JSON.stringify(meta, null, 2), 'utf-8');
124
+ // 4. Success
125
+ if (!silent) {
126
+ console.log(`\nāœ… Checkpoint saved: "${message}"`);
127
+ console.log(` šŸ“„ ${snapshotPath}\n`);
128
+ }
129
+ }
130
+ //# sourceMappingURL=checkpoint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkpoint.js","sourceRoot":"","sources":["../../src/commands/checkpoint.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Install all 3 git hooks for Relay.
3
+ * Returns the list of installed hook names and any skipped hooks.
4
+ */
5
+ export declare function installHooks(): {
6
+ installed: string[];
7
+ skipped: string[];
8
+ };
9
+ /**
10
+ * Remove all relay-managed git hooks.
11
+ * Returns the list of removed hook names.
12
+ */
13
+ export declare function uninstallHooks(): string[];
14
+ /**
15
+ * Check the installation status of all 3 git hooks.
16
+ */
17
+ export declare function getHooksStatus(): Array<{
18
+ name: string;
19
+ exists: boolean;
20
+ relayManaged: boolean;
21
+ path: string;
22
+ }>;
23
+ /**
24
+ * relay hooks — Manage git hooks for automatic context tracking.
25
+ *
26
+ * Options:
27
+ * --install Install git hooks into this project
28
+ * --uninstall Remove git hooks from this project
29
+ * --status Show current hook installation status
30
+ */
31
+ export declare function hooksCommand(options: {
32
+ install?: boolean;
33
+ uninstall?: boolean;
34
+ status?: boolean;
35
+ }): Promise<void>;
36
+ //# sourceMappingURL=hooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/commands/hooks.ts"],"names":[],"mappings":"AAkEA;;;GAGG;AACH,wBAAgB,YAAY,IAAI;IAAE,SAAS,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAmCzE;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,MAAM,EAAE,CAgBzC;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,KAAK,CAAC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,EAAE,OAAO,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC,CAcD;AAED;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE;IAC1C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,GAAG,OAAO,CAAC,IAAI,CAAC,CA0FhB"}
@@ -0,0 +1,226 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.installHooks = installHooks;
7
+ exports.uninstallHooks = uninstallHooks;
8
+ exports.getHooksStatus = getHooksStatus;
9
+ exports.hooksCommand = hooksCommand;
10
+ const fs_1 = __importDefault(require("fs"));
11
+ const path_1 = __importDefault(require("path"));
12
+ const storage_1 = require("../core/storage");
13
+ const RELAY_MANAGED_MARKER = '# relay-managed';
14
+ const HOOKS = [
15
+ {
16
+ name: 'post-commit',
17
+ content: `#!/bin/sh
18
+ ${RELAY_MANAGED_MARKER}
19
+ COMMIT_MSG=$(git log -1 --pretty=%B | head -1)
20
+ relay checkpoint "$COMMIT_MSG" --silent 2>/dev/null || true
21
+ `,
22
+ description: 'auto-checkpoint with your commit message',
23
+ },
24
+ {
25
+ name: 'post-checkout',
26
+ content: `#!/bin/sh
27
+ ${RELAY_MANAGED_MARKER}
28
+ PREV_HEAD=$1
29
+ NEW_HEAD=$2
30
+ BRANCH_SWITCH=$3
31
+
32
+ if [ "$BRANCH_SWITCH" = "1" ]; then
33
+ BRANCH=$(git rev-parse --abbrev-ref HEAD)
34
+ relay sync --silent 2>/dev/null || true
35
+ echo "⚔ Relay: synced context for branch '$BRANCH'"
36
+ fi
37
+ `,
38
+ description: 'auto-sync when you switch branches',
39
+ },
40
+ {
41
+ name: 'post-merge',
42
+ content: `#!/bin/sh
43
+ ${RELAY_MANAGED_MARKER}
44
+ relay sync --silent 2>/dev/null || true
45
+ relay checkpoint "post-merge sync" --silent 2>/dev/null || true
46
+ echo "⚔ Relay: context updated after merge"
47
+ `,
48
+ description: 'auto-sync + checkpoint after merges',
49
+ },
50
+ ];
51
+ /**
52
+ * Get the .git/hooks directory for the current project.
53
+ */
54
+ function getGitHooksDir() {
55
+ return path_1.default.join(process.cwd(), '.git', 'hooks');
56
+ }
57
+ /**
58
+ * Check if a hook file is relay-managed.
59
+ */
60
+ function isRelayManaged(hookPath) {
61
+ if (!fs_1.default.existsSync(hookPath))
62
+ return false;
63
+ const content = fs_1.default.readFileSync(hookPath, 'utf-8');
64
+ return content.includes(RELAY_MANAGED_MARKER);
65
+ }
66
+ /**
67
+ * Install all 3 git hooks for Relay.
68
+ * Returns the list of installed hook names and any skipped hooks.
69
+ */
70
+ function installHooks() {
71
+ const hookNames = HOOKS.map((h) => h.name);
72
+ const installed = [];
73
+ const skipped = [];
74
+ const hooksDir = getGitHooksDir();
75
+ // Ensure hooks directory exists
76
+ fs_1.default.mkdirSync(hooksDir, { recursive: true });
77
+ for (const hook of HOOKS) {
78
+ const hookPath = path_1.default.join(hooksDir, hook.name);
79
+ if (fs_1.default.existsSync(hookPath)) {
80
+ if (isRelayManaged(hookPath)) {
81
+ // Overwrite existing relay-managed hook with latest content
82
+ fs_1.default.writeFileSync(hookPath, hook.content, 'utf-8');
83
+ if (process.platform !== 'win32') {
84
+ fs_1.default.chmodSync(hookPath, 0o755);
85
+ }
86
+ installed.push(hook.name);
87
+ }
88
+ else {
89
+ // Skip — hook exists but isn't relay-managed
90
+ skipped.push(hook.name);
91
+ }
92
+ }
93
+ else {
94
+ fs_1.default.writeFileSync(hookPath, hook.content, 'utf-8');
95
+ if (process.platform !== 'win32') {
96
+ fs_1.default.chmodSync(hookPath, 0o755);
97
+ }
98
+ installed.push(hook.name);
99
+ }
100
+ }
101
+ return { installed, skipped };
102
+ }
103
+ /**
104
+ * Remove all relay-managed git hooks.
105
+ * Returns the list of removed hook names.
106
+ */
107
+ function uninstallHooks() {
108
+ const removed = [];
109
+ const hooksDir = getGitHooksDir();
110
+ if (!fs_1.default.existsSync(hooksDir))
111
+ return removed;
112
+ for (const hook of HOOKS) {
113
+ const hookPath = path_1.default.join(hooksDir, hook.name);
114
+ if (fs_1.default.existsSync(hookPath) && isRelayManaged(hookPath)) {
115
+ fs_1.default.unlinkSync(hookPath);
116
+ removed.push(hook.name);
117
+ }
118
+ }
119
+ return removed;
120
+ }
121
+ /**
122
+ * Check the installation status of all 3 git hooks.
123
+ */
124
+ function getHooksStatus() {
125
+ const hooksDir = getGitHooksDir();
126
+ return HOOKS.map((hook) => {
127
+ const hookPath = path_1.default.join(hooksDir, hook.name);
128
+ const exists = fs_1.default.existsSync(hookPath);
129
+ return {
130
+ name: hook.name,
131
+ exists,
132
+ relayManaged: isRelayManaged(hookPath),
133
+ path: hookPath,
134
+ description: hook.description,
135
+ };
136
+ });
137
+ }
138
+ /**
139
+ * relay hooks — Manage git hooks for automatic context tracking.
140
+ *
141
+ * Options:
142
+ * --install Install git hooks into this project
143
+ * --uninstall Remove git hooks from this project
144
+ * --status Show current hook installation status
145
+ */
146
+ async function hooksCommand(options) {
147
+ const projectName = (0, storage_1.getProjectName)();
148
+ // Default to --status if no option given
149
+ if (!options.install && !options.uninstall && !options.status) {
150
+ options.status = true;
151
+ }
152
+ if (options.status) {
153
+ const statusList = getHooksStatus();
154
+ console.log(`\nšŸ”Œ Relay hooks status for "${projectName}":\n`);
155
+ for (const s of statusList) {
156
+ let state;
157
+ if (!s.exists) {
158
+ state = 'āŒ Not installed';
159
+ }
160
+ else if (s.relayManaged) {
161
+ state = 'āœ… Installed (relay-managed)';
162
+ }
163
+ else {
164
+ state = 'āš ļø Exists (not relay-managed)';
165
+ }
166
+ const hookDef = HOOKS.find((h) => h.name === s.name);
167
+ const desc = hookDef ? hookDef.description : '';
168
+ console.log(` ${s.name.padEnd(15)} ${state}`);
169
+ console.log(` ${''.padEnd(15)} → ${desc}`);
170
+ console.log(` ${''.padEnd(15)} Path: ${s.path}`);
171
+ console.log('');
172
+ }
173
+ return;
174
+ }
175
+ if (options.install) {
176
+ // Validate: must be a git repo
177
+ const gitDir = path_1.default.join(process.cwd(), '.git');
178
+ if (!fs_1.default.existsSync(gitDir)) {
179
+ console.log('āŒ Error: Current directory is not a git repository.');
180
+ console.log(' Run `git init` first, then `relay hooks --install`.\n');
181
+ return;
182
+ }
183
+ // Validate: relay must be initialized
184
+ const projectPath = (0, storage_1.getProjectPath)();
185
+ if (!fs_1.default.existsSync(projectPath)) {
186
+ console.log('āŒ Error: Relay is not initialized for this project.');
187
+ console.log(' Run `relay init` first.\n');
188
+ return;
189
+ }
190
+ const { installed, skipped } = installHooks();
191
+ if (installed.length > 0) {
192
+ console.log(`\n⚔ Relay hooks installed for "${projectName}"\n`);
193
+ for (const name of installed) {
194
+ const hookDef = HOOKS.find((h) => h.name === name);
195
+ const desc = hookDef ? hookDef.description : '';
196
+ console.log(` ${name.padEnd(15)} → ${desc}`);
197
+ }
198
+ console.log('\nEvery git commit now saves a Relay checkpoint automatically.');
199
+ console.log('After 30 commits you\'ll have a complete decision trail.');
200
+ console.log('\nTo remove: relay hooks --uninstall\n');
201
+ }
202
+ if (skipped.length > 0) {
203
+ for (const name of skipped) {
204
+ console.log(`āš ļø Skipped ${name}: hook already exists (not relay-managed).`);
205
+ console.log(' Add relay checkpoint manually.');
206
+ }
207
+ console.log('');
208
+ }
209
+ return;
210
+ }
211
+ if (options.uninstall) {
212
+ const removed = uninstallHooks();
213
+ if (removed.length > 0) {
214
+ console.log(`\nšŸ”Œ Relay hooks removed for "${projectName}":\n`);
215
+ for (const name of removed) {
216
+ console.log(` āœ… ${name} — removed`);
217
+ }
218
+ console.log('\nGit hooks are no longer active. Re-install with: relay hooks --install\n');
219
+ }
220
+ else {
221
+ console.log('\nNo relay-managed hooks found to remove.\n');
222
+ }
223
+ return;
224
+ }
225
+ }
226
+ //# sourceMappingURL=hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/commands/hooks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * relay init — Initialize Relay for the current project.
3
+ *
4
+ * Flow:
5
+ * 1. Ensure relay root directory exists
6
+ * 2. Detect project name
7
+ * 3. Check for existing project, prompt for re-init
8
+ * 4. Interactive setup prompts
9
+ * 5. Check/prompt for Anthropic API key
10
+ * 6. Write initial PROJECT.md
11
+ * 7. Ask about installing git hooks
12
+ */
13
+ export declare function initCommand(): Promise<void>;
14
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AA+DA;;;;;;;;;;;GAWG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAoJjD"}