youmd 0.8.2 → 0.8.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/chat.d.ts.map +1 -1
- package/dist/commands/chat.js +17 -0
- package/dist/commands/chat.js.map +1 -1
- package/dist/commands/env.d.ts +19 -4
- package/dist/commands/env.d.ts.map +1 -1
- package/dist/commands/env.js +243 -21
- package/dist/commands/env.js.map +1 -1
- package/dist/commands/stack.d.ts.map +1 -1
- package/dist/commands/stack.js +8 -2
- package/dist/commands/stack.js.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +8 -1
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/sync.d.ts +1 -0
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +184 -0
- package/dist/commands/sync.js.map +1 -1
- package/dist/index.js +40 -4
- package/dist/index.js.map +1 -1
- package/dist/lib/api.d.ts +74 -0
- package/dist/lib/api.d.ts.map +1 -1
- package/dist/lib/api.js +36 -0
- package/dist/lib/api.js.map +1 -1
- package/dist/lib/daemon.d.ts +3 -0
- package/dist/lib/daemon.d.ts.map +1 -1
- package/dist/lib/daemon.js +21 -0
- package/dist/lib/daemon.js.map +1 -1
- package/dist/lib/machine-bootstrap-prompt.d.ts.map +1 -1
- package/dist/lib/machine-bootstrap-prompt.js +305 -184
- package/dist/lib/machine-bootstrap-prompt.js.map +1 -1
- package/dist/lib/realtime-sync.d.ts +128 -0
- package/dist/lib/realtime-sync.d.ts.map +1 -0
- package/dist/lib/realtime-sync.js +215 -0
- package/dist/lib/realtime-sync.js.map +1 -0
- package/package.json +2 -1
- package/scripts/env-vault/README.md +9 -0
- package/scripts/env-vault/restore.sh +85 -12
- package/scripts/skillstack-sync/README.md +24 -6
- package/scripts/skillstack-sync/bootstrap-new-mac.sh +31 -0
- package/scripts/skillstack-sync/com.youmd.realtime-sync.plist +35 -0
- package/scripts/skillstack-sync/install-daemons.sh +4 -1
- package/skills/machine-bootstrap.md +88 -19
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
export type RealtimeSyncHead = {
|
|
2
|
+
schemaVersion?: string;
|
|
3
|
+
serverNow?: number;
|
|
4
|
+
sessionExpiresAt?: number;
|
|
5
|
+
user?: {
|
|
6
|
+
username?: string;
|
|
7
|
+
plan?: string;
|
|
8
|
+
};
|
|
9
|
+
identity?: {
|
|
10
|
+
latestVersion?: number | null;
|
|
11
|
+
latestHash?: string | null;
|
|
12
|
+
publishedVersion?: number | null;
|
|
13
|
+
publishedHash?: string | null;
|
|
14
|
+
latestCreatedAt?: number | null;
|
|
15
|
+
latestPublishedAt?: number | null;
|
|
16
|
+
};
|
|
17
|
+
skills?: {
|
|
18
|
+
installedCount?: number;
|
|
19
|
+
latestInstalledAt?: number | null;
|
|
20
|
+
names?: string[];
|
|
21
|
+
};
|
|
22
|
+
portfolio?: {
|
|
23
|
+
updatedAt?: number | null;
|
|
24
|
+
projects?: number;
|
|
25
|
+
activeFocusedProjects?: number;
|
|
26
|
+
apiSurfaces?: number;
|
|
27
|
+
dependencyEdges?: number;
|
|
28
|
+
reusablePatterns?: number;
|
|
29
|
+
activities?: number;
|
|
30
|
+
providerAccounts?: number;
|
|
31
|
+
tasks?: number;
|
|
32
|
+
brainDumps?: number;
|
|
33
|
+
machineProofs?: number;
|
|
34
|
+
};
|
|
35
|
+
repoMirror?: {
|
|
36
|
+
repoFullName?: string | null;
|
|
37
|
+
commitSha?: string | null;
|
|
38
|
+
fileCount?: number;
|
|
39
|
+
totalBytes?: number;
|
|
40
|
+
truncated?: boolean;
|
|
41
|
+
syncedAt?: number;
|
|
42
|
+
} | null;
|
|
43
|
+
github?: {
|
|
44
|
+
repoFullName?: string | null;
|
|
45
|
+
lastSyncedAt?: number | null;
|
|
46
|
+
lastPushedCommitSha?: string | null;
|
|
47
|
+
mirrorStale?: boolean;
|
|
48
|
+
lastPushErrorAt?: number | null;
|
|
49
|
+
} | null;
|
|
50
|
+
encryptedEnvVault?: {
|
|
51
|
+
status?: "ready" | "missing" | "scope-missing" | string;
|
|
52
|
+
flow?: string;
|
|
53
|
+
available?: boolean;
|
|
54
|
+
snapshotCount?: number;
|
|
55
|
+
id?: string | null;
|
|
56
|
+
label?: string | null;
|
|
57
|
+
createdAt?: number | null;
|
|
58
|
+
fileName?: string | null;
|
|
59
|
+
contentType?: string | null;
|
|
60
|
+
encryptionTool?: string | null;
|
|
61
|
+
extension?: string | null;
|
|
62
|
+
formatVersion?: number | null;
|
|
63
|
+
sizeBytes?: number | null;
|
|
64
|
+
projectCount?: number | null;
|
|
65
|
+
variableCount?: number | null;
|
|
66
|
+
sha256?: string | null;
|
|
67
|
+
manifestSha256?: string | null;
|
|
68
|
+
agentAuthIncluded?: boolean;
|
|
69
|
+
sourceHost?: string | null;
|
|
70
|
+
sourceRoot?: string | null;
|
|
71
|
+
restoreMode?: string;
|
|
72
|
+
scope?: string;
|
|
73
|
+
secretValuesExposed?: false;
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
export declare const REALTIME_SYNC_STATUS_PATH: string;
|
|
77
|
+
export type RealtimeSecretVaultStatus = {
|
|
78
|
+
state: "ready" | "missing" | "scope-missing" | "unknown";
|
|
79
|
+
flow: "account-backed-encrypted-snapshot";
|
|
80
|
+
available: boolean;
|
|
81
|
+
snapshotCount: number;
|
|
82
|
+
summary: string;
|
|
83
|
+
latestSnapshot?: {
|
|
84
|
+
id?: string | null;
|
|
85
|
+
label?: string | null;
|
|
86
|
+
fileName?: string | null;
|
|
87
|
+
createdAt?: number | null;
|
|
88
|
+
sizeBytes?: number | null;
|
|
89
|
+
projectCount?: number | null;
|
|
90
|
+
variableCount?: number | null;
|
|
91
|
+
sha256?: string | null;
|
|
92
|
+
sha256Short?: string | null;
|
|
93
|
+
manifestSha256?: string | null;
|
|
94
|
+
encryptionTool?: string | null;
|
|
95
|
+
extension?: string | null;
|
|
96
|
+
formatVersion?: number | null;
|
|
97
|
+
agentAuthIncluded?: boolean;
|
|
98
|
+
sourceHost?: string | null;
|
|
99
|
+
sourceRoot?: string | null;
|
|
100
|
+
};
|
|
101
|
+
pullCommand: string;
|
|
102
|
+
restoreCommand: string;
|
|
103
|
+
secretValuesExposed: false;
|
|
104
|
+
};
|
|
105
|
+
export type RealtimeSyncStatusFile = {
|
|
106
|
+
schemaVersion: "you-md/realtime-sync-daemon-status/v1";
|
|
107
|
+
generatedAt: number;
|
|
108
|
+
summary: string;
|
|
109
|
+
user?: RealtimeSyncHead["user"];
|
|
110
|
+
identity?: RealtimeSyncHead["identity"];
|
|
111
|
+
skills?: {
|
|
112
|
+
installedCount?: number;
|
|
113
|
+
latestInstalledAt?: number | null;
|
|
114
|
+
};
|
|
115
|
+
portfolio?: RealtimeSyncHead["portfolio"];
|
|
116
|
+
repoMirror?: RealtimeSyncHead["repoMirror"];
|
|
117
|
+
github?: RealtimeSyncHead["github"];
|
|
118
|
+
secretVault: RealtimeSecretVaultStatus;
|
|
119
|
+
secretValuesExposed: false;
|
|
120
|
+
};
|
|
121
|
+
export declare function describeRealtimeSecretVault(head: RealtimeSyncHead | null | undefined): RealtimeSecretVaultStatus;
|
|
122
|
+
export declare function realtimeSyncHeadSignature(head: RealtimeSyncHead | null | undefined): string;
|
|
123
|
+
export declare function summarizeRealtimeSyncHead(head: RealtimeSyncHead): string;
|
|
124
|
+
export declare function buildRealtimeSyncStatusFile(head: RealtimeSyncHead): RealtimeSyncStatusFile;
|
|
125
|
+
export declare function writeRealtimeSyncStatusFile(head: RealtimeSyncHead): void;
|
|
126
|
+
export declare function readRealtimeSyncStatusFile(): RealtimeSyncStatusFile | null;
|
|
127
|
+
export declare function shouldRunBoundedSync(lastRunAt: number, now: number, minIntervalMs: number): boolean;
|
|
128
|
+
//# sourceMappingURL=realtime-sync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"realtime-sync.d.ts","sourceRoot":"","sources":["../../src/lib/realtime-sync.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.REALTIME_SYNC_STATUS_PATH = void 0;
|
|
37
|
+
exports.describeRealtimeSecretVault = describeRealtimeSecretVault;
|
|
38
|
+
exports.realtimeSyncHeadSignature = realtimeSyncHeadSignature;
|
|
39
|
+
exports.summarizeRealtimeSyncHead = summarizeRealtimeSyncHead;
|
|
40
|
+
exports.buildRealtimeSyncStatusFile = buildRealtimeSyncStatusFile;
|
|
41
|
+
exports.writeRealtimeSyncStatusFile = writeRealtimeSyncStatusFile;
|
|
42
|
+
exports.readRealtimeSyncStatusFile = readRealtimeSyncStatusFile;
|
|
43
|
+
exports.shouldRunBoundedSync = shouldRunBoundedSync;
|
|
44
|
+
const fs = __importStar(require("fs"));
|
|
45
|
+
const os = __importStar(require("os"));
|
|
46
|
+
const path = __importStar(require("path"));
|
|
47
|
+
exports.REALTIME_SYNC_STATUS_PATH = path.join(os.homedir(), ".youmd", "realtime-sync-status.json");
|
|
48
|
+
function shortSha(value) {
|
|
49
|
+
if (!value)
|
|
50
|
+
return null;
|
|
51
|
+
return value.length <= 16 ? value : `${value.slice(0, 12)}...${value.slice(-8)}`;
|
|
52
|
+
}
|
|
53
|
+
function describeRealtimeSecretVault(head) {
|
|
54
|
+
const vault = head?.encryptedEnvVault;
|
|
55
|
+
const state = vault?.status === "ready"
|
|
56
|
+
? "ready"
|
|
57
|
+
: vault?.status === "scope-missing" || vault?.scope === "vault-not-granted"
|
|
58
|
+
? "scope-missing"
|
|
59
|
+
: vault
|
|
60
|
+
? "missing"
|
|
61
|
+
: "unknown";
|
|
62
|
+
const pullCommand = "youmd env vault pull --out ~/.youmd/secret-vault";
|
|
63
|
+
const restoreCommand = "youmd env vault pull --restore --root ~/Desktop/CODE_YOU --map-existing --existing-only --skip-agent-auth";
|
|
64
|
+
if (state === "ready") {
|
|
65
|
+
const projects = vault?.projectCount ?? 0;
|
|
66
|
+
const vars = vault?.variableCount ?? 0;
|
|
67
|
+
const source = vault?.sourceHost ? ` from ${vault.sourceHost}` : "";
|
|
68
|
+
const hash = shortSha(vault?.sha256);
|
|
69
|
+
return {
|
|
70
|
+
state,
|
|
71
|
+
flow: "account-backed-encrypted-snapshot",
|
|
72
|
+
available: true,
|
|
73
|
+
snapshotCount: vault?.snapshotCount ?? 1,
|
|
74
|
+
summary: `Secret Vault ready: ${projects} projects / ${vars} vars${source}${hash ? ` / ${hash}` : ""}`,
|
|
75
|
+
latestSnapshot: {
|
|
76
|
+
id: vault?.id ?? null,
|
|
77
|
+
label: vault?.label ?? null,
|
|
78
|
+
fileName: vault?.fileName ?? null,
|
|
79
|
+
createdAt: vault?.createdAt ?? null,
|
|
80
|
+
sizeBytes: vault?.sizeBytes ?? null,
|
|
81
|
+
projectCount: vault?.projectCount ?? null,
|
|
82
|
+
variableCount: vault?.variableCount ?? null,
|
|
83
|
+
sha256: vault?.sha256 ?? null,
|
|
84
|
+
sha256Short: hash,
|
|
85
|
+
manifestSha256: vault?.manifestSha256 ?? null,
|
|
86
|
+
encryptionTool: vault?.encryptionTool ?? null,
|
|
87
|
+
extension: vault?.extension ?? null,
|
|
88
|
+
formatVersion: vault?.formatVersion ?? null,
|
|
89
|
+
agentAuthIncluded: vault?.agentAuthIncluded === true,
|
|
90
|
+
sourceHost: vault?.sourceHost ?? null,
|
|
91
|
+
sourceRoot: vault?.sourceRoot ?? null,
|
|
92
|
+
},
|
|
93
|
+
pullCommand,
|
|
94
|
+
restoreCommand,
|
|
95
|
+
secretValuesExposed: false,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
if (state === "scope-missing") {
|
|
99
|
+
return {
|
|
100
|
+
state,
|
|
101
|
+
flow: "account-backed-encrypted-snapshot",
|
|
102
|
+
available: false,
|
|
103
|
+
snapshotCount: 0,
|
|
104
|
+
summary: "Secret Vault unknown: current realtime key lacks vault scope",
|
|
105
|
+
pullCommand,
|
|
106
|
+
restoreCommand,
|
|
107
|
+
secretValuesExposed: false,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
if (state === "missing") {
|
|
111
|
+
return {
|
|
112
|
+
state,
|
|
113
|
+
flow: "account-backed-encrypted-snapshot",
|
|
114
|
+
available: false,
|
|
115
|
+
snapshotCount: vault?.snapshotCount ?? 0,
|
|
116
|
+
summary: "Secret Vault missing: upload encrypted snapshot from the source Mac with `youmd env vault push`",
|
|
117
|
+
pullCommand,
|
|
118
|
+
restoreCommand,
|
|
119
|
+
secretValuesExposed: false,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
state,
|
|
124
|
+
flow: "account-backed-encrypted-snapshot",
|
|
125
|
+
available: false,
|
|
126
|
+
snapshotCount: 0,
|
|
127
|
+
summary: "Secret Vault not observed yet: realtime daemon has not received a vault-scoped sync head",
|
|
128
|
+
pullCommand,
|
|
129
|
+
restoreCommand,
|
|
130
|
+
secretValuesExposed: false,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
function realtimeSyncHeadSignature(head) {
|
|
134
|
+
if (!head)
|
|
135
|
+
return "none";
|
|
136
|
+
return JSON.stringify({
|
|
137
|
+
identity: {
|
|
138
|
+
latestVersion: head.identity?.latestVersion ?? null,
|
|
139
|
+
latestHash: head.identity?.latestHash ?? null,
|
|
140
|
+
publishedVersion: head.identity?.publishedVersion ?? null,
|
|
141
|
+
publishedHash: head.identity?.publishedHash ?? null,
|
|
142
|
+
},
|
|
143
|
+
skills: {
|
|
144
|
+
installedCount: head.skills?.installedCount ?? 0,
|
|
145
|
+
latestInstalledAt: head.skills?.latestInstalledAt ?? null,
|
|
146
|
+
names: head.skills?.names ?? [],
|
|
147
|
+
},
|
|
148
|
+
portfolio: head.portfolio ?? null,
|
|
149
|
+
repoMirror: head.repoMirror ?? null,
|
|
150
|
+
github: head.github ?? null,
|
|
151
|
+
encryptedEnvVault: {
|
|
152
|
+
status: head.encryptedEnvVault?.status ?? null,
|
|
153
|
+
available: head.encryptedEnvVault?.available ?? false,
|
|
154
|
+
snapshotCount: head.encryptedEnvVault?.snapshotCount ?? 0,
|
|
155
|
+
id: head.encryptedEnvVault?.id ?? null,
|
|
156
|
+
createdAt: head.encryptedEnvVault?.createdAt ?? null,
|
|
157
|
+
fileName: head.encryptedEnvVault?.fileName ?? null,
|
|
158
|
+
sha256: head.encryptedEnvVault?.sha256 ?? null,
|
|
159
|
+
manifestSha256: head.encryptedEnvVault?.manifestSha256 ?? null,
|
|
160
|
+
projectCount: head.encryptedEnvVault?.projectCount ?? null,
|
|
161
|
+
variableCount: head.encryptedEnvVault?.variableCount ?? null,
|
|
162
|
+
sourceHost: head.encryptedEnvVault?.sourceHost ?? null,
|
|
163
|
+
sourceRoot: head.encryptedEnvVault?.sourceRoot ?? null,
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
function summarizeRealtimeSyncHead(head) {
|
|
168
|
+
const bundle = head.identity?.latestVersion
|
|
169
|
+
? `bundle v${head.identity.latestVersion}`
|
|
170
|
+
: "bundle unknown";
|
|
171
|
+
const skills = `${head.skills?.installedCount ?? 0} skills`;
|
|
172
|
+
const projects = `${head.portfolio?.projects ?? 0} projects`;
|
|
173
|
+
const tasks = `${head.portfolio?.tasks ?? 0} tasks`;
|
|
174
|
+
const vault = describeRealtimeSecretVault(head).summary;
|
|
175
|
+
return `${bundle}, ${skills}, ${projects}, ${tasks}, ${vault}`;
|
|
176
|
+
}
|
|
177
|
+
function buildRealtimeSyncStatusFile(head) {
|
|
178
|
+
return {
|
|
179
|
+
schemaVersion: "you-md/realtime-sync-daemon-status/v1",
|
|
180
|
+
generatedAt: Date.now(),
|
|
181
|
+
summary: summarizeRealtimeSyncHead(head),
|
|
182
|
+
user: head.user,
|
|
183
|
+
identity: head.identity,
|
|
184
|
+
skills: {
|
|
185
|
+
installedCount: head.skills?.installedCount,
|
|
186
|
+
latestInstalledAt: head.skills?.latestInstalledAt ?? null,
|
|
187
|
+
},
|
|
188
|
+
portfolio: head.portfolio,
|
|
189
|
+
repoMirror: head.repoMirror,
|
|
190
|
+
github: head.github,
|
|
191
|
+
secretVault: describeRealtimeSecretVault(head),
|
|
192
|
+
secretValuesExposed: false,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
function writeRealtimeSyncStatusFile(head) {
|
|
196
|
+
fs.mkdirSync(path.dirname(exports.REALTIME_SYNC_STATUS_PATH), { recursive: true, mode: 0o700 });
|
|
197
|
+
fs.writeFileSync(exports.REALTIME_SYNC_STATUS_PATH, JSON.stringify(buildRealtimeSyncStatusFile(head), null, 2), { mode: 0o600 });
|
|
198
|
+
}
|
|
199
|
+
function readRealtimeSyncStatusFile() {
|
|
200
|
+
try {
|
|
201
|
+
const parsed = JSON.parse(fs.readFileSync(exports.REALTIME_SYNC_STATUS_PATH, "utf-8"));
|
|
202
|
+
if (!parsed || typeof parsed !== "object")
|
|
203
|
+
return null;
|
|
204
|
+
if (parsed.secretValuesExposed !== false)
|
|
205
|
+
return null;
|
|
206
|
+
return parsed;
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
return null;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
function shouldRunBoundedSync(lastRunAt, now, minIntervalMs) {
|
|
213
|
+
return lastRunAt === 0 || now - lastRunAt >= minIntervalMs;
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=realtime-sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"realtime-sync.js","sourceRoot":"","sources":["../../src/lib/realtime-sync.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "youmd",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.5",
|
|
4
4
|
"description": "Identity context protocol for the agent internet — an MCP where the context is you. CLI for the You.md platform.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"you": "dist/you.js",
|
|
@@ -45,6 +45,7 @@
|
|
|
45
45
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
46
46
|
"chalk": "^4.1.2",
|
|
47
47
|
"commander": "^12.1.0",
|
|
48
|
+
"convex": "1.33.1",
|
|
48
49
|
"gray-matter": "^4.0.3",
|
|
49
50
|
"jimp": "^0.22.12",
|
|
50
51
|
"js-yaml": "^4.1.1",
|
|
@@ -58,6 +58,10 @@ Do NOT transfer via unencrypted email or public Slack.
|
|
|
58
58
|
youmd env restore /path/to/env-vault-<date>.tar.<ext> --list
|
|
59
59
|
youmd env restore /path/to/env-vault-<date>.tar.<ext>
|
|
60
60
|
|
|
61
|
+
# Fresh-machine restore after repos have been cloned into CODE_YOU:
|
|
62
|
+
youmd env restore /path/to/env-vault-<date>.tar.<ext> --root ~/Desktop/CODE_YOU --list --map-existing --existing-only --skip-agent-auth
|
|
63
|
+
youmd env restore /path/to/env-vault-<date>.tar.<ext> --root ~/Desktop/CODE_YOU --map-existing --existing-only --skip-agent-auth
|
|
64
|
+
|
|
61
65
|
# If files already exist on the new Mac:
|
|
62
66
|
youmd env restore --force /path/to/env-vault-<date>.tar.<ext>
|
|
63
67
|
|
|
@@ -70,6 +74,9 @@ The script:
|
|
|
70
74
|
1. Lists vault contents without writing files when `--list` is provided.
|
|
71
75
|
2. Creates `<CODE_2025>/<project>/.env.local` for each project during restore.
|
|
72
76
|
3. Restores agent-auth files to their absolute home paths (`~/.codex/auth.json`, `~/.cursor/mcp.json`, `~/.claude.json`), creating parent directories as needed.
|
|
77
|
+
4. With `--map-existing`, maps archived project folder names onto existing target-root dirs by normalized name, e.g. `foldermd` -> `folder-md`.
|
|
78
|
+
5. With `--existing-only`, skips archived projects that do not already have a mapped target dir. This prevents fresh-machine restores from creating stale duplicate folders.
|
|
79
|
+
6. With `--skip-agent-auth`, restores only project `.env.local` files and leaves the new machine's active Claude/Codex/Cursor auth files untouched.
|
|
73
80
|
|
|
74
81
|
Existing files are backed up to `<path>.bak.<timestamp>` before overwrite (or silently overwritten with `--force`).
|
|
75
82
|
List mode prints project env target paths, variable names/counts, and agent-auth file presence only. It never prints secret values.
|
|
@@ -115,6 +122,8 @@ youmd env restore <vault> # restore from an encrypted vault
|
|
|
115
122
|
youmd env restore <vault> --list # list vault contents without writing
|
|
116
123
|
youmd env restore --force # overwrite existing .env.local files
|
|
117
124
|
youmd env restore --root <dir> # restore into a custom root
|
|
125
|
+
youmd env restore <vault> --root ~/Desktop/CODE_YOU --map-existing --existing-only --skip-agent-auth
|
|
126
|
+
# safe fresh-machine restore into cloned project dirs
|
|
118
127
|
```
|
|
119
128
|
|
|
120
129
|
The CLI wrapper delegates directly to these bash scripts via `spawnSync` with
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
# secret VALUES. Restore prints which file paths were restored or skipped; list
|
|
5
5
|
# mode prints target paths plus variable names/counts only.
|
|
6
6
|
#
|
|
7
|
-
# Usage: bash restore.sh [--list] [--force] [--
|
|
7
|
+
# Usage: bash restore.sh [--list] [--force] [--map-existing] [--existing-only]
|
|
8
|
+
# [--skip-agent-auth] [--root <target-root>] <vault-file>
|
|
8
9
|
# vault-file: path to env-vault-*.tar.age / .tar.gpg / .tar.enc
|
|
9
10
|
# --force: overwrite existing files without backing them up
|
|
10
11
|
# --root: destination root for .env.local files
|
|
@@ -31,15 +32,21 @@ AGENT_AUTH_MAP=(
|
|
|
31
32
|
TARGET_ROOT="${ENV_VAULT_RESTORE_ROOT:-/Users/houstongolden/Desktop/CODE_2025}"
|
|
32
33
|
FORCE=false
|
|
33
34
|
LIST_ONLY=false
|
|
35
|
+
MAP_EXISTING=false
|
|
36
|
+
EXISTING_ONLY=false
|
|
37
|
+
SKIP_AGENT_AUTH=false
|
|
34
38
|
VAULT_FILE=""
|
|
35
39
|
|
|
36
40
|
# ── parse args ─────────────────────────────────────────────────────────────────
|
|
37
41
|
while [[ $# -gt 0 ]]; do
|
|
38
42
|
case $1 in
|
|
39
|
-
--list)
|
|
40
|
-
--force)
|
|
41
|
-
--
|
|
42
|
-
|
|
43
|
+
--list) LIST_ONLY=true; shift ;;
|
|
44
|
+
--force) FORCE=true; shift ;;
|
|
45
|
+
--map-existing) MAP_EXISTING=true; shift ;;
|
|
46
|
+
--existing-only) EXISTING_ONLY=true; shift ;;
|
|
47
|
+
--skip-agent-auth) SKIP_AGENT_AUTH=true; shift ;;
|
|
48
|
+
--root) TARGET_ROOT="$2"; shift 2 ;;
|
|
49
|
+
-*) echo "Unknown flag: $1" >&2; exit 1 ;;
|
|
43
50
|
*)
|
|
44
51
|
if [[ -z "${VAULT_FILE}" ]]; then
|
|
45
52
|
VAULT_FILE="$1"
|
|
@@ -52,7 +59,7 @@ while [[ $# -gt 0 ]]; do
|
|
|
52
59
|
done
|
|
53
60
|
|
|
54
61
|
if [[ -z "${VAULT_FILE}" ]]; then
|
|
55
|
-
echo "Usage: bash restore.sh [--list] [--force] [--root <path>] <vault-file>" >&2
|
|
62
|
+
echo "Usage: bash restore.sh [--list] [--force] [--map-existing] [--existing-only] [--skip-agent-auth] [--root <path>] <vault-file>" >&2
|
|
56
63
|
echo " vault-file: env-vault-*.tar.age | .tar.gpg | .tar.enc" >&2
|
|
57
64
|
exit 1
|
|
58
65
|
fi
|
|
@@ -80,8 +87,53 @@ fi
|
|
|
80
87
|
echo "Encryption tool: ${ENC_TOOL}"
|
|
81
88
|
echo "Vault file: ${VAULT_FILE}"
|
|
82
89
|
echo "Target root: ${TARGET_ROOT}"
|
|
90
|
+
echo "Project mapping: map-existing=${MAP_EXISTING} existing-only=${EXISTING_ONLY}"
|
|
91
|
+
echo "Agent auth: $([[ "${SKIP_AGENT_AUTH}" == "true" ]] && echo "skip" || echo "restore")"
|
|
83
92
|
echo ""
|
|
84
93
|
|
|
94
|
+
normalize_project_name() {
|
|
95
|
+
printf '%s' "$1" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]//g'
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
map_project_name() {
|
|
99
|
+
local archive_name="$1"
|
|
100
|
+
local exact_dir="${TARGET_ROOT}/${archive_name}"
|
|
101
|
+
if [[ "${MAP_EXISTING}" != "true" ]]; then
|
|
102
|
+
printf '%s\n' "${archive_name}"
|
|
103
|
+
return 0
|
|
104
|
+
fi
|
|
105
|
+
if [[ -d "${exact_dir}" ]]; then
|
|
106
|
+
printf '%s\n' "${archive_name}"
|
|
107
|
+
return 0
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
local wanted
|
|
111
|
+
wanted="$(normalize_project_name "${archive_name}")"
|
|
112
|
+
local matches=()
|
|
113
|
+
local candidate
|
|
114
|
+
while IFS= read -r -d '' candidate; do
|
|
115
|
+
local base
|
|
116
|
+
base="$(basename "${candidate}")"
|
|
117
|
+
if [[ "$(normalize_project_name "${base}")" == "${wanted}" ]]; then
|
|
118
|
+
matches+=("${base}")
|
|
119
|
+
fi
|
|
120
|
+
done < <(find "${TARGET_ROOT}" -mindepth 1 -maxdepth 1 -type d -print0 2>/dev/null || true)
|
|
121
|
+
|
|
122
|
+
if [[ "${#matches[@]}" -eq 1 ]]; then
|
|
123
|
+
printf '%s\n' "${matches[0]}"
|
|
124
|
+
return 0
|
|
125
|
+
fi
|
|
126
|
+
if [[ "${#matches[@]}" -gt 1 ]]; then
|
|
127
|
+
echo "WARN: multiple existing dirs match vault project '${archive_name}': ${matches[*]} — skipping" >&2
|
|
128
|
+
return 1
|
|
129
|
+
fi
|
|
130
|
+
if [[ "${EXISTING_ONLY}" == "true" ]]; then
|
|
131
|
+
echo "WARN: no existing dir for vault project '${archive_name}' under ${TARGET_ROOT} — skipping" >&2
|
|
132
|
+
return 1
|
|
133
|
+
fi
|
|
134
|
+
printf '%s\n' "${archive_name}"
|
|
135
|
+
}
|
|
136
|
+
|
|
85
137
|
# ── decrypt into a temp dir ────────────────────────────────────────────────────
|
|
86
138
|
WORK_DIR="$(mktemp -d)"
|
|
87
139
|
TAR_PATH="${WORK_DIR}/vault.tar"
|
|
@@ -130,18 +182,30 @@ if [[ "${LIST_ONLY}" == "true" ]]; then
|
|
|
130
182
|
echo "Vault contents (secret-safe inventory):"
|
|
131
183
|
while IFS= read -r -d '' ENV_FILE; do
|
|
132
184
|
REL_PATH="${ENV_FILE#${EXTRACT_DIR}/}"
|
|
133
|
-
|
|
185
|
+
ARCHIVE_PROJECT_NAME="$(dirname "${REL_PATH}")"
|
|
186
|
+
if ! PROJECT_NAME="$(map_project_name "${ARCHIVE_PROJECT_NAME}")"; then
|
|
187
|
+
echo " env: ${ARCHIVE_PROJECT_NAME}/.env.local -> SKIPPED (no safe target)"
|
|
188
|
+
(( ENV_COUNT++ )) || true
|
|
189
|
+
continue
|
|
190
|
+
fi
|
|
134
191
|
DEST="${TARGET_ROOT}/${PROJECT_NAME}/.env.local"
|
|
135
192
|
VAR_COUNT=$(grep -cE '^[A-Za-z_][A-Za-z0-9_]*=' "${ENV_FILE}" 2>/dev/null || true)
|
|
136
193
|
VAR_NAMES=$(grep -oE '^[A-Za-z_][A-Za-z0-9_]*' "${ENV_FILE}" 2>/dev/null \
|
|
137
194
|
| grep -v '^$' | sort | paste -sd ',' - || true)
|
|
138
|
-
|
|
195
|
+
if [[ "${ARCHIVE_PROJECT_NAME}" == "${PROJECT_NAME}" ]]; then
|
|
196
|
+
echo " env: ${PROJECT_NAME}/.env.local -> ${DEST} (${VAR_COUNT} variable(s) [${VAR_NAMES}])"
|
|
197
|
+
else
|
|
198
|
+
echo " env: ${ARCHIVE_PROJECT_NAME}/.env.local -> ${DEST} (${VAR_COUNT} variable(s) [${VAR_NAMES}])"
|
|
199
|
+
fi
|
|
139
200
|
(( ENV_COUNT++ )) || true
|
|
140
201
|
done < <(find "${EXTRACT_DIR}" -name ".env.local" -print0)
|
|
141
202
|
|
|
142
203
|
AGENT_AUTH_SRC="${EXTRACT_DIR}/agent-auth"
|
|
143
204
|
echo " agent-auth:"
|
|
144
|
-
|
|
205
|
+
if [[ "${SKIP_AGENT_AUTH}" == "true" ]]; then
|
|
206
|
+
echo " skipped by --skip-agent-auth"
|
|
207
|
+
else
|
|
208
|
+
for ENTRY in "${AGENT_AUTH_MAP[@]}"; do
|
|
145
209
|
ARCHIVE_NAME="${ENTRY%%:*}"
|
|
146
210
|
DEST_PATH="${ENTRY##*:}"
|
|
147
211
|
SRC_FILE="${AGENT_AUTH_SRC}/${ARCHIVE_NAME}"
|
|
@@ -153,7 +217,8 @@ if [[ "${LIST_ONLY}" == "true" ]]; then
|
|
|
153
217
|
echo " missing: agent-auth/${ARCHIVE_NAME}"
|
|
154
218
|
(( AGENT_MISSING++ )) || true
|
|
155
219
|
fi
|
|
156
|
-
|
|
220
|
+
done
|
|
221
|
+
fi
|
|
157
222
|
|
|
158
223
|
echo ""
|
|
159
224
|
echo "List summary: ${ENV_COUNT} .env.local file(s), ${AGENT_PRESENT} agent-auth file(s) present, ${AGENT_MISSING} agent-auth file(s) missing."
|
|
@@ -169,7 +234,12 @@ BACKED_UP=0
|
|
|
169
234
|
while IFS= read -r -d '' ENV_FILE; do
|
|
170
235
|
# ENV_FILE is relative to EXTRACT_DIR, e.g. ./project-name/.env.local
|
|
171
236
|
REL_PATH="${ENV_FILE#${EXTRACT_DIR}/}" # project-name/.env.local
|
|
172
|
-
|
|
237
|
+
ARCHIVE_PROJECT_NAME="$(dirname "${REL_PATH}")" # project-name
|
|
238
|
+
if ! PROJECT_NAME="$(map_project_name "${ARCHIVE_PROJECT_NAME}")"; then
|
|
239
|
+
echo " SKIPPED (no existing mapped target): ${ARCHIVE_PROJECT_NAME}/.env.local"
|
|
240
|
+
(( SKIPPED++ )) || true
|
|
241
|
+
continue
|
|
242
|
+
fi
|
|
173
243
|
DEST="${TARGET_ROOT}/${PROJECT_NAME}/.env.local"
|
|
174
244
|
DEST_DIR="$(dirname "${DEST}")"
|
|
175
245
|
|
|
@@ -204,7 +274,10 @@ AGENT_BACKED_UP=0
|
|
|
204
274
|
|
|
205
275
|
AGENT_AUTH_SRC="${EXTRACT_DIR}/agent-auth"
|
|
206
276
|
|
|
207
|
-
if [[
|
|
277
|
+
if [[ "${SKIP_AGENT_AUTH}" == "true" ]]; then
|
|
278
|
+
echo "Skipping agent-auth restore because --skip-agent-auth was provided."
|
|
279
|
+
echo ""
|
|
280
|
+
elif [[ -d "${AGENT_AUTH_SRC}" ]]; then
|
|
208
281
|
echo "Restoring agent-auth files…"
|
|
209
282
|
for ENTRY in "${AGENT_AUTH_MAP[@]}"; do
|
|
210
283
|
ARCHIVE_NAME="${ENTRY%%:*}"
|
|
@@ -28,7 +28,8 @@ Cross-machine sync toolkit for Houston Golden's agent skill/stack setup.
|
|
|
28
28
|
|
|
29
29
|
### Complementary sync planes
|
|
30
30
|
|
|
31
|
-
- **
|
|
31
|
+
- **Realtime identity/project plane:** `youmd sync --live --daemon` subscribes to Convex websocket updates, mints only a short-lived sync session token, materializes identity files and installed You.md skills locally, and triggers bounded shared stack/project-context syncs. It never prints or returns raw `.env.local` values.
|
|
32
|
+
- **Identity repair plane:** `youmd sync --daemon` (Convex ↔ local profile, memories, preferences). Automated via `com.youmd.identity-sync` daemon as a timer-based fallback. Daemon mode refreshes local files/skills and skips unsafe lossy pushes instead of forcing over richer server data.
|
|
32
33
|
- **Project-context plane:** `youmd stack context-sync` safely commits and syncs only `AGENTS.md`, `CLAUDE.md`, `project-context/`, and `.claude/` in curated Houston-owned repos. It refuses to merge remote app-code changes.
|
|
33
34
|
- **Env-vault plane:** `cli/scripts/env-vault/restore.sh` for secrets (manual, invoked on new machine); also available as `youmd env restore <vault>`.
|
|
34
35
|
|
|
@@ -41,6 +42,7 @@ cli/scripts/skillstack-sync/
|
|
|
41
42
|
├── sync.sh Core syncer (bash 3.2 compatible)
|
|
42
43
|
├── install-daemons.sh Installs all resident LaunchAgents
|
|
43
44
|
├── bootstrap-new-mac.sh New machine setup script
|
|
45
|
+
├── com.youmd.realtime-sync.plist LaunchAgent: runs `youmd sync --live --daemon` as a resident websocket syncer
|
|
44
46
|
├── com.youmd.skillstack-sync.plist LaunchAgent: runs `youmd stack sync` every 5 min
|
|
45
47
|
├── com.youmd.identity-sync.plist LaunchAgent: runs `youmd sync --daemon` every 5 min
|
|
46
48
|
├── com.youmd.context-sync.plist LaunchAgent: runs `youmd stack context-sync` every 15 min
|
|
@@ -103,7 +105,8 @@ Or run the raw script directly:
|
|
|
103
105
|
bash cli/scripts/skillstack-sync/install-daemons.sh
|
|
104
106
|
```
|
|
105
107
|
|
|
106
|
-
Installs
|
|
108
|
+
Installs four LaunchAgents:
|
|
109
|
+
- `com.youmd.realtime-sync` → runs `youmd sync --live --daemon`
|
|
107
110
|
- `com.youmd.skillstack-sync` → runs `youmd stack sync`
|
|
108
111
|
- `com.youmd.identity-sync` → runs `youmd sync --daemon`
|
|
109
112
|
- `com.youmd.context-sync` → runs `youmd stack context-sync`
|
|
@@ -113,6 +116,7 @@ Check status:
|
|
|
113
116
|
youmd stack daemon status
|
|
114
117
|
# or directly:
|
|
115
118
|
launchctl list com.youmd.skillstack-sync
|
|
119
|
+
launchctl list com.youmd.realtime-sync
|
|
116
120
|
launchctl list com.youmd.identity-sync
|
|
117
121
|
launchctl list com.youmd.context-sync
|
|
118
122
|
```
|
|
@@ -145,19 +149,33 @@ rm ~/Library/LaunchAgents/com.youmd.context-sync.plist
|
|
|
145
149
|
|
|
146
150
|
## New Mac setup
|
|
147
151
|
|
|
152
|
+
Preferred path: open the You.md Machine tab on an authenticated source computer,
|
|
153
|
+
copy the fresh-machine Claude/Codex setup prompt, and paste it into Claude Code
|
|
154
|
+
or Codex on the new Mac. That generated prompt checks/install Homebrew, Node 22,
|
|
155
|
+
GitHub CLI, bun, and pnpm; authenticates You.md; requires GitHub auth before
|
|
156
|
+
private clones; clones only setup-eligible active projects into
|
|
157
|
+
`~/Desktop/CODE_YOU`; restores env files with `--map-existing --existing-only
|
|
158
|
+
--skip-agent-auth`; and installs resident daemons.
|
|
159
|
+
|
|
160
|
+
Fallback manual path:
|
|
161
|
+
|
|
148
162
|
```bash
|
|
149
163
|
# 1. Install youmd CLI
|
|
150
164
|
curl -fsSL https://you.md/install.sh | bash
|
|
151
165
|
|
|
152
|
-
# 2.
|
|
166
|
+
# 2. Authenticate GitHub before private stack/project clones
|
|
167
|
+
gh auth login -h github.com -p https -s repo
|
|
168
|
+
|
|
169
|
+
# 3. Clone this repo (youmd)
|
|
153
170
|
git clone https://github.com/houstongolden/youmd ~/Desktop/CODE_2025/youmd
|
|
154
171
|
|
|
155
|
-
#
|
|
172
|
+
# 4. Run bootstrap (clones agent-shared + scistack)
|
|
156
173
|
bash ~/Desktop/CODE_2025/youmd/cli/scripts/skillstack-sync/bootstrap-new-mac.sh
|
|
157
174
|
|
|
158
|
-
#
|
|
175
|
+
# 5. Restore project env files from env-vault (manual step — see env-vault/README)
|
|
176
|
+
youmd env restore <vault> --root ~/Desktop/CODE_YOU --map-existing --existing-only --skip-agent-auth
|
|
159
177
|
|
|
160
|
-
#
|
|
178
|
+
# 6. Activate daemons
|
|
161
179
|
youmd stack daemon install
|
|
162
180
|
```
|
|
163
181
|
|