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
|
@@ -45,10 +45,18 @@ exports.DEFAULT_FRESH_MACHINE_LIMIT = 80;
|
|
|
45
45
|
function shellQuote(value) {
|
|
46
46
|
return `'${value.replace(/'/g, `'\"'\"'`)}'`;
|
|
47
47
|
}
|
|
48
|
-
function envAssignment(name, value) {
|
|
48
|
+
function envAssignment(name, value, options = {}) {
|
|
49
49
|
if (value === undefined || value === null || `${value}`.trim() === "")
|
|
50
50
|
return null;
|
|
51
|
-
|
|
51
|
+
const stringValue = String(value);
|
|
52
|
+
if (options.expandHome) {
|
|
53
|
+
if (stringValue === "~")
|
|
54
|
+
return `${name}="$HOME"`;
|
|
55
|
+
if (stringValue.startsWith("~/")) {
|
|
56
|
+
return `${name}="$HOME${stringValue.slice(1).replace(/["\\$`]/g, (char) => `\\${char}`)}"`;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return `${name}=${shellQuote(stringValue)}`;
|
|
52
60
|
}
|
|
53
61
|
function portableHomePath(value) {
|
|
54
62
|
if (!value)
|
|
@@ -64,193 +72,300 @@ function portableHomePath(value) {
|
|
|
64
72
|
return value;
|
|
65
73
|
}
|
|
66
74
|
function buildFreshMachineBootstrapScript() {
|
|
67
|
-
return
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
75
|
+
return `set -euo pipefail
|
|
76
|
+
export PATH="$HOME/.youmd/bin:$HOME/.youmd/npm-global/bin:/opt/homebrew/opt/node@22/bin:/usr/local/opt/node@22/bin:/opt/homebrew/bin:/usr/local/bin:$PATH"
|
|
77
|
+
ROOT="\${YOUMD_CODE_ROOT:-$HOME/Desktop/CODE_YOU}"
|
|
78
|
+
DAYS="\${YOUMD_ACTIVE_DAYS:-30}"
|
|
79
|
+
EXPAND_DAYS="\${YOUMD_EXPAND_ACTIVE_DAYS:-90}"
|
|
80
|
+
LIMIT="\${YOUMD_PROJECT_LIMIT:-80}"
|
|
81
|
+
HYDRATE_TIMEOUT="\${YOUMD_PORTFOLIO_HYDRATE_TIMEOUT_SECONDS:-180}"
|
|
82
|
+
mkdir -p "$ROOT"
|
|
83
|
+
|
|
84
|
+
command_exists() { command -v "$1" >/dev/null 2>&1; }
|
|
85
|
+
node_major() { node -e 'console.log(process.versions.node.split(".")[0])' 2>/dev/null || echo 0; }
|
|
86
|
+
run_with_timeout() {
|
|
87
|
+
seconds="$1"
|
|
88
|
+
shift
|
|
89
|
+
if command_exists gtimeout; then
|
|
90
|
+
gtimeout "$seconds" "$@"
|
|
91
|
+
elif command_exists timeout; then
|
|
92
|
+
timeout "$seconds" "$@"
|
|
93
|
+
else
|
|
94
|
+
"$@" &
|
|
95
|
+
pid=$!
|
|
96
|
+
( sleep "$seconds"; if kill -0 "$pid" >/dev/null 2>&1; then echo "[you.md] timeout after \${seconds}s: $*" >&2; kill "$pid" >/dev/null 2>&1 || true; fi ) &
|
|
97
|
+
watcher=$!
|
|
98
|
+
wait "$pid"
|
|
99
|
+
status=$?
|
|
100
|
+
kill "$watcher" >/dev/null 2>&1 || true
|
|
101
|
+
wait "$watcher" 2>/dev/null || true
|
|
102
|
+
return "$status"
|
|
103
|
+
fi
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
bootstrap_prereqs() {
|
|
107
|
+
echo "[you.md] checking local prerequisites: Homebrew, Node 22/npm, git, gh, bun, pnpm"
|
|
108
|
+
if [ "$(uname -s 2>/dev/null || echo unknown)" = "Darwin" ] && ! command_exists brew; then
|
|
109
|
+
echo "[you.md] Homebrew missing; installing it first so the rest of setup can stay boring"
|
|
110
|
+
NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" || true
|
|
111
|
+
fi
|
|
112
|
+
if [ -x /opt/homebrew/bin/brew ]; then eval "$(/opt/homebrew/bin/brew shellenv)" || true; fi
|
|
113
|
+
if [ -x /usr/local/bin/brew ]; then eval "$(/usr/local/bin/brew shellenv)" || true; fi
|
|
114
|
+
export PATH="$HOME/.youmd/bin:$HOME/.youmd/npm-global/bin:/opt/homebrew/opt/node@22/bin:/usr/local/opt/node@22/bin:/opt/homebrew/bin:/usr/local/bin:$PATH"
|
|
115
|
+
|
|
116
|
+
if command_exists brew; then
|
|
117
|
+
MAJOR="$(node_major)"
|
|
118
|
+
if ! command_exists node || [ "$MAJOR" -lt 20 ] || [ "$MAJOR" -ge 23 ]; then
|
|
119
|
+
echo "[you.md] installing Node 22 for modern Next/Convex projects"
|
|
120
|
+
brew install node@22 || brew install node || true
|
|
121
|
+
brew link --overwrite --force node@22 || true
|
|
122
|
+
fi
|
|
123
|
+
command_exists git || brew install git || true
|
|
124
|
+
command_exists gh || brew install gh || true
|
|
125
|
+
command_exists bun || brew install bun || brew install oven-sh/bun/bun || true
|
|
126
|
+
fi
|
|
127
|
+
|
|
128
|
+
export PATH="$HOME/.youmd/bin:$HOME/.youmd/npm-global/bin:/opt/homebrew/opt/node@22/bin:/usr/local/opt/node@22/bin:/opt/homebrew/bin:/usr/local/bin:$PATH"
|
|
129
|
+
command_exists corepack && corepack enable || true
|
|
130
|
+
if command_exists corepack && ! command_exists pnpm; then
|
|
131
|
+
corepack prepare pnpm@latest --activate || true
|
|
132
|
+
fi
|
|
133
|
+
|
|
134
|
+
for required in node npm git; do
|
|
135
|
+
if ! command_exists "$required"; then
|
|
136
|
+
echo "[you.md] required tool missing after bootstrap: $required" >&2
|
|
137
|
+
exit 1
|
|
138
|
+
fi
|
|
139
|
+
done
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
ensure_github_auth() {
|
|
143
|
+
if ! command_exists gh; then
|
|
144
|
+
echo "[you.md] GitHub CLI is missing, so private repo clone/setup cannot continue yet." >&2
|
|
145
|
+
return 1
|
|
146
|
+
fi
|
|
147
|
+
if gh auth status >/dev/null 2>&1; then
|
|
148
|
+
echo "[you.md] GitHub auth is ready"
|
|
149
|
+
return 0
|
|
150
|
+
fi
|
|
151
|
+
echo "[you.md] GitHub auth is required before private skill/project repos can clone."
|
|
152
|
+
if [ -t 0 ]; then
|
|
153
|
+
gh auth login -h github.com -p https -s repo || true
|
|
154
|
+
fi
|
|
155
|
+
if gh auth status >/dev/null 2>&1; then
|
|
156
|
+
echo "[you.md] GitHub auth is ready"
|
|
157
|
+
return 0
|
|
158
|
+
fi
|
|
159
|
+
echo "[you.md] GitHub auth still is not complete."
|
|
160
|
+
echo "[you.md] Open a normal Terminal on this Mac and run:"
|
|
161
|
+
echo " $(command -v gh || echo gh) auth login -h github.com -p https -s repo"
|
|
162
|
+
echo "[you.md] Then rerun this same setup prompt/command."
|
|
163
|
+
return 1
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
bootstrap_prereqs
|
|
167
|
+
|
|
168
|
+
echo "[you.md] installing runtime"
|
|
169
|
+
curl -fsSL https://you.md/install.sh | bash
|
|
170
|
+
export PATH="$HOME/.youmd/bin:$HOME/.youmd/npm-global/bin:/opt/homebrew/opt/node@22/bin:/usr/local/opt/node@22/bin:/opt/homebrew/bin:/usr/local/bin:$PATH"
|
|
171
|
+
if ! command_exists youmd; then
|
|
172
|
+
echo "[you.md] youmd was installed but is not on PATH. Try a new Terminal, then rerun this command." >&2
|
|
173
|
+
exit 1
|
|
174
|
+
fi
|
|
175
|
+
|
|
176
|
+
if [ -n "\${YOUMD_API_KEY:-}" ]; then
|
|
177
|
+
echo "[you.md] logging in with bootstrap key"
|
|
178
|
+
youmd login --key "$YOUMD_API_KEY"
|
|
179
|
+
else
|
|
180
|
+
echo "[you.md] no YOUMD_API_KEY set; starting interactive login"
|
|
181
|
+
youmd login
|
|
182
|
+
fi
|
|
183
|
+
|
|
184
|
+
echo "[you.md] pulling identity bundle and syncing local brain"
|
|
185
|
+
youmd pull
|
|
186
|
+
youmd sync
|
|
187
|
+
|
|
188
|
+
echo "[you.md] installing resident realtime/identity/skillstack/project-context daemons early"
|
|
189
|
+
youmd stack daemon install || true
|
|
190
|
+
youmd stack daemon status || true
|
|
191
|
+
|
|
192
|
+
GITHUB_READY=0
|
|
193
|
+
if ensure_github_auth; then
|
|
194
|
+
GITHUB_READY=1
|
|
195
|
+
elif [ "\${YOUMD_REQUIRE_GITHUB_AUTH:-1}" = "1" ]; then
|
|
196
|
+
echo "[you.md] stopping after You.md identity/daemon setup because GitHub auth is required for private repos." >&2
|
|
197
|
+
exit 2
|
|
198
|
+
fi
|
|
199
|
+
|
|
200
|
+
echo "[you.md] restoring shared skills, stacks, and agent host config"
|
|
201
|
+
youmd machine setup || echo "[you.md] machine setup reported a warning; continuing to skills/MCP so the next run can self-heal"
|
|
202
|
+
youmd skill install all || true
|
|
203
|
+
youmd skill sync || true
|
|
204
|
+
youmd mcp --install claude --auto || true
|
|
205
|
+
youmd mcp --install codex --auto || true
|
|
206
|
+
youmd skill link claude || true
|
|
207
|
+
youmd skill link codex || true
|
|
208
|
+
|
|
209
|
+
if [ "$GITHUB_READY" != "1" ]; then
|
|
210
|
+
echo "[you.md] GitHub auth is still missing; project clone pass skipped. Rerun after gh auth login."
|
|
211
|
+
exit 2
|
|
212
|
+
fi
|
|
213
|
+
|
|
214
|
+
RECENT_ONLY_ARGS=()
|
|
215
|
+
if youmd machine --help 2>/dev/null | grep -q -- "--recent-only"; then
|
|
216
|
+
RECENT_ONLY_ARGS=(--recent-only)
|
|
217
|
+
else
|
|
218
|
+
echo "[you.md] installed CLI does not expose --recent-only yet; using noninteractive no-to-older-projects fallback"
|
|
219
|
+
fi
|
|
220
|
+
run_machine_projects_recent_only() {
|
|
221
|
+
if [ "\${#RECENT_ONLY_ARGS[@]}" -gt 0 ]; then
|
|
222
|
+
youmd machine projects "$@"
|
|
223
|
+
else
|
|
224
|
+
youmd machine projects "$@" </dev/null
|
|
225
|
+
fi
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
echo "[you.md] hydrating portfolio graph from You.md/GitHub before the 30-day local clone pass"
|
|
229
|
+
run_with_timeout "$HYDRATE_TIMEOUT" youmd project portfolio-hydrate --root "$ROOT" --days "$DAYS" --limit "$LIMIT" || true
|
|
230
|
+
PROJECT_ARGS=(--root "$ROOT" --days "$DAYS" "\${RECENT_ONLY_ARGS[@]}")
|
|
231
|
+
if [ -n "\${YOUMD_MAX_CLONE_PROJECTS:-}" ]; then
|
|
232
|
+
PROJECT_ARGS+=(--max-clone-projects "$YOUMD_MAX_CLONE_PROJECTS")
|
|
233
|
+
fi
|
|
234
|
+
echo "[you.md] previewing graph-backed 30-day project setup plan (ACTIVE + Top Priority/Focusing only)"
|
|
235
|
+
run_machine_projects_recent_only "\${PROJECT_ARGS[@]}" --dry-run || true
|
|
236
|
+
echo "[you.md] creating code workspace and cloning ACTIVE + Top Priority/Focusing 30-day project repos"
|
|
237
|
+
run_machine_projects_recent_only "\${PROJECT_ARGS[@]}"
|
|
238
|
+
|
|
239
|
+
echo "[you.md] checking encrypted env-vault tooling without printing secrets"
|
|
240
|
+
youmd env backup --root "$ROOT" --preflight || true
|
|
241
|
+
if [ -z "\${YOUMD_ENV_VAULT:-}" ] && [ "\${YOUMD_SECRET_VAULT_PULL:-1}" = "1" ]; then
|
|
242
|
+
SECRET_VAULT_DIR="\${YOUMD_SECRET_VAULT_DIR:-$HOME/.youmd/secret-vault}"
|
|
243
|
+
echo "[you.md] checking You.md Secret Vault for the latest encrypted env vault"
|
|
244
|
+
if SECRET_VAULT_PATH="$(youmd env vault pull --out "$SECRET_VAULT_DIR" --print-path 2>/dev/null)"; then
|
|
245
|
+
if [ -n "$SECRET_VAULT_PATH" ] && [ -f "$SECRET_VAULT_PATH" ]; then
|
|
246
|
+
export YOUMD_ENV_VAULT="$SECRET_VAULT_PATH"
|
|
247
|
+
echo "[you.md] using You.md Secret Vault snapshot: $YOUMD_ENV_VAULT"
|
|
248
|
+
fi
|
|
249
|
+
else
|
|
250
|
+
echo "[you.md] account-backed Secret Vault not available yet; falling back to local/iCloud vault discovery"
|
|
251
|
+
fi
|
|
252
|
+
fi
|
|
253
|
+
if [ -z "\${YOUMD_ENV_VAULT:-}" ]; then
|
|
254
|
+
for DEFAULT_ENV_VAULT_DIR in "$HOME/Desktop/youmd-env-vault" "$HOME/Library/Mobile Documents/com~apple~CloudDocs/Desktop/youmd-env-vault" "$HOME/Library/Mobile Documents/com~apple~CloudDocs/youmd-env-vault"; do
|
|
255
|
+
if [ -d "$DEFAULT_ENV_VAULT_DIR" ]; then
|
|
256
|
+
DETECTED_ENV_VAULT="$(find "$DEFAULT_ENV_VAULT_DIR" -maxdepth 1 -type f \\( -name "env-vault-*.tar.enc" -o -name "env-vault-*.tar.age" -o -name "env-vault-*.tar.gpg" \\) -print 2>/dev/null | sort | tail -n 1 || true)"
|
|
257
|
+
if [ -n "$DETECTED_ENV_VAULT" ]; then
|
|
258
|
+
export YOUMD_ENV_VAULT="$DETECTED_ENV_VAULT"
|
|
259
|
+
echo "[you.md] using detected env vault: $YOUMD_ENV_VAULT"
|
|
260
|
+
break
|
|
261
|
+
fi
|
|
262
|
+
fi
|
|
263
|
+
done
|
|
264
|
+
fi
|
|
265
|
+
if [ -n "\${YOUMD_ENV_VAULT:-}" ]; then
|
|
266
|
+
if [ ! -f "$YOUMD_ENV_VAULT" ]; then
|
|
267
|
+
echo "[you.md] env vault path does not exist: $YOUMD_ENV_VAULT" >&2
|
|
268
|
+
exit 1
|
|
269
|
+
fi
|
|
270
|
+
if [ -z "\${ENV_VAULT_PASS:-}" ] && command_exists security; then
|
|
271
|
+
KEYCHAIN_SERVICE="\${YOUMD_ENV_VAULT_KEYCHAIN_SERVICE:-youmd-env-vault}"
|
|
272
|
+
if ENV_VAULT_PASS_FROM_KEYCHAIN="$(security find-generic-password -a "\${USER:-\${LOGNAME:-houston}}" -s "$KEYCHAIN_SERVICE" -w 2>/dev/null)"; then
|
|
273
|
+
export ENV_VAULT_PASS="$ENV_VAULT_PASS_FROM_KEYCHAIN"
|
|
274
|
+
unset ENV_VAULT_PASS_FROM_KEYCHAIN
|
|
275
|
+
echo "[you.md] loaded env-vault passphrase from macOS Keychain service: $KEYCHAIN_SERVICE"
|
|
276
|
+
else
|
|
277
|
+
echo "[you.md] no env-vault Keychain item found; restore will prompt for the passphrase"
|
|
278
|
+
fi
|
|
279
|
+
fi
|
|
280
|
+
echo "[you.md] listing encrypted .env.local vault before restore"
|
|
281
|
+
youmd env restore "$YOUMD_ENV_VAULT" --root "$ROOT" --list --map-existing --existing-only --skip-agent-auth
|
|
282
|
+
echo "[you.md] restoring encrypted .env.local vault into existing cloned project dirs"
|
|
283
|
+
youmd env restore "$YOUMD_ENV_VAULT" --root "$ROOT" --map-existing --existing-only --skip-agent-auth
|
|
284
|
+
else
|
|
285
|
+
echo "[you.md] env vault not restored yet"
|
|
286
|
+
echo "[you.md] On the old/source Mac, create the encrypted vault first:"
|
|
287
|
+
echo "youmd env vault push --root ~/Desktop/CODE_2025 --out ~/Desktop/youmd-env-vault"
|
|
288
|
+
echo "[you.md] Or create a transferable local copy without account sync:"
|
|
289
|
+
echo "youmd env backup --root ~/Desktop/CODE_2025 --out ~/Desktop/youmd-env-vault"
|
|
290
|
+
echo "[you.md] The setup command also auto-detects vaults in local Desktop and iCloud Desktop: ~/Library/Mobile Documents/com~apple~CloudDocs/Desktop/youmd-env-vault"
|
|
291
|
+
echo "[you.md] Move the generated env-vault-*.tar.enc file to this Mac, then rerun this command with:"
|
|
292
|
+
echo "YOUMD_ENV_VAULT=/path/to/env-vault-YYYYMMDDTHHMMZ.tar.enc YOUMD_REQUIRE_ENV_VAULT=1 <same command>"
|
|
293
|
+
echo "[you.md] Or restore manually after clone:"
|
|
294
|
+
echo "youmd env restore <vault> --root \\"$ROOT\\" --map-existing --existing-only --skip-agent-auth"
|
|
295
|
+
if [ "\${YOUMD_REQUIRE_ENV_VAULT:-}" = "1" ]; then
|
|
296
|
+
echo "[you.md] strict proof requires YOUMD_ENV_VAULT; stopping before readiness is marked complete" >&2
|
|
297
|
+
exit 1
|
|
298
|
+
fi
|
|
299
|
+
fi
|
|
300
|
+
echo "[you.md] rehydrating portfolio graph with local README/project-context/env-key evidence"
|
|
301
|
+
run_with_timeout "$HYDRATE_TIMEOUT" youmd project portfolio-hydrate --root "$ROOT" --days "$DAYS" --limit "$LIMIT" || true
|
|
302
|
+
echo "[you.md] auditing cloned project readiness"
|
|
303
|
+
youmd machine verify --root "$ROOT" --max-projects "$LIMIT" --write-report --sync-report || true
|
|
304
|
+
FULL_PROJECT_SET_COMPLETE=0
|
|
305
|
+
EXPAND_TO_90="\${YOUMD_EXPAND_TO_90_DAYS:-}"
|
|
306
|
+
if [ -z "$EXPAND_TO_90" ] && [ "\${YOUMD_SKIP_90_DAY_EXPANSION_PROMPT:-}" != "1" ] && [ -t 0 ]; then
|
|
307
|
+
printf "\\n[you.md] expand to all active projects from the last \${EXPAND_DAYS} days before calling setup complete? [y/N] "
|
|
308
|
+
read -r EXPAND_TO_90
|
|
309
|
+
fi
|
|
310
|
+
case "$EXPAND_TO_90" in
|
|
311
|
+
y|Y|yes|YES|1|true|TRUE)
|
|
312
|
+
echo "[you.md] expanding workspace to active \${EXPAND_DAYS}-day project set"
|
|
313
|
+
run_with_timeout "$HYDRATE_TIMEOUT" youmd project portfolio-hydrate --root "$ROOT" --days "$EXPAND_DAYS" --limit "$LIMIT" || true
|
|
314
|
+
EXPAND_PROJECT_ARGS=(--root "$ROOT" --days "$EXPAND_DAYS" "\${RECENT_ONLY_ARGS[@]}")
|
|
315
|
+
if [ -n "\${YOUMD_MAX_CLONE_PROJECTS:-}" ]; then
|
|
316
|
+
EXPAND_PROJECT_ARGS+=(--max-clone-projects "$YOUMD_MAX_CLONE_PROJECTS")
|
|
317
|
+
fi
|
|
318
|
+
run_machine_projects_recent_only "\${EXPAND_PROJECT_ARGS[@]}" --dry-run || true
|
|
319
|
+
run_machine_projects_recent_only "\${EXPAND_PROJECT_ARGS[@]}"
|
|
320
|
+
run_with_timeout "$HYDRATE_TIMEOUT" youmd project portfolio-hydrate --root "$ROOT" --days "$EXPAND_DAYS" --limit "$LIMIT" || true
|
|
321
|
+
youmd machine verify --root "$ROOT" --max-projects "$LIMIT" --write-report --sync-report || true
|
|
322
|
+
FULL_PROJECT_SET_COMPLETE=1
|
|
323
|
+
;;
|
|
324
|
+
*)
|
|
325
|
+
echo "[you.md] stopped after the \${DAYS}-day active project setup; \${EXPAND_DAYS}-day expansion remains intentionally open."
|
|
326
|
+
;;
|
|
327
|
+
esac
|
|
328
|
+
if [ "\${YOUMD_RUN_CHECKS:-}" = "1" ]; then
|
|
329
|
+
echo "[you.md] running bounded package checks"
|
|
330
|
+
youmd machine verify --root "$ROOT" --max-projects "$LIMIT" --run-checks --max-check-projects "\${YOUMD_MAX_CHECK_PROJECTS:-8}" --check-timeout-ms "\${YOUMD_CHECK_TIMEOUT_MS:-120000}" --write-report --sync-report || true
|
|
331
|
+
else
|
|
332
|
+
echo "[you.md] bounded package checks skipped; set YOUMD_RUN_CHECKS=1 to run lint/typecheck/test/build caps"
|
|
333
|
+
fi
|
|
334
|
+
if [ "\${YOUMD_INSTALL_DEPS:-}" = "1" ] || [ "\${YOUMD_PROBE_SERVERS:-}" = "1" ]; then
|
|
335
|
+
echo "[you.md] running bounded clean-host install/server proof"
|
|
336
|
+
VERIFY_ARGS=(--root "$ROOT" --max-projects "$LIMIT")
|
|
337
|
+
if [ "\${YOUMD_INSTALL_DEPS:-}" = "1" ]; then
|
|
338
|
+
VERIFY_ARGS+=(--install-deps --max-install-projects "\${YOUMD_MAX_INSTALL_PROJECTS:-4}" --install-timeout-ms "\${YOUMD_INSTALL_TIMEOUT_MS:-180000}")
|
|
339
|
+
fi
|
|
340
|
+
if [ "\${YOUMD_PROBE_SERVERS:-}" = "1" ]; then
|
|
341
|
+
VERIFY_ARGS+=(--probe-servers --max-server-projects "\${YOUMD_MAX_SERVER_PROJECTS:-3}" --server-timeout-ms "\${YOUMD_SERVER_TIMEOUT_MS:-45000}" --server-start-port "\${YOUMD_SERVER_START_PORT:-4310}")
|
|
342
|
+
fi
|
|
343
|
+
youmd machine verify "\${VERIFY_ARGS[@]}" --write-report --sync-report || true
|
|
344
|
+
else
|
|
345
|
+
echo "[you.md] clean-host install/server proof skipped; set YOUMD_INSTALL_DEPS=1 and YOUMD_PROBE_SERVERS=1 to install deps and smoke-probe local dev servers"
|
|
346
|
+
fi
|
|
347
|
+
echo "[you.md] confirming resident realtime/identity/skillstack/project-context daemons"
|
|
348
|
+
youmd stack daemon install || true
|
|
349
|
+
youmd stack daemon status || true
|
|
350
|
+
youmd status
|
|
351
|
+
if [ "$FULL_PROJECT_SET_COMPLETE" = "1" ]; then
|
|
352
|
+
echo "[you.md] fresh-machine full \${EXPAND_DAYS}-day project setup complete: $ROOT"
|
|
353
|
+
else
|
|
354
|
+
echo "[you.md] fresh-machine \${DAYS}-day setup pass complete; \${EXPAND_DAYS}-day expansion is still open: $ROOT"
|
|
355
|
+
fi`;
|
|
242
356
|
}
|
|
243
357
|
function buildFreshMachineBootstrapCommand(options = {}) {
|
|
244
358
|
const assignments = [
|
|
245
359
|
envAssignment("YOUMD_API_KEY", options.apiKey),
|
|
246
|
-
envAssignment("YOUMD_CODE_ROOT", portableHomePath(options.root)),
|
|
360
|
+
envAssignment("YOUMD_CODE_ROOT", portableHomePath(options.root), { expandHome: true }),
|
|
247
361
|
envAssignment("YOUMD_ACTIVE_DAYS", options.days ?? exports.DEFAULT_FRESH_MACHINE_DAYS),
|
|
248
362
|
envAssignment("YOUMD_PROJECT_LIMIT", options.limit ?? exports.DEFAULT_FRESH_MACHINE_LIMIT),
|
|
249
363
|
envAssignment("YOUMD_MAX_CLONE_PROJECTS", options.maxCloneProjects),
|
|
250
|
-
envAssignment("YOUMD_ENV_VAULT", portableHomePath(options.envVaultPath)),
|
|
364
|
+
envAssignment("YOUMD_ENV_VAULT", portableHomePath(options.envVaultPath), { expandHome: true }),
|
|
251
365
|
envAssignment("YOUMD_REQUIRE_ENV_VAULT", options.requireEnvVault ? "1" : undefined),
|
|
252
366
|
].filter((value) => Boolean(value));
|
|
253
|
-
|
|
367
|
+
const pathPrefix = `PATH="$HOME/.youmd/bin:$HOME/.youmd/npm-global/bin:/opt/homebrew/opt/node@22/bin:/usr/local/opt/node@22/bin:/opt/homebrew/bin:/usr/local/bin:$PATH"`;
|
|
368
|
+
return `${[pathPrefix, ...assignments].join(" ")} bash -lc ${shellQuote(buildFreshMachineBootstrapScript())}`;
|
|
254
369
|
}
|
|
255
370
|
function buildFreshMachineBootstrapPrompt(options = {}) {
|
|
256
371
|
const root = portableHomePath(options.root) ?? exports.DEFAULT_FRESH_MACHINE_ROOT;
|
|
@@ -270,6 +385,8 @@ function buildFreshMachineBootstrapPrompt(options = {}) {
|
|
|
270
385
|
"",
|
|
271
386
|
authLine,
|
|
272
387
|
"",
|
|
388
|
+
"Behind-the-scenes operating rule: use the You.md CLI and You Agent yourself before asking Houston to do anything. Run deterministic commands like `youmd status`, `youmd whoami`, `youmd pull`, `youmd sync`, `youmd skill install all`, `youmd skill sync`, `youmd env vault list`, `youmd env vault pull`, `youmd machine prompt`, `youmd machine verify`, and `youmd project portfolio-hydrate` as needed. Use `you` / `youmd chat` only when you need the You Agent to synthesize or route context, then turn its output into concrete shell actions. Interrupt Houston only for true human-gated steps: GitHub browser auth, macOS Keychain/passphrase entry, npm OTP, OS permissions, or an explicit choice such as the 90-day expansion.",
|
|
389
|
+
"",
|
|
273
390
|
"Exact setup command:",
|
|
274
391
|
"",
|
|
275
392
|
"```bash",
|
|
@@ -277,19 +394,23 @@ function buildFreshMachineBootstrapPrompt(options = {}) {
|
|
|
277
394
|
"```",
|
|
278
395
|
"",
|
|
279
396
|
"What it will do:",
|
|
280
|
-
"- install
|
|
397
|
+
"- check/install the local prerequisites first: Homebrew, Node 22/npm, git, GitHub CLI, bun, and pnpm/corepack",
|
|
398
|
+
"- install You.md from the curl runtime and force the You.md/Homebrew/Node 22 paths into this setup shell",
|
|
281
399
|
"- authenticate and pull/sync your identity bundle",
|
|
400
|
+
"- install resident realtime sync daemons early so identity/skill/project-context sync is not deferred until the end",
|
|
401
|
+
"- require GitHub CLI auth before private shared-skill/project repos clone; if browser auth fails inside Claude/Codex, it prints the exact Terminal command to run and stops cleanly",
|
|
282
402
|
"- install/configure MCP for Claude Code and Codex",
|
|
283
|
-
"- restore shared agent skills, stack config, Claude/Codex links, and
|
|
403
|
+
"- restore shared agent skills, stack config, Claude/Codex links, and agent host config",
|
|
404
|
+
"- use the installed You.md CLI behind the scenes for status, skill sync, Secret Vault pull, portfolio graph hydration, machine verification, and You Agent context routing instead of making Houston manually drive those steps",
|
|
284
405
|
"- hydrate the portfolio graph from You.md + authenticated GitHub before cloning",
|
|
285
406
|
`- preview the graph-backed plan, create ${root}, and clone only projects marked ACTIVE plus Top Priority/Focusing from the last ${days} days first`,
|
|
286
407
|
`- ask whether to expand to all ACTIVE plus Top Priority/Focusing projects from the last ${expandDays} days before calling the full project clone set complete`,
|
|
287
|
-
"- check env-vault tooling, auto-detect the newest
|
|
408
|
+
"- check env-vault tooling, pull the latest account-backed You.md Secret Vault encrypted snapshot when available, otherwise auto-detect the newest local Desktop or iCloud Desktop `youmd-env-vault/env-vault-*` file if `YOUMD_ENV_VAULT` is not set, list the encrypted vault, try macOS Keychain service `youmd-env-vault` for the passphrase, restore env files into existing cloned project dirs with `--map-existing --existing-only --skip-agent-auth`, then rehydrate local project/env evidence",
|
|
288
409
|
"- write and sync a secret-safe machine proof report, with optional bounded install/check/server proof flags",
|
|
289
410
|
"- bound portfolio hydration with `YOUMD_PORTFOLIO_HYDRATE_TIMEOUT_SECONDS` so large restored roots do not wedge setup",
|
|
290
411
|
"",
|
|
291
412
|
`Project source: You.md portfolio graph + authenticated GitHub recent repos, capped at ${limit} tracked projects before local audit evidence is merged. When the graph exists, new-computer setup clones only projects with status ACTIVE and focus Top Priority/Focusing; inactive, unsorted, on-ice, abandoned, killed, and unreviewed GitHub-only repos are skipped unless --include-inactive is explicitly used. First pass is ${days} days with out-of-window projects skipped; the ${expandDays}-day pass is explicit.`,
|
|
292
|
-
"Secret rule: .env.local values are never embedded here.
|
|
413
|
+
"Secret rule: .env.local values are never embedded here. Best path: on the old/source Mac, run `youmd env vault push --root ~/Desktop/CODE_2025 --out ~/Desktop/youmd-env-vault` once. That uploads only encrypted archive bytes plus a safe manifest to You.md Secret Vault, so a trusted new Mac can pull it after login. Local fallback: run `youmd env backup --root ~/Desktop/CODE_2025 --out ~/Desktop/youmd-env-vault`, move the generated `env-vault-*.tar.enc` file to `~/Desktop/youmd-env-vault/` or the iCloud Desktop `youmd-env-vault/` on the new machine, then run this command. The command checks Secret Vault first, then auto-detects the newest local vault; you can also override with `YOUMD_ENV_VAULT=/path/to/env-vault-*.tar.enc`. If macOS Keychain contains service `youmd-env-vault` for the current user, restore uses it automatically; otherwise it prompts. The restore path lists variable names/counts and target paths only, never values, maps old folder names onto cloned dirs, and skips agent auth config so it does not clobber the new machine's active Claude/Codex login.",
|
|
293
414
|
"",
|
|
294
415
|
"After the command finishes, report:",
|
|
295
416
|
"- the `youmd status` sync state",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"machine-bootstrap-prompt.js","sourceRoot":"","sources":["../../src/lib/machine-bootstrap-prompt.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"machine-bootstrap-prompt.js","sourceRoot":"","sources":["../../src/lib/machine-bootstrap-prompt.ts"],"names":[],"mappings":"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"}
|