youmd 0.7.1 → 0.8.2
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 +3 -2
- package/dist/commands/chat.js.map +1 -1
- package/dist/commands/env.d.ts +2 -0
- package/dist/commands/env.d.ts.map +1 -1
- package/dist/commands/env.js +7 -3
- package/dist/commands/env.js.map +1 -1
- package/dist/commands/login.d.ts +1 -0
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +20 -4
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/machine.d.ts +31 -0
- package/dist/commands/machine.d.ts.map +1 -1
- package/dist/commands/machine.js +610 -14
- package/dist/commands/machine.js.map +1 -1
- package/dist/commands/project-log.d.ts +13 -0
- package/dist/commands/project-log.d.ts.map +1 -0
- package/dist/commands/project-log.js +241 -0
- package/dist/commands/project-log.js.map +1 -0
- package/dist/commands/project.d.ts.map +1 -1
- package/dist/commands/project.js +872 -15
- package/dist/commands/project.js.map +1 -1
- package/dist/commands/prompts.d.ts +19 -0
- package/dist/commands/prompts.d.ts.map +1 -1
- package/dist/commands/prompts.js +304 -1
- package/dist/commands/prompts.js.map +1 -1
- package/dist/commands/pull.d.ts.map +1 -1
- package/dist/commands/pull.js +28 -8
- package/dist/commands/pull.js.map +1 -1
- package/dist/commands/push.d.ts +3 -1
- package/dist/commands/push.d.ts.map +1 -1
- package/dist/commands/push.js +26 -12
- package/dist/commands/push.js.map +1 -1
- package/dist/commands/skill.d.ts.map +1 -1
- package/dist/commands/skill.js +19 -15
- package/dist/commands/skill.js.map +1 -1
- package/dist/commands/stack.d.ts.map +1 -1
- package/dist/commands/stack.js +37 -17
- package/dist/commands/stack.js.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +31 -0
- 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 +51 -2
- package/dist/commands/sync.js.map +1 -1
- package/dist/index.js +125 -36
- package/dist/index.js.map +1 -1
- package/dist/lib/api.d.ts +324 -0
- package/dist/lib/api.d.ts.map +1 -1
- package/dist/lib/api.js +68 -0
- package/dist/lib/api.js.map +1 -1
- package/dist/lib/compiler.d.ts.map +1 -1
- package/dist/lib/compiler.js +10 -0
- package/dist/lib/compiler.js.map +1 -1
- package/dist/lib/daemon.d.ts +23 -0
- package/dist/lib/daemon.d.ts.map +1 -0
- package/dist/lib/daemon.js +166 -0
- package/dist/lib/daemon.js.map +1 -0
- package/dist/lib/first-run.d.ts +1 -1
- package/dist/lib/first-run.d.ts.map +1 -1
- package/dist/lib/first-run.js +8 -0
- package/dist/lib/first-run.js.map +1 -1
- package/dist/lib/machine-bootstrap-prompt.d.ts +17 -0
- package/dist/lib/machine-bootstrap-prompt.d.ts.map +1 -0
- package/dist/lib/machine-bootstrap-prompt.js +305 -0
- package/dist/lib/machine-bootstrap-prompt.js.map +1 -0
- package/dist/lib/machine-projects.d.ts +71 -0
- package/dist/lib/machine-projects.d.ts.map +1 -0
- package/dist/lib/machine-projects.js +510 -0
- package/dist/lib/machine-projects.js.map +1 -0
- package/dist/lib/machine-verify.d.ts +175 -0
- package/dist/lib/machine-verify.d.ts.map +1 -0
- package/dist/lib/machine-verify.js +684 -0
- package/dist/lib/machine-verify.js.map +1 -0
- package/dist/lib/portfolio-audit.d.ts +34 -0
- package/dist/lib/portfolio-audit.d.ts.map +1 -0
- package/dist/lib/portfolio-audit.js +254 -0
- package/dist/lib/portfolio-audit.js.map +1 -0
- package/dist/lib/portfolio-graph.d.ts +104 -0
- package/dist/lib/portfolio-graph.d.ts.map +1 -0
- package/dist/lib/portfolio-graph.js +281 -0
- package/dist/lib/portfolio-graph.js.map +1 -0
- package/dist/lib/project-strategy.d.ts +45 -0
- package/dist/lib/project-strategy.d.ts.map +1 -0
- package/dist/lib/project-strategy.js +234 -0
- package/dist/lib/project-strategy.js.map +1 -0
- package/dist/lib/reusable-patterns.d.ts +30 -0
- package/dist/lib/reusable-patterns.d.ts.map +1 -0
- package/dist/lib/reusable-patterns.js +375 -0
- package/dist/lib/reusable-patterns.js.map +1 -0
- package/dist/lib/skill-catalog.d.ts.map +1 -1
- package/dist/lib/skill-catalog.js +20 -0
- package/dist/lib/skill-catalog.js.map +1 -1
- package/dist/lib/skills.d.ts +1 -0
- package/dist/lib/skills.d.ts.map +1 -1
- package/dist/lib/skills.js +43 -13
- package/dist/lib/skills.js.map +1 -1
- package/dist/lib/version.d.ts +2 -0
- package/dist/lib/version.d.ts.map +1 -0
- package/dist/lib/version.js +63 -0
- package/dist/lib/version.js.map +1 -0
- package/dist/mcp/registry.d.ts +5 -1
- package/dist/mcp/registry.d.ts.map +1 -1
- package/dist/mcp/registry.js +426 -2
- package/dist/mcp/registry.js.map +1 -1
- package/dist/mcp/server.d.ts +2 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +50 -5
- package/dist/mcp/server.js.map +1 -1
- package/package.json +1 -1
- package/scripts/env-vault/README.md +37 -10
- package/scripts/env-vault/backup.sh +70 -4
- package/scripts/env-vault/restore.sh +117 -9
- package/scripts/skillstack-sync/README.md +13 -6
- package/scripts/skillstack-sync/bootstrap-new-mac.sh +19 -5
- package/scripts/skillstack-sync/capture-agent-config.sh +110 -0
- package/scripts/skillstack-sync/com.youmd.context-sync.plist +38 -0
- package/scripts/skillstack-sync/com.youmd.identity-sync.plist +3 -1
- package/scripts/skillstack-sync/com.youmd.skillstack-sync.plist +1 -1
- package/scripts/skillstack-sync/context-sync.sh +412 -0
- package/scripts/skillstack-sync/install-daemons.sh +7 -3
- package/scripts/skillstack-sync/restore-agent-config.sh +152 -0
- package/scripts/skillstack-sync/sync.sh +20 -6
- package/skills/machine-bootstrap.md +243 -0
|
@@ -1,8 +1,22 @@
|
|
|
1
|
-
# env-vault — Secure .env.local Backup & Restore
|
|
1
|
+
# env-vault — Secure .env.local + Agent-Auth Backup & Restore
|
|
2
2
|
|
|
3
|
-
Backs up all `.env.local` files across your CODE_2025 projects
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
Backs up all `.env.local` files across your CODE_2025 projects **and** a fixed
|
|
4
|
+
set of hard agent-auth secret files into a single encrypted archive, and
|
|
5
|
+
restores them on a new Mac. No secret values ever appear in plaintext outside
|
|
6
|
+
the encrypted blob.
|
|
7
|
+
|
|
8
|
+
### What's in the vault
|
|
9
|
+
|
|
10
|
+
| Source path | Archive path | Restore destination |
|
|
11
|
+
|---|---|---|
|
|
12
|
+
| `<CODE_2025>/<project>/.env.local` | `<project>/.env.local` | `<CODE_2025>/<project>/.env.local` |
|
|
13
|
+
| `~/.codex/auth.json` | `agent-auth/codex-auth.json` | `~/.codex/auth.json` |
|
|
14
|
+
| `~/.cursor/mcp.json` | `agent-auth/cursor-mcp.json` | `~/.cursor/mcp.json` |
|
|
15
|
+
| `~/.claude.json` | `agent-auth/claude.json` | `~/.claude.json` |
|
|
16
|
+
|
|
17
|
+
To add more agent-auth files, extend the `AGENT_SECRET_FILES` array near the
|
|
18
|
+
top of `backup.sh` and add the matching entry to `AGENT_AUTH_MAP` in
|
|
19
|
+
`restore.sh`.
|
|
6
20
|
|
|
7
21
|
---
|
|
8
22
|
|
|
@@ -14,6 +28,9 @@ in plaintext outside the encrypted blob.
|
|
|
14
28
|
# via CLI (preferred — ships in the npm package)
|
|
15
29
|
youmd env backup
|
|
16
30
|
|
|
31
|
+
# Check local encryption tooling and env discovery without writing a vault:
|
|
32
|
+
youmd env backup --preflight
|
|
33
|
+
|
|
17
34
|
# or directly via bash (from the youmd repo root)
|
|
18
35
|
cd /Users/houstongolden/Desktop/CODE_2025/youmd
|
|
19
36
|
bash cli/scripts/env-vault/backup.sh
|
|
@@ -21,7 +38,7 @@ bash cli/scripts/env-vault/backup.sh
|
|
|
21
38
|
|
|
22
39
|
This writes two files to `.env-vault/`:
|
|
23
40
|
- `env-vault-<date>.tar.<ext>` — encrypted archive (safe to transport)
|
|
24
|
-
- `manifest-<date>.txt` — variable names + counts only (safe to read, no values)
|
|
41
|
+
- `manifest-<date>.txt` — variable names + counts + agent-auth file paths/sizes only (safe to read, no values)
|
|
25
42
|
|
|
26
43
|
You will be prompted for a passphrase. Store it in **1Password** immediately.
|
|
27
44
|
|
|
@@ -38,9 +55,10 @@ Do NOT transfer via unencrypted email or public Slack.
|
|
|
38
55
|
|
|
39
56
|
```bash
|
|
40
57
|
# Install dependencies first (e.g. Node, pnpm, etc.), then:
|
|
58
|
+
youmd env restore /path/to/env-vault-<date>.tar.<ext> --list
|
|
41
59
|
youmd env restore /path/to/env-vault-<date>.tar.<ext>
|
|
42
60
|
|
|
43
|
-
# If
|
|
61
|
+
# If files already exist on the new Mac:
|
|
44
62
|
youmd env restore --force /path/to/env-vault-<date>.tar.<ext>
|
|
45
63
|
|
|
46
64
|
# or directly via bash:
|
|
@@ -48,8 +66,13 @@ bash cli/scripts/env-vault/restore.sh /path/to/env-vault-<date>.tar.<ext>
|
|
|
48
66
|
bash cli/scripts/env-vault/restore.sh --force /path/to/env-vault-<date>.tar.<ext>
|
|
49
67
|
```
|
|
50
68
|
|
|
51
|
-
The script
|
|
52
|
-
|
|
69
|
+
The script:
|
|
70
|
+
1. Lists vault contents without writing files when `--list` is provided.
|
|
71
|
+
2. Creates `<CODE_2025>/<project>/.env.local` for each project during restore.
|
|
72
|
+
3. Restores agent-auth files to their absolute home paths (`~/.codex/auth.json`, `~/.cursor/mcp.json`, `~/.claude.json`), creating parent directories as needed.
|
|
73
|
+
|
|
74
|
+
Existing files are backed up to `<path>.bak.<timestamp>` before overwrite (or silently overwritten with `--force`).
|
|
75
|
+
List mode prints project env target paths, variable names/counts, and agent-auth file presence only. It never prints secret values.
|
|
53
76
|
|
|
54
77
|
---
|
|
55
78
|
|
|
@@ -70,8 +93,8 @@ The encrypted file itself is safe to store anywhere. The passphrase is the secre
|
|
|
70
93
|
## Security Model
|
|
71
94
|
|
|
72
95
|
- **Encryption:** `age` (preferred) → `gpg AES-256` → `openssl AES-256-CBC PBKDF2`
|
|
73
|
-
- **What's in the encrypted archive:** full `.env.local` file contents
|
|
74
|
-
- **What's in plaintext:** only the project name + variable NAMES + count (the manifest)
|
|
96
|
+
- **What's in the encrypted archive:** full `.env.local` file contents + agent-auth files (`~/.codex/auth.json`, `~/.cursor/mcp.json`, `~/.claude.json`)
|
|
97
|
+
- **What's in plaintext:** only the project name + variable NAMES + count + agent-auth file paths/byte-sizes (the manifest)
|
|
75
98
|
- **Values:** never printed, echoed, logged, or written anywhere outside the encrypted blob
|
|
76
99
|
- **Passphrase:** stored nowhere by these scripts — you must store it in 1Password
|
|
77
100
|
|
|
@@ -84,10 +107,12 @@ and are exposed as first-class CLI commands:
|
|
|
84
107
|
|
|
85
108
|
```bash
|
|
86
109
|
youmd env backup # back up all .env.local files
|
|
110
|
+
youmd env backup --preflight # verify tooling/discovery without writing
|
|
87
111
|
youmd env backup --root <dir> # custom search root
|
|
88
112
|
youmd env backup --out <dir> # custom output dir
|
|
89
113
|
|
|
90
114
|
youmd env restore <vault> # restore from an encrypted vault
|
|
115
|
+
youmd env restore <vault> --list # list vault contents without writing
|
|
91
116
|
youmd env restore --force # overwrite existing .env.local files
|
|
92
117
|
youmd env restore --root <dir> # restore into a custom root
|
|
93
118
|
```
|
|
@@ -104,6 +129,7 @@ your terminal unchanged.
|
|
|
104
129
|
|
|
105
130
|
| Flag | Default | Description |
|
|
106
131
|
|------|---------|-------------|
|
|
132
|
+
| `--preflight` | off | Verify encryption tooling/discovery without writing a vault |
|
|
107
133
|
| `--root <dir>` | `~/Desktop/CODE_2025` | Where to discover `.env.local` files |
|
|
108
134
|
| `--out <dir>` | `youmd/.env-vault/` | Where to write encrypted vault + manifest |
|
|
109
135
|
|
|
@@ -111,6 +137,7 @@ your terminal unchanged.
|
|
|
111
137
|
|
|
112
138
|
| Flag | Default | Description |
|
|
113
139
|
|------|---------|-------------|
|
|
140
|
+
| `--list` | off | List vault contents without writing files |
|
|
114
141
|
| `--root <dir>` | `~/Desktop/CODE_2025` | Where to restore project `.env.local` files |
|
|
115
142
|
| `--force` | off | Overwrite existing `.env.local` instead of skipping |
|
|
116
143
|
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# env-vault/backup.sh — backs up all .env.local files under CODE_2025
|
|
3
|
-
#
|
|
4
|
-
# Only variable NAMES
|
|
2
|
+
# env-vault/backup.sh — backs up all .env.local files under CODE_2025 AND a
|
|
3
|
+
# fixed set of agent-auth secret files into an encrypted vault. NEVER prints,
|
|
4
|
+
# echoes, logs, or writes any secret VALUE. Only variable NAMES, counts, and
|
|
5
|
+
# file paths appear in plaintext output.
|
|
5
6
|
#
|
|
6
|
-
# Usage: bash backup.sh [--root <search-root>] [--out <output-dir>]
|
|
7
|
+
# Usage: bash backup.sh [--preflight] [--root <search-root>] [--out <output-dir>]
|
|
7
8
|
# Defaults:
|
|
8
9
|
# search-root: /Users/houstongolden/Desktop/CODE_2025
|
|
9
10
|
# output-dir: /Users/houstongolden/Desktop/CODE_2025/youmd/.env-vault
|
|
@@ -13,10 +14,22 @@ set -euo pipefail
|
|
|
13
14
|
# ── configurable defaults ──────────────────────────────────────────────────────
|
|
14
15
|
SEARCH_ROOT="${ENV_VAULT_ROOT:-/Users/houstongolden/Desktop/CODE_2025}"
|
|
15
16
|
OUTPUT_DIR="${ENV_VAULT_OUT:-/Users/houstongolden/Desktop/CODE_2025/youmd/.env-vault}"
|
|
17
|
+
PREFLIGHT=false
|
|
18
|
+
|
|
19
|
+
# ── agent-auth secret files ────────────────────────────────────────────────────
|
|
20
|
+
# Absolute paths to hard agent-auth secrets that must travel with the vault.
|
|
21
|
+
# Each entry is archived as agent-auth/<stable-name> inside the tar.
|
|
22
|
+
# To add more: append to this array. Format: "absolute-path:stable-archive-name"
|
|
23
|
+
AGENT_SECRET_FILES=(
|
|
24
|
+
"${HOME}/.codex/auth.json:codex-auth.json"
|
|
25
|
+
"${HOME}/.cursor/mcp.json:cursor-mcp.json"
|
|
26
|
+
"${HOME}/.claude.json:claude.json"
|
|
27
|
+
)
|
|
16
28
|
|
|
17
29
|
# ── parse flags ────────────────────────────────────────────────────────────────
|
|
18
30
|
while [[ $# -gt 0 ]]; do
|
|
19
31
|
case $1 in
|
|
32
|
+
--preflight) PREFLIGHT=true; shift ;;
|
|
20
33
|
--root) SEARCH_ROOT="$2"; shift 2 ;;
|
|
21
34
|
--out) OUTPUT_DIR="$2"; shift 2 ;;
|
|
22
35
|
*) echo "Unknown flag: $1" >&2; exit 1 ;;
|
|
@@ -55,11 +68,32 @@ done < <(find "${SEARCH_ROOT}" -maxdepth 2 -name ".env.local" -print0 2>/dev/nul
|
|
|
55
68
|
|
|
56
69
|
if [[ ${#ENV_FILES[@]} -eq 0 ]]; then
|
|
57
70
|
echo "No .env.local files found under ${SEARCH_ROOT}" >&2
|
|
71
|
+
if [[ "${PREFLIGHT}" == "true" ]]; then
|
|
72
|
+
echo "Preflight only: encryption tooling is available, but no .env.local files were found."
|
|
73
|
+
exit 0
|
|
74
|
+
fi
|
|
58
75
|
exit 1
|
|
59
76
|
fi
|
|
60
77
|
|
|
61
78
|
echo "Found ${#ENV_FILES[@]} .env.local file(s)."
|
|
62
79
|
|
|
80
|
+
if [[ "${PREFLIGHT}" == "true" ]]; then
|
|
81
|
+
echo "Output dir: ${OUTPUT_DIR}"
|
|
82
|
+
echo "Agent-auth candidates:"
|
|
83
|
+
for ENTRY in "${AGENT_SECRET_FILES[@]}"; do
|
|
84
|
+
SRC_PATH="${ENTRY%%:*}"
|
|
85
|
+
ARCHIVE_NAME="${ENTRY##*:}"
|
|
86
|
+
if [[ -f "${SRC_PATH}" ]]; then
|
|
87
|
+
FILE_BYTES=$(wc -c < "${SRC_PATH}" | tr -d ' ')
|
|
88
|
+
echo " present: agent-auth/${ARCHIVE_NAME} (${FILE_BYTES} bytes)"
|
|
89
|
+
else
|
|
90
|
+
echo " missing: agent-auth/${ARCHIVE_NAME}"
|
|
91
|
+
fi
|
|
92
|
+
done
|
|
93
|
+
echo "Preflight only: no vault written and no secret values printed."
|
|
94
|
+
exit 0
|
|
95
|
+
fi
|
|
96
|
+
|
|
63
97
|
# ── build plaintext manifest (names + counts, NO values) ─────────────────────
|
|
64
98
|
mkdir -p "${OUTPUT_DIR}"
|
|
65
99
|
UTC_DATE="$(date -u +%Y-%m-%dT%H%MZ)"
|
|
@@ -94,6 +128,38 @@ for ENV_FILE in "${ENV_FILES[@]}"; do
|
|
|
94
128
|
>> "${MANIFEST_PATH}"
|
|
95
129
|
done
|
|
96
130
|
|
|
131
|
+
# ── stage agent-auth secret files ─────────────────────────────────────────────
|
|
132
|
+
# Each entry in AGENT_SECRET_FILES has format "absolute-path:stable-archive-name".
|
|
133
|
+
# Files are stored under agent-auth/<stable-name> inside the archive.
|
|
134
|
+
# Only the path and byte-size appear in the manifest — never the contents.
|
|
135
|
+
AGENT_AUTH_STAGING="${STAGING_DIR}/agent-auth"
|
|
136
|
+
mkdir -p "${AGENT_AUTH_STAGING}"
|
|
137
|
+
AGENT_AUTH_COUNT=0
|
|
138
|
+
|
|
139
|
+
echo "" >> "${MANIFEST_PATH}"
|
|
140
|
+
echo "agent-auth files:" >> "${MANIFEST_PATH}"
|
|
141
|
+
|
|
142
|
+
for ENTRY in "${AGENT_SECRET_FILES[@]}"; do
|
|
143
|
+
SRC_PATH="${ENTRY%%:*}"
|
|
144
|
+
ARCHIVE_NAME="${ENTRY##*:}"
|
|
145
|
+
|
|
146
|
+
if [[ -f "${SRC_PATH}" ]]; then
|
|
147
|
+
cp "${SRC_PATH}" "${AGENT_AUTH_STAGING}/${ARCHIVE_NAME}"
|
|
148
|
+
FILE_BYTES=$(wc -c < "${SRC_PATH}" | tr -d ' ')
|
|
149
|
+
echo " agent-auth/${ARCHIVE_NAME} (${SRC_PATH}): ${FILE_BYTES} bytes" \
|
|
150
|
+
>> "${MANIFEST_PATH}"
|
|
151
|
+
echo " Staged agent-auth: ${SRC_PATH} → agent-auth/${ARCHIVE_NAME}"
|
|
152
|
+
(( AGENT_AUTH_COUNT++ )) || true
|
|
153
|
+
else
|
|
154
|
+
echo " agent-auth/${ARCHIVE_NAME} (${SRC_PATH}): NOT FOUND — skipped" \
|
|
155
|
+
>> "${MANIFEST_PATH}"
|
|
156
|
+
echo " Skipped (not found): ${SRC_PATH}"
|
|
157
|
+
fi
|
|
158
|
+
done
|
|
159
|
+
|
|
160
|
+
echo ""
|
|
161
|
+
echo "Staged ${AGENT_AUTH_COUNT} agent-auth file(s)."
|
|
162
|
+
|
|
97
163
|
echo "" >> "${MANIFEST_PATH}"
|
|
98
164
|
echo "SECURITY: The encrypted archive is safe to transport. Keep the passphrase private." \
|
|
99
165
|
>> "${MANIFEST_PATH}"
|
|
@@ -1,23 +1,42 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# env-vault/restore.sh — restores .env.local files
|
|
3
|
-
# created by backup.sh. NEVER prints, echoes, or logs any
|
|
4
|
-
#
|
|
2
|
+
# env-vault/restore.sh — restores .env.local files AND agent-auth secrets from
|
|
3
|
+
# an encrypted vault created by backup.sh. NEVER prints, echoes, or logs any
|
|
4
|
+
# secret VALUES. Restore prints which file paths were restored or skipped; list
|
|
5
|
+
# mode prints target paths plus variable names/counts only.
|
|
5
6
|
#
|
|
6
|
-
# Usage: bash restore.sh [--force] [--root <target-root>] <vault-file>
|
|
7
|
+
# Usage: bash restore.sh [--list] [--force] [--root <target-root>] <vault-file>
|
|
7
8
|
# vault-file: path to env-vault-*.tar.age / .tar.gpg / .tar.enc
|
|
8
|
-
# --force: overwrite existing
|
|
9
|
-
# --root: destination root
|
|
9
|
+
# --force: overwrite existing files without backing them up
|
|
10
|
+
# --root: destination root for .env.local files
|
|
11
|
+
# (default: /Users/houstongolden/Desktop/CODE_2025)
|
|
12
|
+
#
|
|
13
|
+
# agent-auth restore map (archive name → absolute home path):
|
|
14
|
+
# agent-auth/codex-auth.json → ~/.codex/auth.json
|
|
15
|
+
# agent-auth/cursor-mcp.json → ~/.cursor/mcp.json
|
|
16
|
+
# agent-auth/claude.json → ~/.claude.json
|
|
10
17
|
|
|
11
18
|
set -euo pipefail
|
|
12
19
|
|
|
20
|
+
# ── agent-auth restore map ─────────────────────────────────────────────────────
|
|
21
|
+
# Maps archive name (inside agent-auth/) to its absolute home destination.
|
|
22
|
+
# Format: "archive-name:absolute-destination-path"
|
|
23
|
+
# Must stay in sync with AGENT_SECRET_FILES in backup.sh.
|
|
24
|
+
AGENT_AUTH_MAP=(
|
|
25
|
+
"codex-auth.json:${HOME}/.codex/auth.json"
|
|
26
|
+
"cursor-mcp.json:${HOME}/.cursor/mcp.json"
|
|
27
|
+
"claude.json:${HOME}/.claude.json"
|
|
28
|
+
)
|
|
29
|
+
|
|
13
30
|
# ── defaults ──────────────────────────────────────────────────────────────────
|
|
14
31
|
TARGET_ROOT="${ENV_VAULT_RESTORE_ROOT:-/Users/houstongolden/Desktop/CODE_2025}"
|
|
15
32
|
FORCE=false
|
|
33
|
+
LIST_ONLY=false
|
|
16
34
|
VAULT_FILE=""
|
|
17
35
|
|
|
18
36
|
# ── parse args ─────────────────────────────────────────────────────────────────
|
|
19
37
|
while [[ $# -gt 0 ]]; do
|
|
20
38
|
case $1 in
|
|
39
|
+
--list) LIST_ONLY=true; shift ;;
|
|
21
40
|
--force) FORCE=true; shift ;;
|
|
22
41
|
--root) TARGET_ROOT="$2"; shift 2 ;;
|
|
23
42
|
-*) echo "Unknown flag: $1" >&2; exit 1 ;;
|
|
@@ -33,7 +52,7 @@ while [[ $# -gt 0 ]]; do
|
|
|
33
52
|
done
|
|
34
53
|
|
|
35
54
|
if [[ -z "${VAULT_FILE}" ]]; then
|
|
36
|
-
echo "Usage: bash restore.sh [--force] [--root <path>] <vault-file>" >&2
|
|
55
|
+
echo "Usage: bash restore.sh [--list] [--force] [--root <path>] <vault-file>" >&2
|
|
37
56
|
echo " vault-file: env-vault-*.tar.age | .tar.gpg | .tar.enc" >&2
|
|
38
57
|
exit 1
|
|
39
58
|
fi
|
|
@@ -103,6 +122,45 @@ EXTRACT_DIR="${WORK_DIR}/extracted"
|
|
|
103
122
|
mkdir -p "${EXTRACT_DIR}"
|
|
104
123
|
tar -xf "${TAR_PATH}" -C "${EXTRACT_DIR}"
|
|
105
124
|
|
|
125
|
+
if [[ "${LIST_ONLY}" == "true" ]]; then
|
|
126
|
+
ENV_COUNT=0
|
|
127
|
+
AGENT_PRESENT=0
|
|
128
|
+
AGENT_MISSING=0
|
|
129
|
+
|
|
130
|
+
echo "Vault contents (secret-safe inventory):"
|
|
131
|
+
while IFS= read -r -d '' ENV_FILE; do
|
|
132
|
+
REL_PATH="${ENV_FILE#${EXTRACT_DIR}/}"
|
|
133
|
+
PROJECT_NAME="$(dirname "${REL_PATH}")"
|
|
134
|
+
DEST="${TARGET_ROOT}/${PROJECT_NAME}/.env.local"
|
|
135
|
+
VAR_COUNT=$(grep -cE '^[A-Za-z_][A-Za-z0-9_]*=' "${ENV_FILE}" 2>/dev/null || true)
|
|
136
|
+
VAR_NAMES=$(grep -oE '^[A-Za-z_][A-Za-z0-9_]*' "${ENV_FILE}" 2>/dev/null \
|
|
137
|
+
| grep -v '^$' | sort | paste -sd ',' - || true)
|
|
138
|
+
echo " env: ${PROJECT_NAME}/.env.local -> ${DEST} (${VAR_COUNT} variable(s) [${VAR_NAMES}])"
|
|
139
|
+
(( ENV_COUNT++ )) || true
|
|
140
|
+
done < <(find "${EXTRACT_DIR}" -name ".env.local" -print0)
|
|
141
|
+
|
|
142
|
+
AGENT_AUTH_SRC="${EXTRACT_DIR}/agent-auth"
|
|
143
|
+
echo " agent-auth:"
|
|
144
|
+
for ENTRY in "${AGENT_AUTH_MAP[@]}"; do
|
|
145
|
+
ARCHIVE_NAME="${ENTRY%%:*}"
|
|
146
|
+
DEST_PATH="${ENTRY##*:}"
|
|
147
|
+
SRC_FILE="${AGENT_AUTH_SRC}/${ARCHIVE_NAME}"
|
|
148
|
+
if [[ -f "${SRC_FILE}" ]]; then
|
|
149
|
+
FILE_BYTES=$(wc -c < "${SRC_FILE}" | tr -d ' ')
|
|
150
|
+
echo " present: agent-auth/${ARCHIVE_NAME} -> ${DEST_PATH} (${FILE_BYTES} bytes)"
|
|
151
|
+
(( AGENT_PRESENT++ )) || true
|
|
152
|
+
else
|
|
153
|
+
echo " missing: agent-auth/${ARCHIVE_NAME}"
|
|
154
|
+
(( AGENT_MISSING++ )) || true
|
|
155
|
+
fi
|
|
156
|
+
done
|
|
157
|
+
|
|
158
|
+
echo ""
|
|
159
|
+
echo "List summary: ${ENV_COUNT} .env.local file(s), ${AGENT_PRESENT} agent-auth file(s) present, ${AGENT_MISSING} agent-auth file(s) missing."
|
|
160
|
+
echo "No files were written and no secret values were printed."
|
|
161
|
+
exit 0
|
|
162
|
+
fi
|
|
163
|
+
|
|
106
164
|
# ── restore each .env.local ───────────────────────────────────────────────────
|
|
107
165
|
RESTORED=0
|
|
108
166
|
SKIPPED=0
|
|
@@ -139,11 +197,61 @@ while IFS= read -r -d '' ENV_FILE; do
|
|
|
139
197
|
fi
|
|
140
198
|
done < <(find "${EXTRACT_DIR}" -name ".env.local" -print0)
|
|
141
199
|
|
|
200
|
+
# ── restore agent-auth files ───────────────────────────────────────────────────
|
|
201
|
+
AGENT_RESTORED=0
|
|
202
|
+
AGENT_SKIPPED=0
|
|
203
|
+
AGENT_BACKED_UP=0
|
|
204
|
+
|
|
205
|
+
AGENT_AUTH_SRC="${EXTRACT_DIR}/agent-auth"
|
|
206
|
+
|
|
207
|
+
if [[ -d "${AGENT_AUTH_SRC}" ]]; then
|
|
208
|
+
echo "Restoring agent-auth files…"
|
|
209
|
+
for ENTRY in "${AGENT_AUTH_MAP[@]}"; do
|
|
210
|
+
ARCHIVE_NAME="${ENTRY%%:*}"
|
|
211
|
+
DEST_PATH="${ENTRY##*:}"
|
|
212
|
+
SRC_FILE="${AGENT_AUTH_SRC}/${ARCHIVE_NAME}"
|
|
213
|
+
|
|
214
|
+
if [[ ! -f "${SRC_FILE}" ]]; then
|
|
215
|
+
echo " SKIPPED (not in vault): agent-auth/${ARCHIVE_NAME}"
|
|
216
|
+
(( AGENT_SKIPPED++ )) || true
|
|
217
|
+
continue
|
|
218
|
+
fi
|
|
219
|
+
|
|
220
|
+
DEST_DIR="$(dirname "${DEST_PATH}")"
|
|
221
|
+
mkdir -p "${DEST_DIR}"
|
|
222
|
+
|
|
223
|
+
if [[ -f "${DEST_PATH}" ]]; then
|
|
224
|
+
if [[ "${FORCE}" == "true" ]]; then
|
|
225
|
+
cp "${SRC_FILE}" "${DEST_PATH}"
|
|
226
|
+
echo " RESTORED (overwrite): ${DEST_PATH}"
|
|
227
|
+
(( AGENT_RESTORED++ )) || true
|
|
228
|
+
else
|
|
229
|
+
TS="$(date -u +%Y%m%dT%H%M%SZ)"
|
|
230
|
+
BAK="${DEST_PATH}.bak.${TS}"
|
|
231
|
+
cp "${DEST_PATH}" "${BAK}"
|
|
232
|
+
cp "${SRC_FILE}" "${DEST_PATH}"
|
|
233
|
+
echo " RESTORED (backed up old → $(basename "${BAK}")): ${DEST_PATH}"
|
|
234
|
+
(( AGENT_RESTORED++ )) || true
|
|
235
|
+
(( AGENT_BACKED_UP++ )) || true
|
|
236
|
+
fi
|
|
237
|
+
else
|
|
238
|
+
cp "${SRC_FILE}" "${DEST_PATH}"
|
|
239
|
+
echo " RESTORED (new): ${DEST_PATH}"
|
|
240
|
+
(( AGENT_RESTORED++ )) || true
|
|
241
|
+
fi
|
|
242
|
+
done
|
|
243
|
+
echo ""
|
|
244
|
+
else
|
|
245
|
+
echo "No agent-auth/ directory in vault — skipping agent-auth restore."
|
|
246
|
+
echo ""
|
|
247
|
+
fi
|
|
248
|
+
|
|
142
249
|
echo ""
|
|
143
250
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
144
251
|
echo " Restore summary"
|
|
145
252
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
146
|
-
echo " Restored: ${RESTORED} | Skipped: ${SKIPPED} | Old files backed up: ${BACKED_UP}"
|
|
253
|
+
echo " .env.local — Restored: ${RESTORED} | Skipped: ${SKIPPED} | Old files backed up: ${BACKED_UP}"
|
|
254
|
+
echo " agent-auth — Restored: ${AGENT_RESTORED} | Skipped: ${AGENT_SKIPPED} | Old files backed up: ${AGENT_BACKED_UP}"
|
|
147
255
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
148
256
|
echo ""
|
|
149
|
-
echo "Secrets are now in place. Do not print or share
|
|
257
|
+
echo "Secrets are now in place. Do not print or share secret files."
|
|
@@ -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
|
-
- **Identity plane:** `youmd sync` (Convex ↔ local profile, memories, preferences). Automated via `com.youmd.identity-sync` daemon.
|
|
31
|
+
- **Identity plane:** `youmd sync --daemon` (Convex ↔ local profile, memories, preferences). Automated via `com.youmd.identity-sync` daemon. Daemon mode refreshes local files/skills and skips unsafe lossy pushes instead of forcing over richer server data.
|
|
32
|
+
- **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.
|
|
32
33
|
- **Env-vault plane:** `cli/scripts/env-vault/restore.sh` for secrets (manual, invoked on new machine); also available as `youmd env restore <vault>`.
|
|
33
34
|
|
|
34
35
|
---
|
|
@@ -38,10 +39,11 @@ Cross-machine sync toolkit for Houston Golden's agent skill/stack setup.
|
|
|
38
39
|
```
|
|
39
40
|
cli/scripts/skillstack-sync/
|
|
40
41
|
├── sync.sh Core syncer (bash 3.2 compatible)
|
|
41
|
-
├── install-daemons.sh Installs
|
|
42
|
+
├── install-daemons.sh Installs all resident LaunchAgents
|
|
42
43
|
├── bootstrap-new-mac.sh New machine setup script
|
|
43
44
|
├── com.youmd.skillstack-sync.plist LaunchAgent: runs `youmd stack sync` every 5 min
|
|
44
|
-
├── com.youmd.identity-sync.plist LaunchAgent: runs `youmd sync` every 5 min
|
|
45
|
+
├── com.youmd.identity-sync.plist LaunchAgent: runs `youmd sync --daemon` every 5 min
|
|
46
|
+
├── com.youmd.context-sync.plist LaunchAgent: runs `youmd stack context-sync` every 15 min
|
|
45
47
|
└── README.md This file
|
|
46
48
|
```
|
|
47
49
|
|
|
@@ -90,7 +92,7 @@ GIT_USER_EMAIL="houston@bamf.ai" # commit email (default)
|
|
|
90
92
|
The preferred way is via the CLI:
|
|
91
93
|
|
|
92
94
|
```bash
|
|
93
|
-
youmd stack daemon install # installs
|
|
95
|
+
youmd stack daemon install # installs all resident LaunchAgents
|
|
94
96
|
youmd stack daemon status # check loaded/not-loaded
|
|
95
97
|
youmd stack daemon uninstall # remove plists from ~/Library/LaunchAgents/
|
|
96
98
|
```
|
|
@@ -101,9 +103,10 @@ Or run the raw script directly:
|
|
|
101
103
|
bash cli/scripts/skillstack-sync/install-daemons.sh
|
|
102
104
|
```
|
|
103
105
|
|
|
104
|
-
Installs
|
|
106
|
+
Installs three LaunchAgents:
|
|
105
107
|
- `com.youmd.skillstack-sync` → runs `youmd stack sync`
|
|
106
|
-
- `com.youmd.identity-sync` → runs `youmd sync`
|
|
108
|
+
- `com.youmd.identity-sync` → runs `youmd sync --daemon`
|
|
109
|
+
- `com.youmd.context-sync` → runs `youmd stack context-sync`
|
|
107
110
|
|
|
108
111
|
Check status:
|
|
109
112
|
```bash
|
|
@@ -111,6 +114,7 @@ youmd stack daemon status
|
|
|
111
114
|
# or directly:
|
|
112
115
|
launchctl list com.youmd.skillstack-sync
|
|
113
116
|
launchctl list com.youmd.identity-sync
|
|
117
|
+
launchctl list com.youmd.context-sync
|
|
114
118
|
```
|
|
115
119
|
|
|
116
120
|
Check logs:
|
|
@@ -118,6 +122,7 @@ Check logs:
|
|
|
118
122
|
tail -f ~/.youmd/logs/skillstack-sync.log
|
|
119
123
|
tail -f ~/.youmd/logs/skillstack-sync.out.log
|
|
120
124
|
tail -f ~/.youmd/logs/identity-sync.out.log
|
|
125
|
+
tail -f ~/.youmd/logs/context-sync.log
|
|
121
126
|
```
|
|
122
127
|
|
|
123
128
|
### Uninstall daemons
|
|
@@ -130,8 +135,10 @@ Or manually:
|
|
|
130
135
|
```bash
|
|
131
136
|
launchctl unload ~/Library/LaunchAgents/com.youmd.skillstack-sync.plist
|
|
132
137
|
launchctl unload ~/Library/LaunchAgents/com.youmd.identity-sync.plist
|
|
138
|
+
launchctl unload ~/Library/LaunchAgents/com.youmd.context-sync.plist
|
|
133
139
|
rm ~/Library/LaunchAgents/com.youmd.skillstack-sync.plist
|
|
134
140
|
rm ~/Library/LaunchAgents/com.youmd.identity-sync.plist
|
|
141
|
+
rm ~/Library/LaunchAgents/com.youmd.context-sync.plist
|
|
135
142
|
```
|
|
136
143
|
|
|
137
144
|
---
|
|
@@ -101,14 +101,29 @@ for skill in ${LOOSE_SKILLS}; do
|
|
|
101
101
|
done
|
|
102
102
|
|
|
103
103
|
# ---------------------------------------------------------------------------
|
|
104
|
-
step "5.
|
|
104
|
+
step "5. Restore agent config from agent-shared"
|
|
105
|
+
# ---------------------------------------------------------------------------
|
|
106
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
107
|
+
RESTORE_SCRIPT="${SCRIPT_DIR}/restore-agent-config.sh"
|
|
108
|
+
|
|
109
|
+
if [ -f "${RESTORE_SCRIPT}" ]; then
|
|
110
|
+
info "Running restore-agent-config.sh (backs up existing files, safe to re-run)..."
|
|
111
|
+
bash "${RESTORE_SCRIPT}"
|
|
112
|
+
info "Agent config restored."
|
|
113
|
+
else
|
|
114
|
+
warn "restore-agent-config.sh not found at ${RESTORE_SCRIPT} — skipping agent config restore."
|
|
115
|
+
warn "You can run it manually later once youmd is fully installed:"
|
|
116
|
+
warn " bash ${RESTORE_SCRIPT}"
|
|
117
|
+
fi
|
|
118
|
+
|
|
119
|
+
# ---------------------------------------------------------------------------
|
|
120
|
+
step "6. Reminder: restore secrets"
|
|
105
121
|
# ---------------------------------------------------------------------------
|
|
106
122
|
echo ""
|
|
107
123
|
echo " !! IMPORTANT: Secrets are NOT in git. Restore them separately:"
|
|
108
124
|
echo ""
|
|
109
|
-
echo " If you use the env-vault
|
|
125
|
+
echo " If you use the env-vault:"
|
|
110
126
|
echo " youmd env restore <vault-file> # CLI wrapper (preferred)"
|
|
111
|
-
echo " bash ~/Desktop/CODE_2025/youmd/cli/scripts/env-vault/restore.sh <vault-file>"
|
|
112
127
|
echo ""
|
|
113
128
|
echo " Secrets to restore (set in your shell profile or .env files):"
|
|
114
129
|
echo " OPENROUTER_API_KEY"
|
|
@@ -119,7 +134,7 @@ echo " ANTHROPIC_API_KEY"
|
|
|
119
134
|
echo ""
|
|
120
135
|
|
|
121
136
|
# ---------------------------------------------------------------------------
|
|
122
|
-
step "
|
|
137
|
+
step "7. Next steps"
|
|
123
138
|
# ---------------------------------------------------------------------------
|
|
124
139
|
echo ""
|
|
125
140
|
echo " Bootstrap complete. To activate the auto-sync daemons, run:"
|
|
@@ -127,7 +142,6 @@ echo ""
|
|
|
127
142
|
echo " youmd stack daemon install # preferred (CLI-native)"
|
|
128
143
|
echo ""
|
|
129
144
|
echo " Or run the raw script directly:"
|
|
130
|
-
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
131
145
|
echo " bash ${SCRIPT_DIR}/install-daemons.sh"
|
|
132
146
|
echo ""
|
|
133
147
|
echo " To do a manual sync now:"
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# capture-agent-config.sh — snapshot NON-SECRET agent config into ~/.agent-shared/
|
|
3
|
+
#
|
|
4
|
+
# This captures the agent-behavior config that isn't already in a synced repo —
|
|
5
|
+
# Claude/Codex/Warp settings, slash commands, plugin list, the orphaned
|
|
6
|
+
# ~/.agents skills, and the launchd/cron automations — into the agent-shared
|
|
7
|
+
# repo so they travel across machines. The skillstack-sync daemon then commits +
|
|
8
|
+
# pushes agent-shared, and `youmd machine setup`/restore applies them on a new Mac.
|
|
9
|
+
#
|
|
10
|
+
# SECRETS NEVER GO HERE. agent-shared is a git repo. Live secrets (codex
|
|
11
|
+
# auth.json, cursor mcp.json, ~/.claude.json BAMF token, .env.local) travel via
|
|
12
|
+
# the ENCRYPTED env-vault instead. This script captures only files confirmed to
|
|
13
|
+
# be secret-free, and a final guard greps the staged output for secret patterns
|
|
14
|
+
# and ABORTS if any are found (nothing is left in agent-shared on abort).
|
|
15
|
+
#
|
|
16
|
+
# bash 3.2 / BSD safe. Idempotent. --dry-run to preview.
|
|
17
|
+
|
|
18
|
+
set -euo pipefail
|
|
19
|
+
|
|
20
|
+
AGENT_SHARED="${HOME}/.agent-shared"
|
|
21
|
+
DEST="${AGENT_SHARED}/agent-config"
|
|
22
|
+
LOG_DIR="${HOME}/.youmd/logs"
|
|
23
|
+
LOG_FILE="${LOG_DIR}/capture-agent-config.log"
|
|
24
|
+
|
|
25
|
+
DRY_RUN=0
|
|
26
|
+
for arg in "$@"; do
|
|
27
|
+
case "$arg" in
|
|
28
|
+
--dry-run) DRY_RUN=1 ;;
|
|
29
|
+
*) echo "Unknown flag: $arg" >&2; exit 1 ;;
|
|
30
|
+
esac
|
|
31
|
+
done
|
|
32
|
+
|
|
33
|
+
mkdir -p "${LOG_DIR}"
|
|
34
|
+
log() { local ts; ts="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"; echo "[${ts}] $*"; echo "[${ts}] $*" >> "${LOG_FILE}"; }
|
|
35
|
+
is_dry() { [ "${DRY_RUN}" -eq 1 ]; }
|
|
36
|
+
|
|
37
|
+
if [ ! -d "${AGENT_SHARED}/.git" ]; then
|
|
38
|
+
log "ERROR: ${AGENT_SHARED} is not a git repo — run machine setup first."
|
|
39
|
+
exit 1
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
# copy_in <src> <dest-subpath> — copy a file/dir into the staging dest if it exists
|
|
43
|
+
copy_in() {
|
|
44
|
+
local src="$1" rel="$2" target
|
|
45
|
+
target="${DEST}/${rel}"
|
|
46
|
+
if [ ! -e "${src}" ]; then return 0; fi
|
|
47
|
+
if is_dry; then log "DRY would capture ${src} → agent-config/${rel}"; return 0; fi
|
|
48
|
+
mkdir -p "$(dirname "${target}")"
|
|
49
|
+
if [ -d "${src}" ]; then
|
|
50
|
+
rsync -a --delete "${src}/" "${target}/"
|
|
51
|
+
else
|
|
52
|
+
cp "${src}" "${target}"
|
|
53
|
+
fi
|
|
54
|
+
log "captured ${src} → agent-config/${rel}"
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
log "=== capture-agent-config START ($([ "${DRY_RUN}" -eq 1 ] && echo DRY || echo LIVE)) ==="
|
|
58
|
+
|
|
59
|
+
# ── Claude config (settings have no raw secrets; ~/.claude.json is EXCLUDED — vaulted) ──
|
|
60
|
+
copy_in "${HOME}/.claude/settings.json" "claude/settings.json"
|
|
61
|
+
copy_in "${HOME}/.claude/settings.local.json" "claude/settings.local.json"
|
|
62
|
+
copy_in "${HOME}/.claude/commands" "claude/commands"
|
|
63
|
+
copy_in "${HOME}/.claude/mcp.json" "claude/mcp.json"
|
|
64
|
+
copy_in "${HOME}/.claude/plugins/installed_plugins.json" "claude/plugins/installed_plugins.json"
|
|
65
|
+
|
|
66
|
+
# ── Codex config (config.toml only; auth.json is EXCLUDED — vaulted) ──
|
|
67
|
+
copy_in "${HOME}/.codex/config.toml" "codex/config.toml"
|
|
68
|
+
|
|
69
|
+
# ── Warp (no secrets) ──
|
|
70
|
+
copy_in "${HOME}/.warp/settings.toml" "warp/settings.toml"
|
|
71
|
+
copy_in "${HOME}/.warp/keybindings.yaml" "warp/keybindings.yaml"
|
|
72
|
+
|
|
73
|
+
# ── Orphaned ~/.agents skills (no repo of their own today) ──
|
|
74
|
+
copy_in "${HOME}/.agents/skills/find-skills" "agents-skills/find-skills"
|
|
75
|
+
copy_in "${HOME}/.agents/skills/ui-ux-pro-max" "agents-skills/ui-ux-pro-max"
|
|
76
|
+
|
|
77
|
+
# ── Automations: launchd plists (HOME-templated) + crontab snapshot ──
|
|
78
|
+
capture_plist() {
|
|
79
|
+
local label="$1" src="${HOME}/Library/LaunchAgents/$1.plist" target="${DEST}/automations/launchd/$1.plist"
|
|
80
|
+
if [ ! -f "${src}" ]; then return 0; fi
|
|
81
|
+
if is_dry; then log "DRY would capture plist ${label} (HOME-templated)"; return 0; fi
|
|
82
|
+
mkdir -p "$(dirname "${target}")"
|
|
83
|
+
sed "s|${HOME}|__HOME__|g" "${src}" > "${target}"
|
|
84
|
+
log "captured plist ${label} → agent-config/automations/launchd/${label}.plist"
|
|
85
|
+
}
|
|
86
|
+
capture_plist "com.youmd.skillstack-sync"
|
|
87
|
+
capture_plist "com.youmd.identity-sync"
|
|
88
|
+
capture_plist "com.youmd.context-sync"
|
|
89
|
+
capture_plist "com.houstongolden.agent-runtime-guard"
|
|
90
|
+
|
|
91
|
+
if ! is_dry; then
|
|
92
|
+
mkdir -p "${DEST}/automations"
|
|
93
|
+
crontab -l 2>/dev/null > "${DEST}/automations/crontab.txt" || true
|
|
94
|
+
log "captured crontab → agent-config/automations/crontab.txt"
|
|
95
|
+
fi
|
|
96
|
+
|
|
97
|
+
# ── SECRET-LEAK GUARD — abort if anything captured looks like a live secret ──
|
|
98
|
+
if ! is_dry && [ -d "${DEST}" ]; then
|
|
99
|
+
# Match real secret token shapes; allow bare key NAMES (KEY=) which are fine.
|
|
100
|
+
HITS="$(grep -rIlE 'sk-ant-[A-Za-z0-9_-]{20}|sk-[A-Za-z0-9]{32}|ghp_[A-Za-z0-9]{30}|gho_[A-Za-z0-9]{30}|Bearer [A-Za-z0-9._-]{20}|AKIA[0-9A-Z]{16}|xox[baprs]-[A-Za-z0-9-]{10}' "${DEST}" 2>/dev/null || true)"
|
|
101
|
+
if [ -n "${HITS}" ]; then
|
|
102
|
+
log "ABORT: possible secret(s) found in captured config — removing capture, nothing committed:"
|
|
103
|
+
log "${HITS}"
|
|
104
|
+
rm -rf "${DEST}"
|
|
105
|
+
exit 1
|
|
106
|
+
fi
|
|
107
|
+
log "secret-leak guard: clean (no live secret patterns in captured config)"
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
log "=== capture-agent-config DONE ==="
|
|
@@ -0,0 +1,38 @@
|
|
|
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.context-sync</string>
|
|
7
|
+
|
|
8
|
+
<key>ProgramArguments</key>
|
|
9
|
+
<array>
|
|
10
|
+
<string>/bin/zsh</string>
|
|
11
|
+
<string>-lc</string>
|
|
12
|
+
<string>youmd stack context-sync</string>
|
|
13
|
+
</array>
|
|
14
|
+
|
|
15
|
+
<key>StartInterval</key>
|
|
16
|
+
<integer>900</integer>
|
|
17
|
+
|
|
18
|
+
<key>RunAtLoad</key>
|
|
19
|
+
<true/>
|
|
20
|
+
|
|
21
|
+
<key>KeepAlive</key>
|
|
22
|
+
<false/>
|
|
23
|
+
|
|
24
|
+
<key>StandardOutPath</key>
|
|
25
|
+
<string>__HOME__/.youmd/logs/context-sync.out.log</string>
|
|
26
|
+
|
|
27
|
+
<key>StandardErrorPath</key>
|
|
28
|
+
<string>__HOME__/.youmd/logs/context-sync.err.log</string>
|
|
29
|
+
|
|
30
|
+
<key>EnvironmentVariables</key>
|
|
31
|
+
<dict>
|
|
32
|
+
<key>HOME</key>
|
|
33
|
+
<string>__HOME__</string>
|
|
34
|
+
<key>PATH</key>
|
|
35
|
+
<string>/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
|
|
36
|
+
</dict>
|
|
37
|
+
</dict>
|
|
38
|
+
</plist>
|