youmd 0.6.27 → 0.7.1
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/env.d.ts +9 -0
- package/dist/commands/env.d.ts.map +1 -0
- package/dist/commands/env.js +105 -0
- package/dist/commands/env.js.map +1 -0
- package/dist/commands/machine.d.ts +2 -0
- package/dist/commands/machine.d.ts.map +1 -0
- package/dist/commands/machine.js +71 -0
- package/dist/commands/machine.js.map +1 -0
- package/dist/commands/stack.d.ts.map +1 -1
- package/dist/commands/stack.js +98 -0
- package/dist/commands/stack.js.map +1 -1
- package/dist/index.js +53 -0
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
- package/scripts/check-version-exists.mjs +40 -0
- package/scripts/env-vault/README.md +123 -0
- package/scripts/env-vault/backup.sh +167 -0
- package/scripts/env-vault/restore.sh +149 -0
- package/scripts/skillstack-sync/README.md +166 -0
- package/scripts/skillstack-sync/bootstrap-new-mac.sh +141 -0
- package/scripts/skillstack-sync/com.youmd.identity-sync.plist +36 -0
- package/scripts/skillstack-sync/com.youmd.skillstack-sync.plist +38 -0
- package/scripts/skillstack-sync/install-daemons.sh +75 -0
- package/scripts/skillstack-sync/sync.sh +320 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# skillstack-sync
|
|
2
|
+
|
|
3
|
+
Cross-machine sync toolkit for Houston Golden's agent skill/stack setup.
|
|
4
|
+
|
|
5
|
+
## What this syncs
|
|
6
|
+
|
|
7
|
+
### Sync plane: Skills & Stacks (this toolkit)
|
|
8
|
+
|
|
9
|
+
| What | How | Notes |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| `~/.agent-shared` | git push/pull to `houstongolden/agent-shared` | Canonical shared agent layer: AGENTS.md, learnings, preferences, STACK-MAP |
|
|
12
|
+
| `~/.claude/scistack` | git push/pull to `Hubify-Projects/scistack` | Science skills: astrostack, hubstack, extensions |
|
|
13
|
+
| 4 loose skills (see below) | rsync into agent-shared repo, then back out | Ride along in agent-shared without their own repo |
|
|
14
|
+
|
|
15
|
+
**Loose skills synced via agent-shared/claude-skills/:**
|
|
16
|
+
- `agent-runtime-guard`
|
|
17
|
+
- `agent-stack-sync`
|
|
18
|
+
- `continue`
|
|
19
|
+
- `skill-governor`
|
|
20
|
+
|
|
21
|
+
### What does NOT sync here
|
|
22
|
+
|
|
23
|
+
| What | Why |
|
|
24
|
+
|---|---|
|
|
25
|
+
| `~/.claude/skills/gstack/` | Tracks upstream `garrytan/gstack` — updated via `/gstack-upgrade`, read-only to us |
|
|
26
|
+
| Project files / code | Synced via their own project repos (youmd, bamfaiapp, etc.) |
|
|
27
|
+
| Secrets / env vars | Use the env-vault (`cli/scripts/env-vault/`) |
|
|
28
|
+
|
|
29
|
+
### Complementary sync planes
|
|
30
|
+
|
|
31
|
+
- **Identity plane:** `youmd sync` (Convex ↔ local profile, memories, preferences). Automated via `com.youmd.identity-sync` daemon.
|
|
32
|
+
- **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
|
+
---
|
|
35
|
+
|
|
36
|
+
## Files
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
cli/scripts/skillstack-sync/
|
|
40
|
+
├── sync.sh Core syncer (bash 3.2 compatible)
|
|
41
|
+
├── install-daemons.sh Installs both LaunchAgents
|
|
42
|
+
├── bootstrap-new-mac.sh New machine setup script
|
|
43
|
+
├── 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
|
+
└── README.md This file
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Sync logic (sync.sh)
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
1. Mirror loose skills: ~/.claude/skills/<name>/ → ~/.agent-shared/claude-skills/<name>/
|
|
54
|
+
2. Sync ~/.agent-shared:
|
|
55
|
+
a. git add -A + commit "auto-sync: <host> <timestamp>" if dirty
|
|
56
|
+
b. git pull --no-rebase --no-edit (merge)
|
|
57
|
+
→ on conflict: abort merge, log LOUD warning, skip push, continue
|
|
58
|
+
c. git push
|
|
59
|
+
3. Sync ~/.claude/scistack: same a/b/c sequence
|
|
60
|
+
4. Reverse-mirror loose skills: ~/.agent-shared/claude-skills/<name>/ → ~/.claude/skills/<name>/
|
|
61
|
+
→ backs up existing local copy to <name>.bak.<timestamp> before overwriting
|
|
62
|
+
→ skips if no changes detected
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
All actions logged to `~/.youmd/logs/skillstack-sync.log`.
|
|
66
|
+
|
|
67
|
+
### Flags
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
youmd stack sync # live sync (all repos + loose skills)
|
|
71
|
+
youmd stack sync --dry-run # log what WOULD happen, write nothing
|
|
72
|
+
|
|
73
|
+
# or run the script directly:
|
|
74
|
+
./sync.sh
|
|
75
|
+
./sync.sh --dry-run
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Env overrides
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
SKILLSTACK_REPOS="/path/to/repo1 /path/to/repo2" # override repo list
|
|
82
|
+
GIT_USER_NAME="Houston Golden" # commit author (default)
|
|
83
|
+
GIT_USER_EMAIL="houston@bamf.ai" # commit email (default)
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Daemon setup (existing machine)
|
|
89
|
+
|
|
90
|
+
The preferred way is via the CLI:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
youmd stack daemon install # installs both LaunchAgents
|
|
94
|
+
youmd stack daemon status # check loaded/not-loaded
|
|
95
|
+
youmd stack daemon uninstall # remove plists from ~/Library/LaunchAgents/
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Or run the raw script directly:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
bash cli/scripts/skillstack-sync/install-daemons.sh
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Installs two LaunchAgents that fire every 300 seconds (5 minutes):
|
|
105
|
+
- `com.youmd.skillstack-sync` → runs `youmd stack sync`
|
|
106
|
+
- `com.youmd.identity-sync` → runs `youmd sync`
|
|
107
|
+
|
|
108
|
+
Check status:
|
|
109
|
+
```bash
|
|
110
|
+
youmd stack daemon status
|
|
111
|
+
# or directly:
|
|
112
|
+
launchctl list com.youmd.skillstack-sync
|
|
113
|
+
launchctl list com.youmd.identity-sync
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Check logs:
|
|
117
|
+
```bash
|
|
118
|
+
tail -f ~/.youmd/logs/skillstack-sync.log
|
|
119
|
+
tail -f ~/.youmd/logs/skillstack-sync.out.log
|
|
120
|
+
tail -f ~/.youmd/logs/identity-sync.out.log
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Uninstall daemons
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
youmd stack daemon uninstall
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Or manually:
|
|
130
|
+
```bash
|
|
131
|
+
launchctl unload ~/Library/LaunchAgents/com.youmd.skillstack-sync.plist
|
|
132
|
+
launchctl unload ~/Library/LaunchAgents/com.youmd.identity-sync.plist
|
|
133
|
+
rm ~/Library/LaunchAgents/com.youmd.skillstack-sync.plist
|
|
134
|
+
rm ~/Library/LaunchAgents/com.youmd.identity-sync.plist
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## New Mac setup
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
# 1. Install youmd CLI
|
|
143
|
+
curl -fsSL https://you.md/install.sh | bash
|
|
144
|
+
|
|
145
|
+
# 2. Clone this repo (youmd)
|
|
146
|
+
git clone https://github.com/houstongolden/youmd ~/Desktop/CODE_2025/youmd
|
|
147
|
+
|
|
148
|
+
# 3. Run bootstrap (clones agent-shared + scistack)
|
|
149
|
+
bash ~/Desktop/CODE_2025/youmd/cli/scripts/skillstack-sync/bootstrap-new-mac.sh
|
|
150
|
+
|
|
151
|
+
# 4. Restore secrets from env-vault (manual step — see env-vault/README)
|
|
152
|
+
|
|
153
|
+
# 5. Activate daemons
|
|
154
|
+
youmd stack daemon install
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
The bootstrap script is idempotent (safe to re-run).
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Compatibility
|
|
162
|
+
|
|
163
|
+
Scripts target macOS with:
|
|
164
|
+
- bash 3.2.57 (default macOS shell)
|
|
165
|
+
- BSD coreutils (no GNU `mapfile`, no `mktemp --suffix`, BSD `date`/`find`/`rsync`)
|
|
166
|
+
- No external tools installed beyond: `git`, `rsync`, `bash` (all stock on macOS)
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# bootstrap-new-mac.sh — set up a new Mac with Houston's agent skill/stack layer
|
|
3
|
+
#
|
|
4
|
+
# Safe to re-run (idempotent). Prints all steps before executing them.
|
|
5
|
+
# Does NOT run launchctl, does NOT push git, does NOT install anything
|
|
6
|
+
# beyond youmd CLI and git clones.
|
|
7
|
+
#
|
|
8
|
+
# After this script: run install-daemons.sh to activate the sync daemons.
|
|
9
|
+
#
|
|
10
|
+
# Usage: bash bootstrap-new-mac.sh
|
|
11
|
+
|
|
12
|
+
set -euo pipefail
|
|
13
|
+
|
|
14
|
+
AGENT_SHARED="${HOME}/.agent-shared"
|
|
15
|
+
SCISTACK="${HOME}/.claude/scistack"
|
|
16
|
+
CLAUDE_SKILLS="${HOME}/.claude/skills"
|
|
17
|
+
|
|
18
|
+
LOOSE_SKILLS="agent-runtime-guard agent-stack-sync continue skill-governor"
|
|
19
|
+
|
|
20
|
+
AGENT_SHARED_REPO="https://github.com/houstongolden/agent-shared.git"
|
|
21
|
+
SCISTACK_REPO="https://github.com/Hubify-Projects/scistack.git"
|
|
22
|
+
|
|
23
|
+
step() {
|
|
24
|
+
echo ""
|
|
25
|
+
echo "===> $*"
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
info() {
|
|
29
|
+
echo " $*"
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
warn() {
|
|
33
|
+
echo " WARN: $*"
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
# ---------------------------------------------------------------------------
|
|
37
|
+
step "1. Install youmd CLI"
|
|
38
|
+
# ---------------------------------------------------------------------------
|
|
39
|
+
if command -v youmd >/dev/null 2>&1; then
|
|
40
|
+
info "youmd already installed: $(youmd --version 2>/dev/null || echo '(version unknown)')"
|
|
41
|
+
else
|
|
42
|
+
info "Installing youmd via official install script..."
|
|
43
|
+
curl -fsSL https://you.md/install.sh | bash
|
|
44
|
+
info "youmd installed."
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
# ---------------------------------------------------------------------------
|
|
48
|
+
step "2. Clone agent-shared repo → ${AGENT_SHARED}"
|
|
49
|
+
# ---------------------------------------------------------------------------
|
|
50
|
+
if [ -d "${AGENT_SHARED}/.git" ]; then
|
|
51
|
+
info "Already present: ${AGENT_SHARED} — skipping clone."
|
|
52
|
+
else
|
|
53
|
+
info "Cloning ${AGENT_SHARED_REPO} → ${AGENT_SHARED}"
|
|
54
|
+
mkdir -p "$(dirname "${AGENT_SHARED}")"
|
|
55
|
+
# Use gh if available for credential handling; fall back to git
|
|
56
|
+
if command -v gh >/dev/null 2>&1; then
|
|
57
|
+
gh repo clone houstongolden/agent-shared "${AGENT_SHARED}"
|
|
58
|
+
else
|
|
59
|
+
git clone "${AGENT_SHARED_REPO}" "${AGENT_SHARED}"
|
|
60
|
+
fi
|
|
61
|
+
info "Cloned agent-shared."
|
|
62
|
+
fi
|
|
63
|
+
|
|
64
|
+
# ---------------------------------------------------------------------------
|
|
65
|
+
step "3. Clone scistack repo → ${SCISTACK}"
|
|
66
|
+
# ---------------------------------------------------------------------------
|
|
67
|
+
if [ -d "${SCISTACK}/.git" ]; then
|
|
68
|
+
info "Already present: ${SCISTACK} — skipping clone."
|
|
69
|
+
else
|
|
70
|
+
info "Cloning ${SCISTACK_REPO} → ${SCISTACK}"
|
|
71
|
+
mkdir -p "$(dirname "${SCISTACK}")"
|
|
72
|
+
if command -v gh >/dev/null 2>&1; then
|
|
73
|
+
gh repo clone Hubify-Projects/scistack "${SCISTACK}"
|
|
74
|
+
else
|
|
75
|
+
git clone "${SCISTACK_REPO}" "${SCISTACK}"
|
|
76
|
+
fi
|
|
77
|
+
info "Cloned scistack."
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
# ---------------------------------------------------------------------------
|
|
81
|
+
step "4. Restore loose skills from agent-shared/claude-skills/ → ~/.claude/skills/"
|
|
82
|
+
# ---------------------------------------------------------------------------
|
|
83
|
+
mkdir -p "${CLAUDE_SKILLS}"
|
|
84
|
+
|
|
85
|
+
for skill in ${LOOSE_SKILLS}; do
|
|
86
|
+
src="${AGENT_SHARED}/claude-skills/${skill}"
|
|
87
|
+
dst="${CLAUDE_SKILLS}/${skill}"
|
|
88
|
+
|
|
89
|
+
if [ ! -d "${src}" ]; then
|
|
90
|
+
warn "Loose skill '${skill}' not found in agent-shared yet — will be populated on first sync."
|
|
91
|
+
continue
|
|
92
|
+
fi
|
|
93
|
+
|
|
94
|
+
if [ -d "${dst}" ]; then
|
|
95
|
+
info "Skill '${skill}' already exists at ${dst} — skipping (run sync.sh to update)."
|
|
96
|
+
else
|
|
97
|
+
info "Restoring skill '${skill}' → ${dst}"
|
|
98
|
+
rsync -a "${src}/" "${dst}/"
|
|
99
|
+
info "Restored ${skill}."
|
|
100
|
+
fi
|
|
101
|
+
done
|
|
102
|
+
|
|
103
|
+
# ---------------------------------------------------------------------------
|
|
104
|
+
step "5. Reminder: restore secrets"
|
|
105
|
+
# ---------------------------------------------------------------------------
|
|
106
|
+
echo ""
|
|
107
|
+
echo " !! IMPORTANT: Secrets are NOT in git. Restore them separately:"
|
|
108
|
+
echo ""
|
|
109
|
+
echo " If you use the env-vault (~/Desktop/CODE_2025/youmd/cli/scripts/env-vault/):"
|
|
110
|
+
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
|
+
echo ""
|
|
113
|
+
echo " Secrets to restore (set in your shell profile or .env files):"
|
|
114
|
+
echo " OPENROUTER_API_KEY"
|
|
115
|
+
echo " CONVEX_DEPLOY_KEY"
|
|
116
|
+
echo " YOUMD_API_KEY"
|
|
117
|
+
echo " GH_TOKEN (or: gh auth login)"
|
|
118
|
+
echo " ANTHROPIC_API_KEY"
|
|
119
|
+
echo ""
|
|
120
|
+
|
|
121
|
+
# ---------------------------------------------------------------------------
|
|
122
|
+
step "6. Next steps"
|
|
123
|
+
# ---------------------------------------------------------------------------
|
|
124
|
+
echo ""
|
|
125
|
+
echo " Bootstrap complete. To activate the auto-sync daemons, run:"
|
|
126
|
+
echo ""
|
|
127
|
+
echo " youmd stack daemon install # preferred (CLI-native)"
|
|
128
|
+
echo ""
|
|
129
|
+
echo " Or run the raw script directly:"
|
|
130
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
131
|
+
echo " bash ${SCRIPT_DIR}/install-daemons.sh"
|
|
132
|
+
echo ""
|
|
133
|
+
echo " To do a manual sync now:"
|
|
134
|
+
echo " youmd stack sync # preferred (CLI-native)"
|
|
135
|
+
echo ""
|
|
136
|
+
echo " To do a dry-run first (recommended):"
|
|
137
|
+
echo " youmd stack sync --dry-run"
|
|
138
|
+
echo ""
|
|
139
|
+
echo "================================================================"
|
|
140
|
+
echo "Bootstrap done. Welcome to the new machine."
|
|
141
|
+
echo "================================================================"
|
|
@@ -0,0 +1,36 @@
|
|
|
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.identity-sync</string>
|
|
7
|
+
|
|
8
|
+
<key>ProgramArguments</key>
|
|
9
|
+
<array>
|
|
10
|
+
<string>/bin/zsh</string>
|
|
11
|
+
<string>-lc</string>
|
|
12
|
+
<string>youmd sync</string>
|
|
13
|
+
</array>
|
|
14
|
+
|
|
15
|
+
<key>StartInterval</key>
|
|
16
|
+
<integer>300</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/identity-sync.out.log</string>
|
|
26
|
+
|
|
27
|
+
<key>StandardErrorPath</key>
|
|
28
|
+
<string>__HOME__/.youmd/logs/identity-sync.err.log</string>
|
|
29
|
+
|
|
30
|
+
<key>EnvironmentVariables</key>
|
|
31
|
+
<dict>
|
|
32
|
+
<key>HOME</key>
|
|
33
|
+
<string>__HOME__</string>
|
|
34
|
+
</dict>
|
|
35
|
+
</dict>
|
|
36
|
+
</plist>
|
|
@@ -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.skillstack-sync</string>
|
|
7
|
+
|
|
8
|
+
<key>ProgramArguments</key>
|
|
9
|
+
<array>
|
|
10
|
+
<string>/bin/zsh</string>
|
|
11
|
+
<string>-lc</string>
|
|
12
|
+
<string>youmd stack sync</string>
|
|
13
|
+
</array>
|
|
14
|
+
|
|
15
|
+
<key>StartInterval</key>
|
|
16
|
+
<integer>300</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/skillstack-sync.out.log</string>
|
|
26
|
+
|
|
27
|
+
<key>StandardErrorPath</key>
|
|
28
|
+
<string>__HOME__/.youmd/logs/skillstack-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:/usr/bin:/bin:/usr/sbin:/sbin</string>
|
|
36
|
+
</dict>
|
|
37
|
+
</dict>
|
|
38
|
+
</plist>
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# install-daemons.sh — install skillstack-sync and identity-sync LaunchAgents
|
|
3
|
+
#
|
|
4
|
+
# Idempotent: safe to re-run. Unloads before reloading.
|
|
5
|
+
# Does NOT need sudo — LaunchAgents run as the current user.
|
|
6
|
+
#
|
|
7
|
+
# Usage: ./install-daemons.sh
|
|
8
|
+
|
|
9
|
+
set -euo pipefail
|
|
10
|
+
|
|
11
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
12
|
+
LAUNCH_AGENTS_DIR="${HOME}/Library/LaunchAgents"
|
|
13
|
+
LOG_DIR="${HOME}/.youmd/logs"
|
|
14
|
+
|
|
15
|
+
PLISTS="com.youmd.skillstack-sync com.youmd.identity-sync"
|
|
16
|
+
|
|
17
|
+
echo "==> Creating log directory: ${LOG_DIR}"
|
|
18
|
+
mkdir -p "${LOG_DIR}"
|
|
19
|
+
|
|
20
|
+
echo "==> Creating LaunchAgents directory: ${LAUNCH_AGENTS_DIR}"
|
|
21
|
+
mkdir -p "${LAUNCH_AGENTS_DIR}"
|
|
22
|
+
|
|
23
|
+
for label in ${PLISTS}; do
|
|
24
|
+
src="${SCRIPT_DIR}/${label}.plist"
|
|
25
|
+
dst="${LAUNCH_AGENTS_DIR}/${label}.plist"
|
|
26
|
+
|
|
27
|
+
if [ ! -f "${src}" ]; then
|
|
28
|
+
echo "ERROR: Source plist not found: ${src}" >&2
|
|
29
|
+
exit 1
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
echo ""
|
|
33
|
+
echo "--- Installing ${label} ---"
|
|
34
|
+
|
|
35
|
+
# Substitute __HOME__ placeholder with actual home dir
|
|
36
|
+
# BSD sed: use a temp file, no -i '' in-place on stdin
|
|
37
|
+
local_tmp="$(mktemp -t youmd_plist)"
|
|
38
|
+
sed "s|__HOME__|${HOME}|g" "${src}" > "${local_tmp}"
|
|
39
|
+
|
|
40
|
+
# Unload existing daemon if loaded (ignore errors — it may not be loaded)
|
|
41
|
+
if launchctl list "${label}" >/dev/null 2>&1; then
|
|
42
|
+
echo " Unloading existing ${label}..."
|
|
43
|
+
launchctl unload "${dst}" 2>/dev/null || true
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
echo " Copying ${label}.plist → ${LAUNCH_AGENTS_DIR}/"
|
|
47
|
+
cp "${local_tmp}" "${dst}"
|
|
48
|
+
rm -f "${local_tmp}"
|
|
49
|
+
|
|
50
|
+
echo " Loading ${label}..."
|
|
51
|
+
launchctl load -w "${dst}"
|
|
52
|
+
|
|
53
|
+
echo " Loaded: ${label}"
|
|
54
|
+
done
|
|
55
|
+
|
|
56
|
+
echo ""
|
|
57
|
+
echo "================================================================"
|
|
58
|
+
echo "Both daemons installed and running."
|
|
59
|
+
echo ""
|
|
60
|
+
echo "Log files:"
|
|
61
|
+
echo " ${LOG_DIR}/skillstack-sync.log (combined sync log)"
|
|
62
|
+
echo " ${LOG_DIR}/skillstack-sync.out.log (daemon stdout)"
|
|
63
|
+
echo " ${LOG_DIR}/skillstack-sync.err.log (daemon stderr)"
|
|
64
|
+
echo " ${LOG_DIR}/identity-sync.out.log (youmd sync stdout)"
|
|
65
|
+
echo " ${LOG_DIR}/identity-sync.err.log (youmd sync stderr)"
|
|
66
|
+
echo ""
|
|
67
|
+
echo "Check daemon status:"
|
|
68
|
+
echo " launchctl list com.youmd.skillstack-sync"
|
|
69
|
+
echo " launchctl list com.youmd.identity-sync"
|
|
70
|
+
echo ""
|
|
71
|
+
echo "To uninstall:"
|
|
72
|
+
for label in ${PLISTS}; do
|
|
73
|
+
echo " launchctl unload ${LAUNCH_AGENTS_DIR}/${label}.plist && rm ${LAUNCH_AGENTS_DIR}/${label}.plist"
|
|
74
|
+
done
|
|
75
|
+
echo "================================================================"
|