youmd 0.8.2 → 0.8.6
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/agent.d.ts +13 -0
- package/dist/commands/agent.d.ts.map +1 -0
- package/dist/commands/agent.js +233 -0
- package/dist/commands/agent.js.map +1 -0
- 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 +20 -4
- package/dist/commands/env.d.ts.map +1 -1
- package/dist/commands/env.js +613 -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 +200 -0
- package/dist/commands/sync.js.map +1 -1
- package/dist/index.js +71 -4
- package/dist/index.js.map +1 -1
- package/dist/lib/api.d.ts +173 -0
- package/dist/lib/api.d.ts.map +1 -1
- package/dist/lib/api.js +87 -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 +372 -184
- package/dist/lib/machine-bootstrap-prompt.js.map +1 -1
- package/dist/lib/realtime-sync.d.ts +174 -0
- package/dist/lib/realtime-sync.d.ts.map +1 -0
- package/dist/lib/realtime-sync.js +300 -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 +114 -19
|
@@ -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
|
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
# Usage: bash bootstrap-new-mac.sh
|
|
11
11
|
|
|
12
12
|
set -euo pipefail
|
|
13
|
+
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}"
|
|
13
14
|
|
|
14
15
|
AGENT_SHARED="${HOME}/.agent-shared"
|
|
15
16
|
SCISTACK="${HOME}/.claude/scistack"
|
|
@@ -33,6 +34,34 @@ warn() {
|
|
|
33
34
|
echo " WARN: $*"
|
|
34
35
|
}
|
|
35
36
|
|
|
37
|
+
ensure_github_auth() {
|
|
38
|
+
if ! command -v gh >/dev/null 2>&1; then
|
|
39
|
+
warn "GitHub CLI is missing. Install it with Homebrew first: brew install gh"
|
|
40
|
+
return 1
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
if gh auth status >/dev/null 2>&1; then
|
|
44
|
+
info "GitHub auth ready."
|
|
45
|
+
return 0
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
warn "GitHub auth is required before private skill/stack repos can clone."
|
|
49
|
+
if [ -t 0 ]; then
|
|
50
|
+
gh auth login -h github.com -p https -s repo || true
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
if gh auth status >/dev/null 2>&1; then
|
|
54
|
+
info "GitHub auth ready."
|
|
55
|
+
return 0
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
warn "GitHub auth still is not complete."
|
|
59
|
+
warn "Open a normal Terminal and run:"
|
|
60
|
+
warn " $(command -v gh || echo gh) auth login -h github.com -p https -s repo"
|
|
61
|
+
warn "Then rerun: youmd machine setup"
|
|
62
|
+
return 1
|
|
63
|
+
}
|
|
64
|
+
|
|
36
65
|
# ---------------------------------------------------------------------------
|
|
37
66
|
step "1. Install youmd CLI"
|
|
38
67
|
# ---------------------------------------------------------------------------
|
|
@@ -47,6 +76,8 @@ fi
|
|
|
47
76
|
# ---------------------------------------------------------------------------
|
|
48
77
|
step "2. Clone agent-shared repo → ${AGENT_SHARED}"
|
|
49
78
|
# ---------------------------------------------------------------------------
|
|
79
|
+
ensure_github_auth
|
|
80
|
+
|
|
50
81
|
if [ -d "${AGENT_SHARED}/.git" ]; then
|
|
51
82
|
info "Already present: ${AGENT_SHARED} — skipping clone."
|
|
52
83
|
else
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>Label</key>
|
|
6
|
+
<string>com.youmd.realtime-sync</string>
|
|
7
|
+
|
|
8
|
+
<key>ProgramArguments</key>
|
|
9
|
+
<array>
|
|
10
|
+
<string>/bin/zsh</string>
|
|
11
|
+
<string>-lc</string>
|
|
12
|
+
<string>youmd sync --live --daemon</string>
|
|
13
|
+
</array>
|
|
14
|
+
|
|
15
|
+
<key>RunAtLoad</key>
|
|
16
|
+
<true/>
|
|
17
|
+
|
|
18
|
+
<key>KeepAlive</key>
|
|
19
|
+
<true/>
|
|
20
|
+
|
|
21
|
+
<key>StandardOutPath</key>
|
|
22
|
+
<string>__HOME__/.youmd/logs/realtime-sync.out.log</string>
|
|
23
|
+
|
|
24
|
+
<key>StandardErrorPath</key>
|
|
25
|
+
<string>__HOME__/.youmd/logs/realtime-sync.err.log</string>
|
|
26
|
+
|
|
27
|
+
<key>EnvironmentVariables</key>
|
|
28
|
+
<dict>
|
|
29
|
+
<key>HOME</key>
|
|
30
|
+
<string>__HOME__</string>
|
|
31
|
+
<key>PATH</key>
|
|
32
|
+
<string>/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
|
|
33
|
+
</dict>
|
|
34
|
+
</dict>
|
|
35
|
+
</plist>
|
|
@@ -12,7 +12,7 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
|
12
12
|
LAUNCH_AGENTS_DIR="${HOME}/Library/LaunchAgents"
|
|
13
13
|
LOG_DIR="${HOME}/.youmd/logs"
|
|
14
14
|
|
|
15
|
-
PLISTS="com.youmd.skillstack-sync com.youmd.identity-sync com.youmd.context-sync"
|
|
15
|
+
PLISTS="com.youmd.realtime-sync com.youmd.skillstack-sync com.youmd.identity-sync com.youmd.context-sync"
|
|
16
16
|
|
|
17
17
|
echo "==> Creating log directory: ${LOG_DIR}"
|
|
18
18
|
mkdir -p "${LOG_DIR}"
|
|
@@ -58,6 +58,8 @@ echo "================================================================"
|
|
|
58
58
|
echo "Resident You.md daemons installed and running."
|
|
59
59
|
echo ""
|
|
60
60
|
echo "Log files:"
|
|
61
|
+
echo " ${LOG_DIR}/realtime-sync.out.log (Convex websocket sync stdout)"
|
|
62
|
+
echo " ${LOG_DIR}/realtime-sync.err.log (Convex websocket sync stderr)"
|
|
61
63
|
echo " ${LOG_DIR}/skillstack-sync.log (combined sync log)"
|
|
62
64
|
echo " ${LOG_DIR}/skillstack-sync.out.log (daemon stdout)"
|
|
63
65
|
echo " ${LOG_DIR}/skillstack-sync.err.log (daemon stderr)"
|
|
@@ -68,6 +70,7 @@ echo " ${LOG_DIR}/context-sync.out.log (daemon stdout)"
|
|
|
68
70
|
echo " ${LOG_DIR}/context-sync.err.log (daemon stderr)"
|
|
69
71
|
echo ""
|
|
70
72
|
echo "Check daemon status:"
|
|
73
|
+
echo " launchctl list com.youmd.realtime-sync"
|
|
71
74
|
echo " launchctl list com.youmd.skillstack-sync"
|
|
72
75
|
echo " launchctl list com.youmd.identity-sync"
|
|
73
76
|
echo " launchctl list com.youmd.context-sync"
|
|
@@ -34,12 +34,14 @@ You.md is the brain. The new machine should become a runnable local agent workst
|
|
|
34
34
|
for Claude Code or Codex on the new machine, generate it first:
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
|
-
youmd machine prompt --root ~/Desktop/CODE_YOU --days
|
|
37
|
+
youmd machine prompt --root ~/Desktop/CODE_YOU --days 30 --limit 80 --require-env-vault
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
If the web dashboard minted a scoped bootstrap key, the generated prompt may
|
|
41
41
|
include `YOUMD_API_KEY`. Treat that prompt as secret-bearing local setup
|
|
42
42
|
material and do not paste it into public chats, tickets, or docs.
|
|
43
|
+
Fresh-machine bootstrap keys must include the `vault` scope so the trusted
|
|
44
|
+
device can pull encrypted Secret Vault snapshots after login.
|
|
43
45
|
For bounded proof runs on a clean local root, add
|
|
44
46
|
`--max-clone-projects 2` or set `YOUMD_MAX_CLONE_PROJECTS=2`; omit that cap
|
|
45
47
|
on the real new machine.
|
|
@@ -70,31 +72,40 @@ You.md is the brain. The new machine should become a runnable local agent workst
|
|
|
70
72
|
|
|
71
73
|
6. Hydrate the portfolio graph from You.md/GitHub records before cloning, then
|
|
72
74
|
preview the graph-backed setup plan before creating the desktop code workspace
|
|
73
|
-
and syncing active projects:
|
|
75
|
+
and syncing truly active 30-day projects first:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
youmd project portfolio-hydrate --root ~/Desktop/CODE_YOU --days 30 --limit 80
|
|
79
|
+
youmd machine projects --root ~/Desktop/CODE_YOU --days 30 --recent-only --dry-run
|
|
80
|
+
youmd machine projects --root ~/Desktop/CODE_YOU --days 30 --recent-only
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
7. Ask whether Houston wants to expand the workspace to all active projects
|
|
84
|
+
from the last 90 days before calling the full project clone set complete:
|
|
74
85
|
|
|
75
86
|
```bash
|
|
76
87
|
youmd project portfolio-hydrate --root ~/Desktop/CODE_YOU --days 90 --limit 80
|
|
77
|
-
youmd machine projects --root ~/Desktop/CODE_YOU --days 90 --dry-run
|
|
78
|
-
youmd machine projects --root ~/Desktop/CODE_YOU --days 90
|
|
88
|
+
youmd machine projects --root ~/Desktop/CODE_YOU --days 90 --recent-only --dry-run
|
|
89
|
+
youmd machine projects --root ~/Desktop/CODE_YOU --days 90 --recent-only
|
|
79
90
|
```
|
|
80
91
|
|
|
81
|
-
|
|
92
|
+
8. If GitHub auth is missing, help the user log in and rerun only the project
|
|
82
93
|
clone step:
|
|
83
94
|
|
|
84
95
|
```bash
|
|
85
96
|
gh auth login
|
|
86
|
-
youmd machine projects --root ~/Desktop/CODE_YOU --days
|
|
97
|
+
youmd machine projects --root ~/Desktop/CODE_YOU --days 30 --recent-only
|
|
87
98
|
```
|
|
88
99
|
|
|
89
|
-
|
|
100
|
+
9. After projects are cloned and any encrypted env vault is restored, hydrate the
|
|
90
101
|
portfolio graph again so local README, project-context, git, PR, and env-key
|
|
91
102
|
evidence becomes visible to future agents:
|
|
92
103
|
|
|
93
104
|
```bash
|
|
94
|
-
youmd project portfolio-hydrate --root ~/Desktop/CODE_YOU --days
|
|
105
|
+
youmd project portfolio-hydrate --root ~/Desktop/CODE_YOU --days 30 --limit 80
|
|
95
106
|
```
|
|
96
107
|
|
|
97
|
-
|
|
108
|
+
10. Run the secret-safe readiness audit and sync the proof summary:
|
|
98
109
|
|
|
99
110
|
```bash
|
|
100
111
|
youmd machine verify --root ~/Desktop/CODE_YOU --max-projects 80 --write-report --sync-report
|
|
@@ -107,7 +118,7 @@ You.md is the brain. The new machine should become a runnable local agent workst
|
|
|
107
118
|
summary to the You.md machine dashboard. It does not read secret values,
|
|
108
119
|
upload raw logs, or launch every dev server.
|
|
109
120
|
|
|
110
|
-
|
|
121
|
+
11. Only when Houston explicitly wants deeper local proof or the clean host has
|
|
111
122
|
enough time/CPU, run bounded package checks and dev-server probes:
|
|
112
123
|
|
|
113
124
|
```bash
|
|
@@ -119,11 +130,46 @@ You.md is the brain. The new machine should become a runnable local agent workst
|
|
|
119
130
|
and dev-server probes are capped by default; tune with
|
|
120
131
|
`--max-install-projects`, `--max-server-projects`, and timeout flags.
|
|
121
132
|
|
|
133
|
+
## Behind-the-Scenes Agent Operation
|
|
134
|
+
|
|
135
|
+
- Use the You.md CLI and You Agent yourself before asking Houston to do manual
|
|
136
|
+
work. Prefer deterministic commands for setup and proof:
|
|
137
|
+
`youmd status`, `youmd whoami`, `youmd pull`, `youmd sync`,
|
|
138
|
+
`youmd machine prompt`, `youmd machine setup`,
|
|
139
|
+
`youmd skill install all`, `youmd skill sync`,
|
|
140
|
+
`youmd env vault list`, `youmd env vault pull`,
|
|
141
|
+
`youmd project portfolio-hydrate`, `youmd machine verify`,
|
|
142
|
+
`youmd agent status`, and `youmd agent inbox`.
|
|
143
|
+
- Report setup milestones to Houston's other trusted Macs with the realtime
|
|
144
|
+
agent bus instead of relying on clipboard/manual status relays:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
youmd agent send --channel machine-sync --kind status "Mac mini completed identity + skill sync"
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
This writes through Convex realtime and the receiving daemon materializes it
|
|
151
|
+
into `~/.youmd/agent-bus/inbox.json` without reading or exposing `.env.local`
|
|
152
|
+
values.
|
|
153
|
+
- Use `you` / `youmd chat` when you need the You Agent to synthesize context,
|
|
154
|
+
route a natural-language request, or produce the setup artifact, then turn the
|
|
155
|
+
result into concrete shell actions.
|
|
156
|
+
- Do not stop to ask "what next?" after each setup phase. Continue through the
|
|
157
|
+
command, verify the result, and report concise proof.
|
|
158
|
+
- Interrupt Houston only for true human-gated steps: GitHub browser auth,
|
|
159
|
+
source-Mac Secret Vault share/passphrase entry if no trusted-device envelope
|
|
160
|
+
exists yet, npm OTP, OS permissions, or the explicit 90-day project expansion
|
|
161
|
+
choice.
|
|
162
|
+
- If the installed CLI is stale, run the curl installer/update path first, then
|
|
163
|
+
retry the You.md command. Tell Houston when npm publish is needed for
|
|
164
|
+
`npx youmd@latest` or npm fallback installs.
|
|
165
|
+
|
|
122
166
|
## Project Bootstrap Rules
|
|
123
167
|
|
|
124
168
|
- Use repo directory names from GitHub URLs. `https://github.com/houstongolden/foldermd` becomes `foldermd`.
|
|
125
|
-
- Default to projects active in the last
|
|
126
|
-
|
|
169
|
+
- Default to projects active in the last 30 days and marked active plus Top
|
|
170
|
+
Priority/Focusing in You.md. Ask before expanding to the 90-day active set.
|
|
171
|
+
- Ask before including older, archived, paused, inactive, on-ice, abandoned,
|
|
172
|
+
killed, dormant, or unsorted projects.
|
|
127
173
|
- Create the workspace root on the Desktop if it is missing. `CODE_YOU` is the default fresh-machine root.
|
|
128
174
|
- Use the You.md Portfolio Graph as the strategic source of truth, then merge
|
|
129
175
|
authenticated GitHub recent-repo data and local bundle project records so repo
|
|
@@ -133,7 +179,9 @@ You.md is the brain. The new machine should become a runnable local agent workst
|
|
|
133
179
|
local bundle plus authenticated GitHub scan and say so.
|
|
134
180
|
- Clone with `gh repo clone owner/repo <target>` when `gh` is authenticated; otherwise fall back to `git clone`.
|
|
135
181
|
- Skip non-empty directories instead of overwriting them.
|
|
136
|
-
- Never print secrets. If `.env.local` files are needed, use
|
|
182
|
+
- Never print secrets. If `.env.local` files are needed, use You.md Secret Vault
|
|
183
|
+
or the shared encrypted env backup/restore path. Never paste raw env values
|
|
184
|
+
into chat.
|
|
137
185
|
- After cloning, initialize missing per-repo agent context with `youmd skill init-project` from inside that repo.
|
|
138
186
|
|
|
139
187
|
## Secret-Safe Env Transfer
|
|
@@ -146,18 +194,65 @@ Audit local project env coverage before backup:
|
|
|
146
194
|
youmd env backup --root ~/Desktop/CODE_2025 --preflight
|
|
147
195
|
```
|
|
148
196
|
|
|
149
|
-
|
|
197
|
+
Primary path: from the old/source machine, create an encrypted archive and push
|
|
198
|
+
only the ciphertext plus safe manifest metadata to You.md Secret Vault:
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
youmd env vault push --root ~/Desktop/CODE_2025 --out ~/Desktop/youmd-env-vault
|
|
202
|
+
youmd env vault list
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
On the new machine, register its local Secret Vault device key. The private key
|
|
206
|
+
stays under `~/.youmd/secret-vault/devices/`; only the public key is synced:
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
youmd env vault device-register
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Back on the old/source machine, share local decrypt access to trusted devices.
|
|
213
|
+
This stores per-device encrypted passphrase envelopes; it does not upload raw env
|
|
214
|
+
values:
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
youmd env vault share
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
On the new machine, pull the latest encrypted account snapshot and restore into
|
|
221
|
+
already-cloned project directories without clobbering local agent auth:
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
youmd env vault pull --restore --root ~/Desktop/CODE_YOU --map-existing --existing-only --skip-agent-auth
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
If `pull --restore` says no trusted-device envelope exists for this Mac, do not
|
|
228
|
+
ask Houston for raw secrets. Confirm `device-register` ran on the new Mac, run
|
|
229
|
+
`youmd env vault share` on the source Mac, then rerun `pull --restore`.
|
|
230
|
+
|
|
231
|
+
Fallback path: create an encrypted archive from the old machine in an
|
|
232
|
+
interactive macOS terminal and transfer the encrypted file by iCloud, AirDrop,
|
|
233
|
+
USB, or private password-manager attachment:
|
|
150
234
|
|
|
151
235
|
```bash
|
|
152
236
|
open ~/.agent-shared/bin/env-backup-interactive.command
|
|
237
|
+
youmd env backup --root ~/Desktop/CODE_2025 --out ~/Desktop/youmd-env-vault
|
|
153
238
|
```
|
|
154
239
|
|
|
155
240
|
On the new machine, list the encrypted archive by path only before restore:
|
|
156
241
|
|
|
157
242
|
```bash
|
|
158
243
|
~/.agent-shared/bin/env-secure-restore.sh --archive ~/Desktop/env-local-backup.tar.gz.gpg --list
|
|
159
|
-
youmd env restore ~/Desktop/env-local-backup.tar.gz.gpg --root ~/Desktop/CODE_YOU --list
|
|
160
|
-
youmd env restore ~/Desktop/env-local-backup.tar.gz.gpg --root ~/Desktop/CODE_YOU
|
|
244
|
+
youmd env restore ~/Desktop/env-local-backup.tar.gz.gpg --root ~/Desktop/CODE_YOU --list --map-existing --existing-only --skip-agent-auth
|
|
245
|
+
youmd env restore ~/Desktop/env-local-backup.tar.gz.gpg --root ~/Desktop/CODE_YOU --map-existing --existing-only --skip-agent-auth
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
If a headless agent still cannot decrypt after device sharing, then and only then
|
|
249
|
+
use the macOS Keychain fallback for the env-vault passphrase. Input is silent and
|
|
250
|
+
the value is not printed:
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
read -rs "PW?You.md vault passphrase: " && \
|
|
254
|
+
security add-generic-password -a "$USER" -s youmd-env-vault -w "$PW" -U && \
|
|
255
|
+
unset PW && echo "stored in Keychain"
|
|
161
256
|
```
|
|
162
257
|
|
|
163
258
|
## Useful Variants
|
|
@@ -165,7 +260,7 @@ youmd env restore ~/Desktop/env-local-backup.tar.gz.gpg --root ~/Desktop/CODE_YO
|
|
|
165
260
|
Dry-run the project layout:
|
|
166
261
|
|
|
167
262
|
```bash
|
|
168
|
-
youmd machine projects --root ~/Desktop/CODE_YOU --days
|
|
263
|
+
youmd machine projects --root ~/Desktop/CODE_YOU --days 30 --recent-only --dry-run
|
|
169
264
|
```
|
|
170
265
|
|
|
171
266
|
Create directories only, without cloning:
|
|
@@ -201,13 +296,13 @@ youmd machine projects --root ~/Desktop/CODE_YOU --yes
|
|
|
201
296
|
Generate the copy/paste prompt for a new Claude Code or Codex terminal:
|
|
202
297
|
|
|
203
298
|
```bash
|
|
204
|
-
youmd machine prompt --root ~/Desktop/CODE_YOU --days
|
|
299
|
+
youmd machine prompt --root ~/Desktop/CODE_YOU --days 30 --limit 80 --require-env-vault
|
|
205
300
|
```
|
|
206
301
|
|
|
207
302
|
Generate the same prompt but cap clones for a clean-host proof run:
|
|
208
303
|
|
|
209
304
|
```bash
|
|
210
|
-
youmd machine prompt --root /tmp/youmd-clean-host-CODE_YOU --days
|
|
305
|
+
youmd machine prompt --root /tmp/youmd-clean-host-CODE_YOU --days 30 --limit 80 --max-clone-projects 2 --require-env-vault
|
|
211
306
|
```
|
|
212
307
|
|
|
213
308
|
Fetch the secret-safe project graph directly:
|