@bvdm/delano 0.1.0
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/HANDBOOK.md +1511 -0
- package/README.md +122 -0
- package/assets/install-manifest.json +102 -0
- package/assets/payload/.agents/README.md +12 -0
- package/assets/payload/.agents/adapters/claude/README.md +5 -0
- package/assets/payload/.agents/adapters/codex/README.md +5 -0
- package/assets/payload/.agents/adapters/opencode/README.md +5 -0
- package/assets/payload/.agents/adapters/pi/README.md +5 -0
- package/assets/payload/.agents/common/README.md +3 -0
- package/assets/payload/.agents/hooks/README.md +11 -0
- package/assets/payload/.agents/hooks/bash-worktree-fix.sh +7 -0
- package/assets/payload/.agents/hooks/post-tool-logger.js +18 -0
- package/assets/payload/.agents/hooks/session-tracker.js +17 -0
- package/assets/payload/.agents/hooks/user-prompt-logger.js +18 -0
- package/assets/payload/.agents/logs/.gitkeep +0 -0
- package/assets/payload/.agents/logs/schema.md +42 -0
- package/assets/payload/.agents/rules/README.md +12 -0
- package/assets/payload/.agents/rules/agent-coordination.md +5 -0
- package/assets/payload/.agents/rules/datetime.md +5 -0
- package/assets/payload/.agents/rules/frontmatter-operations.md +6 -0
- package/assets/payload/.agents/rules/github-operations.md +5 -0
- package/assets/payload/.agents/rules/path-standards.md +5 -0
- package/assets/payload/.agents/rules/test-execution.md +5 -0
- package/assets/payload/.agents/rules/worktree-operations.md +5 -0
- package/assets/payload/.agents/scripts/README.md +31 -0
- package/assets/payload/.agents/scripts/check-path-standards.sh +26 -0
- package/assets/payload/.agents/scripts/fix-path-standards.sh +14 -0
- package/assets/payload/.agents/scripts/git-sparse-download.sh +162 -0
- package/assets/payload/.agents/scripts/log-event.js +33 -0
- package/assets/payload/.agents/scripts/log-event.sh +5 -0
- package/assets/payload/.agents/scripts/pm/blocked.sh +36 -0
- package/assets/payload/.agents/scripts/pm/epic-list.sh +34 -0
- package/assets/payload/.agents/scripts/pm/in-progress.sh +36 -0
- package/assets/payload/.agents/scripts/pm/init.sh +139 -0
- package/assets/payload/.agents/scripts/pm/next.sh +110 -0
- package/assets/payload/.agents/scripts/pm/prd-list.sh +34 -0
- package/assets/payload/.agents/scripts/pm/search.sh +13 -0
- package/assets/payload/.agents/scripts/pm/standup.sh +19 -0
- package/assets/payload/.agents/scripts/pm/status.sh +61 -0
- package/assets/payload/.agents/scripts/pm/validate.sh +309 -0
- package/assets/payload/.agents/scripts/query-log.sh +57 -0
- package/assets/payload/.agents/scripts/test-and-log.sh +28 -0
- package/assets/payload/.agents/skills/.gitkeep +0 -0
- package/assets/payload/.agents/skills/README.md +23 -0
- package/assets/payload/.agents/skills/breakdown-skill/SKILL.md +40 -0
- package/assets/payload/.agents/skills/breakdown-skill/references/runbook.md +16 -0
- package/assets/payload/.agents/skills/breakdown-skill/templates/ambiguity-report.md +11 -0
- package/assets/payload/.agents/skills/breakdown-skill/templates/task-batch-summary.md +11 -0
- package/assets/payload/.agents/skills/closeout-skill/SKILL.md +42 -0
- package/assets/payload/.agents/skills/closeout-skill/references/runbook.md +16 -0
- package/assets/payload/.agents/skills/closeout-skill/templates/closure-checklist.md +7 -0
- package/assets/payload/.agents/skills/closeout-skill/templates/outcome-review.md +11 -0
- package/assets/payload/.agents/skills/discovery-skill/SKILL.md +44 -0
- package/assets/payload/.agents/skills/discovery-skill/references/runbook.md +14 -0
- package/assets/payload/.agents/skills/discovery-skill/templates/clarification-questions.md +18 -0
- package/assets/payload/.agents/skills/discovery-skill/templates/discovery-summary.md +14 -0
- package/assets/payload/.agents/skills/execution-skill/SKILL.md +42 -0
- package/assets/payload/.agents/skills/execution-skill/references/runbook.md +16 -0
- package/assets/payload/.agents/skills/execution-skill/templates/blocker-update.md +13 -0
- package/assets/payload/.agents/skills/execution-skill/templates/stream-update.md +9 -0
- package/assets/payload/.agents/skills/learning-skill/SKILL.md +41 -0
- package/assets/payload/.agents/skills/learning-skill/references/runbook.md +13 -0
- package/assets/payload/.agents/skills/learning-skill/templates/improvement-backlog.md +10 -0
- package/assets/payload/.agents/skills/learning-skill/templates/retrospective.md +11 -0
- package/assets/payload/.agents/skills/planning-skill/SKILL.md +40 -0
- package/assets/payload/.agents/skills/planning-skill/references/runbook.md +15 -0
- package/assets/payload/.agents/skills/planning-skill/templates/architecture-decision.md +15 -0
- package/assets/payload/.agents/skills/planning-skill/templates/workstream-definition.md +13 -0
- package/assets/payload/.agents/skills/quality-skill/SKILL.md +40 -0
- package/assets/payload/.agents/skills/quality-skill/references/runbook.md +14 -0
- package/assets/payload/.agents/skills/quality-skill/templates/gate-decision.md +10 -0
- package/assets/payload/.agents/skills/quality-skill/templates/quality-evidence.md +16 -0
- package/assets/payload/.agents/skills/sync-skill/SKILL.md +41 -0
- package/assets/payload/.agents/skills/sync-skill/references/runbook.md +17 -0
- package/assets/payload/.agents/skills/sync-skill/templates/conflict-resolution-actions.md +10 -0
- package/assets/payload/.agents/skills/sync-skill/templates/drift-report.md +14 -0
- package/assets/payload/.delano/README.md +7 -0
- package/assets/payload/.gitattributes +14 -0
- package/assets/payload/.project/context/README.md +15 -0
- package/assets/payload/.project/context/gui-testing.md +20 -0
- package/assets/payload/.project/context/product-context.md +17 -0
- package/assets/payload/.project/context/progress.md +23 -0
- package/assets/payload/.project/context/project-brief.md +13 -0
- package/assets/payload/.project/context/project-overview.md +14 -0
- package/assets/payload/.project/context/project-structure.md +24 -0
- package/assets/payload/.project/context/project-style-guide.md +17 -0
- package/assets/payload/.project/context/system-patterns.md +22 -0
- package/assets/payload/.project/context/tech-context.md +19 -0
- package/assets/payload/.project/projects/.gitkeep +0 -0
- package/assets/payload/.project/registry/linear-map.json +6 -0
- package/assets/payload/.project/registry/migration-map.json +5 -0
- package/assets/payload/.project/templates/completion-summary.md +16 -0
- package/assets/payload/.project/templates/plan.md +30 -0
- package/assets/payload/.project/templates/progress-update.md +20 -0
- package/assets/payload/.project/templates/spec.md +42 -0
- package/assets/payload/.project/templates/task.md +33 -0
- package/assets/payload/.project/templates/workstream.md +19 -0
- package/assets/payload/HANDBOOK.md +1511 -0
- package/assets/payload/install-delano.sh +311 -0
- package/bin/delano.js +13 -0
- package/install-delano.sh +311 -0
- package/package.json +26 -0
- package/src/cli/commands/install.js +57 -0
- package/src/cli/commands/wrapper.js +26 -0
- package/src/cli/index.js +97 -0
- package/src/cli/lib/errors.js +11 -0
- package/src/cli/lib/install.js +261 -0
- package/src/cli/lib/pm.js +29 -0
- package/src/cli/lib/runtime.js +122 -0
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
REPO_URL="${DELANO_REPO_URL:-https://github.com/MajesteitBart/delano.git}"
|
|
5
|
+
TARGET_DIR="$(pwd)"
|
|
6
|
+
BRANCH=""
|
|
7
|
+
FORCE=false
|
|
8
|
+
ASSUME_YES=false
|
|
9
|
+
AGENTS_RAW=""
|
|
10
|
+
|
|
11
|
+
usage() {
|
|
12
|
+
cat <<USAGE
|
|
13
|
+
Delano legacy installer bridge (interactive by default)
|
|
14
|
+
|
|
15
|
+
Usage:
|
|
16
|
+
$0 [options]
|
|
17
|
+
|
|
18
|
+
Options:
|
|
19
|
+
--repo <url> Delano git repository URL
|
|
20
|
+
--target <dir> Target directory (default: current directory)
|
|
21
|
+
--branch <name> Branch/tag to install (default: remote default branch)
|
|
22
|
+
--agents <list> Comma-separated agents: claude,codex,opencode,pi
|
|
23
|
+
--force Overwrite existing files without prompting
|
|
24
|
+
--yes Assume yes for prompts
|
|
25
|
+
-h, --help Show this help
|
|
26
|
+
|
|
27
|
+
Notes:
|
|
28
|
+
- This script remains the shell-first migration bridge while @bvdm/delano matures.
|
|
29
|
+
- Prefer 'delano install' from @bvdm/delano for the allowlist-driven, conflict-first v1 install path when that package flow is available.
|
|
30
|
+
USAGE
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
log() { printf '%s\n' "$*"; }
|
|
34
|
+
warn() { printf '⚠️ %s\n' "$*" >&2; }
|
|
35
|
+
err() { printf '❌ %s\n' "$*" >&2; }
|
|
36
|
+
|
|
37
|
+
confirm() {
|
|
38
|
+
local prompt="$1"
|
|
39
|
+
if [[ "$ASSUME_YES" == "true" ]]; then
|
|
40
|
+
return 0
|
|
41
|
+
fi
|
|
42
|
+
read -r -p "$prompt [y/N]: " reply
|
|
43
|
+
[[ "$reply" =~ ^[Yy]$ ]]
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
parse_agents() {
|
|
47
|
+
local raw="$1"
|
|
48
|
+
local -n out_ref=$2
|
|
49
|
+
out_ref=()
|
|
50
|
+
|
|
51
|
+
IFS=',' read -r -a parts <<< "$raw"
|
|
52
|
+
for p in "${parts[@]}"; do
|
|
53
|
+
local a
|
|
54
|
+
a="$(echo "$p" | tr '[:upper:]' '[:lower:]' | xargs)"
|
|
55
|
+
case "$a" in
|
|
56
|
+
claude|codex|opencode|pi)
|
|
57
|
+
out_ref+=("$a")
|
|
58
|
+
;;
|
|
59
|
+
"") ;;
|
|
60
|
+
*)
|
|
61
|
+
err "Unknown agent: $a"
|
|
62
|
+
exit 1
|
|
63
|
+
;;
|
|
64
|
+
esac
|
|
65
|
+
done
|
|
66
|
+
|
|
67
|
+
# unique preserve order
|
|
68
|
+
local -A seen=()
|
|
69
|
+
local unique=()
|
|
70
|
+
for a in "${out_ref[@]}"; do
|
|
71
|
+
if [[ -z "${seen[$a]:-}" ]]; then
|
|
72
|
+
seen[$a]=1
|
|
73
|
+
unique+=("$a")
|
|
74
|
+
fi
|
|
75
|
+
done
|
|
76
|
+
out_ref=("${unique[@]}")
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
select_agents_interactive() {
|
|
80
|
+
cat <<MENU
|
|
81
|
+
Which coding agents do you use? (multi-select)
|
|
82
|
+
|
|
83
|
+
1) Claude Code
|
|
84
|
+
2) Codex CLI
|
|
85
|
+
3) OpenCode
|
|
86
|
+
4) Pi coding agent
|
|
87
|
+
|
|
88
|
+
Enter one or more numbers, comma-separated (example: 1,2)
|
|
89
|
+
MENU
|
|
90
|
+
|
|
91
|
+
read -r -p "Selection: " pick
|
|
92
|
+
pick="$(echo "$pick" | tr -d ' ')"
|
|
93
|
+
if [[ -z "$pick" ]]; then
|
|
94
|
+
err "No agents selected"
|
|
95
|
+
exit 1
|
|
96
|
+
fi
|
|
97
|
+
|
|
98
|
+
local mapped=()
|
|
99
|
+
IFS=',' read -r -a nums <<< "$pick"
|
|
100
|
+
for n in "${nums[@]}"; do
|
|
101
|
+
case "$n" in
|
|
102
|
+
1) mapped+=("claude") ;;
|
|
103
|
+
2) mapped+=("codex") ;;
|
|
104
|
+
3) mapped+=("opencode") ;;
|
|
105
|
+
4) mapped+=("pi") ;;
|
|
106
|
+
*) err "Invalid selection: $n"; exit 1 ;;
|
|
107
|
+
esac
|
|
108
|
+
done
|
|
109
|
+
|
|
110
|
+
# unique preserve order
|
|
111
|
+
local -A seen=()
|
|
112
|
+
AGENTS=()
|
|
113
|
+
for a in "${mapped[@]}"; do
|
|
114
|
+
if [[ -z "${seen[$a]:-}" ]]; then
|
|
115
|
+
seen[$a]=1
|
|
116
|
+
AGENTS+=("$a")
|
|
117
|
+
fi
|
|
118
|
+
done
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
while [[ $# -gt 0 ]]; do
|
|
122
|
+
case "$1" in
|
|
123
|
+
--repo)
|
|
124
|
+
REPO_URL="$2"; shift 2 ;;
|
|
125
|
+
--target)
|
|
126
|
+
TARGET_DIR="$2"; shift 2 ;;
|
|
127
|
+
--branch)
|
|
128
|
+
BRANCH="$2"; shift 2 ;;
|
|
129
|
+
--agents)
|
|
130
|
+
AGENTS_RAW="$2"; shift 2 ;;
|
|
131
|
+
--force)
|
|
132
|
+
FORCE=true; shift ;;
|
|
133
|
+
--yes)
|
|
134
|
+
ASSUME_YES=true; shift ;;
|
|
135
|
+
-h|--help)
|
|
136
|
+
usage; exit 0 ;;
|
|
137
|
+
*)
|
|
138
|
+
err "Unknown argument: $1"
|
|
139
|
+
usage
|
|
140
|
+
exit 1 ;;
|
|
141
|
+
esac
|
|
142
|
+
done
|
|
143
|
+
|
|
144
|
+
if ! command -v git >/dev/null 2>&1; then
|
|
145
|
+
err "git is required"
|
|
146
|
+
exit 1
|
|
147
|
+
fi
|
|
148
|
+
|
|
149
|
+
mkdir -p "$TARGET_DIR"
|
|
150
|
+
TARGET_DIR="$(cd "$TARGET_DIR" && pwd)"
|
|
151
|
+
|
|
152
|
+
AGENTS=()
|
|
153
|
+
if [[ -n "$AGENTS_RAW" ]]; then
|
|
154
|
+
parse_agents "$AGENTS_RAW" AGENTS
|
|
155
|
+
else
|
|
156
|
+
select_agents_interactive
|
|
157
|
+
fi
|
|
158
|
+
|
|
159
|
+
if [[ ${#AGENTS[@]} -eq 0 ]]; then
|
|
160
|
+
err "No agents selected"
|
|
161
|
+
exit 1
|
|
162
|
+
fi
|
|
163
|
+
|
|
164
|
+
CORE_PATHS=(
|
|
165
|
+
"HANDBOOK.md"
|
|
166
|
+
"AGENTS.md"
|
|
167
|
+
".project"
|
|
168
|
+
".delano"
|
|
169
|
+
".agents/README.md"
|
|
170
|
+
".agents/common"
|
|
171
|
+
".agents/scripts"
|
|
172
|
+
".agents/rules"
|
|
173
|
+
".agents/hooks"
|
|
174
|
+
".agents/skills"
|
|
175
|
+
".agents/logs"
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
declare -A ADAPTER_PATHS
|
|
179
|
+
ADAPTER_PATHS[claude]=".agents/adapters/claude CLAUDE.md"
|
|
180
|
+
ADAPTER_PATHS[codex]=".agents/adapters/codex CODEX.md"
|
|
181
|
+
ADAPTER_PATHS[opencode]=".agents/adapters/opencode OPENCODE.md"
|
|
182
|
+
ADAPTER_PATHS[pi]=".agents/adapters/pi PI.md"
|
|
183
|
+
|
|
184
|
+
paths=("${CORE_PATHS[@]}")
|
|
185
|
+
for a in "${AGENTS[@]}"; do
|
|
186
|
+
# shellcheck disable=SC2206
|
|
187
|
+
extra=( ${ADAPTER_PATHS[$a]} )
|
|
188
|
+
paths+=("${extra[@]}")
|
|
189
|
+
done
|
|
190
|
+
|
|
191
|
+
# unique paths preserve order
|
|
192
|
+
unique_paths=()
|
|
193
|
+
declare -A path_seen=()
|
|
194
|
+
for p in "${paths[@]}"; do
|
|
195
|
+
if [[ -z "${path_seen[$p]:-}" ]]; then
|
|
196
|
+
path_seen[$p]=1
|
|
197
|
+
unique_paths+=("$p")
|
|
198
|
+
fi
|
|
199
|
+
done
|
|
200
|
+
|
|
201
|
+
if [[ -z "$BRANCH" ]]; then
|
|
202
|
+
BRANCH="$(git ls-remote --symref "$REPO_URL" HEAD 2>/dev/null | awk '/^ref:/ {sub("refs/heads/","",$2); print $2; exit}')"
|
|
203
|
+
BRANCH="${BRANCH:-main}"
|
|
204
|
+
fi
|
|
205
|
+
|
|
206
|
+
log "Installing Delano from: $REPO_URL"
|
|
207
|
+
log "Branch: $BRANCH"
|
|
208
|
+
log "Target: $TARGET_DIR"
|
|
209
|
+
log "Agents: ${AGENTS[*]}"
|
|
210
|
+
log "Mode: legacy bridge installer"
|
|
211
|
+
log ""
|
|
212
|
+
|
|
213
|
+
tmp="$(mktemp -d)"
|
|
214
|
+
cleanup() {
|
|
215
|
+
rm -rf "$tmp"
|
|
216
|
+
}
|
|
217
|
+
trap cleanup EXIT
|
|
218
|
+
|
|
219
|
+
git -C "$tmp" init -q
|
|
220
|
+
git -C "$tmp" remote add origin "$REPO_URL"
|
|
221
|
+
git -C "$tmp" config advice.detachedHead false
|
|
222
|
+
|
|
223
|
+
if git -C "$tmp" sparse-checkout init --cone >/dev/null 2>&1; then
|
|
224
|
+
git -C "$tmp" sparse-checkout set "${unique_paths[@]}" >/dev/null 2>&1 || true
|
|
225
|
+
else
|
|
226
|
+
mkdir -p "$tmp/.git/info"
|
|
227
|
+
: > "$tmp/.git/info/sparse-checkout"
|
|
228
|
+
for p in "${unique_paths[@]}"; do
|
|
229
|
+
printf '%s\n' "$p" >> "$tmp/.git/info/sparse-checkout"
|
|
230
|
+
printf '%s/**\n' "$p" >> "$tmp/.git/info/sparse-checkout"
|
|
231
|
+
done
|
|
232
|
+
git -C "$tmp" config core.sparseCheckout true
|
|
233
|
+
fi
|
|
234
|
+
|
|
235
|
+
if ! git -C "$tmp" fetch --depth 1 origin "$BRANCH" >/dev/null 2>&1; then
|
|
236
|
+
err "Could not fetch branch '$BRANCH' from $REPO_URL"
|
|
237
|
+
exit 1
|
|
238
|
+
fi
|
|
239
|
+
git -C "$tmp" checkout -q FETCH_HEAD
|
|
240
|
+
|
|
241
|
+
copy_item() {
|
|
242
|
+
local rel="$1"
|
|
243
|
+
local src="$tmp/$rel"
|
|
244
|
+
local dst="$TARGET_DIR/$rel"
|
|
245
|
+
|
|
246
|
+
if [[ ! -e "$src" && ! -L "$src" ]]; then
|
|
247
|
+
warn "Path not found in source repo, skipping: $rel"
|
|
248
|
+
return 0
|
|
249
|
+
fi
|
|
250
|
+
|
|
251
|
+
if [[ -e "$dst" || -L "$dst" ]]; then
|
|
252
|
+
if [[ "$FORCE" == "true" ]]; then
|
|
253
|
+
rm -rf "$dst"
|
|
254
|
+
else
|
|
255
|
+
if confirm "Overwrite existing '$rel'?"; then
|
|
256
|
+
rm -rf "$dst"
|
|
257
|
+
else
|
|
258
|
+
warn "Skipped existing: $rel"
|
|
259
|
+
return 0
|
|
260
|
+
fi
|
|
261
|
+
fi
|
|
262
|
+
fi
|
|
263
|
+
|
|
264
|
+
mkdir -p "$(dirname "$dst")"
|
|
265
|
+
if [[ -d "$src" && ! -L "$src" ]]; then
|
|
266
|
+
cp -a "$src" "$(dirname "$dst")/"
|
|
267
|
+
else
|
|
268
|
+
cp -a "$src" "$dst"
|
|
269
|
+
fi
|
|
270
|
+
|
|
271
|
+
log "✓ Installed: $rel"
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
for rel in "${unique_paths[@]}"; do
|
|
275
|
+
copy_item "$rel"
|
|
276
|
+
done
|
|
277
|
+
|
|
278
|
+
# Compatibility symlink for runtime scripts
|
|
279
|
+
if [[ -e "$TARGET_DIR/.agents" ]]; then
|
|
280
|
+
if [[ -L "$TARGET_DIR/.claude" ]]; then
|
|
281
|
+
current_target="$(readlink "$TARGET_DIR/.claude" || true)"
|
|
282
|
+
if [[ "$current_target" != ".agents" ]]; then
|
|
283
|
+
if [[ "$FORCE" == "true" ]] || confirm "Replace existing .claude symlink target '$current_target'?"; then
|
|
284
|
+
rm -f "$TARGET_DIR/.claude"
|
|
285
|
+
fi
|
|
286
|
+
fi
|
|
287
|
+
elif [[ -e "$TARGET_DIR/.claude" ]]; then
|
|
288
|
+
if [[ "$FORCE" == "true" ]] || confirm "Replace existing .claude directory/file with symlink?"; then
|
|
289
|
+
rm -rf "$TARGET_DIR/.claude"
|
|
290
|
+
fi
|
|
291
|
+
fi
|
|
292
|
+
|
|
293
|
+
if [[ ! -e "$TARGET_DIR/.claude" && ! -L "$TARGET_DIR/.claude" ]]; then
|
|
294
|
+
if (cd "$TARGET_DIR" && ln -s .agents .claude) 2>/dev/null; then
|
|
295
|
+
log "✓ Created compatibility symlink: .claude -> .agents"
|
|
296
|
+
else
|
|
297
|
+
warn "Could not create symlink (.claude). Falling back to directory copy."
|
|
298
|
+
cp -a "$TARGET_DIR/.agents" "$TARGET_DIR/.claude"
|
|
299
|
+
fi
|
|
300
|
+
fi
|
|
301
|
+
else
|
|
302
|
+
warn "Runtime missing at .agents, skipped .claude compatibility link"
|
|
303
|
+
fi
|
|
304
|
+
|
|
305
|
+
log ""
|
|
306
|
+
log "Done."
|
|
307
|
+
log "Next steps:"
|
|
308
|
+
log "1) Read HANDBOOK.md"
|
|
309
|
+
log "2) Read AGENTS.md"
|
|
310
|
+
log "3) Validate scaffold: bash .agents/scripts/pm/validate.sh"
|
|
311
|
+
log "4) Prefer @bvdm/delano for the conservative v1 install path when you adopt the npm CLI flow."
|
package/bin/delano.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { run } = require("../src/cli");
|
|
4
|
+
|
|
5
|
+
run(process.argv.slice(2))
|
|
6
|
+
.then((exitCode) => {
|
|
7
|
+
process.exitCode = exitCode;
|
|
8
|
+
})
|
|
9
|
+
.catch((error) => {
|
|
10
|
+
const message = error && error.message ? error.message : String(error);
|
|
11
|
+
console.error(message);
|
|
12
|
+
process.exitCode = typeof error?.exitCode === "number" ? error.exitCode : 1;
|
|
13
|
+
});
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
REPO_URL="${DELANO_REPO_URL:-https://github.com/MajesteitBart/delano.git}"
|
|
5
|
+
TARGET_DIR="$(pwd)"
|
|
6
|
+
BRANCH=""
|
|
7
|
+
FORCE=false
|
|
8
|
+
ASSUME_YES=false
|
|
9
|
+
AGENTS_RAW=""
|
|
10
|
+
|
|
11
|
+
usage() {
|
|
12
|
+
cat <<USAGE
|
|
13
|
+
Delano legacy installer bridge (interactive by default)
|
|
14
|
+
|
|
15
|
+
Usage:
|
|
16
|
+
$0 [options]
|
|
17
|
+
|
|
18
|
+
Options:
|
|
19
|
+
--repo <url> Delano git repository URL
|
|
20
|
+
--target <dir> Target directory (default: current directory)
|
|
21
|
+
--branch <name> Branch/tag to install (default: remote default branch)
|
|
22
|
+
--agents <list> Comma-separated agents: claude,codex,opencode,pi
|
|
23
|
+
--force Overwrite existing files without prompting
|
|
24
|
+
--yes Assume yes for prompts
|
|
25
|
+
-h, --help Show this help
|
|
26
|
+
|
|
27
|
+
Notes:
|
|
28
|
+
- This script remains the shell-first migration bridge while @bvdm/delano matures.
|
|
29
|
+
- Prefer 'delano install' from @bvdm/delano for the allowlist-driven, conflict-first v1 install path when that package flow is available.
|
|
30
|
+
USAGE
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
log() { printf '%s\n' "$*"; }
|
|
34
|
+
warn() { printf '⚠️ %s\n' "$*" >&2; }
|
|
35
|
+
err() { printf '❌ %s\n' "$*" >&2; }
|
|
36
|
+
|
|
37
|
+
confirm() {
|
|
38
|
+
local prompt="$1"
|
|
39
|
+
if [[ "$ASSUME_YES" == "true" ]]; then
|
|
40
|
+
return 0
|
|
41
|
+
fi
|
|
42
|
+
read -r -p "$prompt [y/N]: " reply
|
|
43
|
+
[[ "$reply" =~ ^[Yy]$ ]]
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
parse_agents() {
|
|
47
|
+
local raw="$1"
|
|
48
|
+
local -n out_ref=$2
|
|
49
|
+
out_ref=()
|
|
50
|
+
|
|
51
|
+
IFS=',' read -r -a parts <<< "$raw"
|
|
52
|
+
for p in "${parts[@]}"; do
|
|
53
|
+
local a
|
|
54
|
+
a="$(echo "$p" | tr '[:upper:]' '[:lower:]' | xargs)"
|
|
55
|
+
case "$a" in
|
|
56
|
+
claude|codex|opencode|pi)
|
|
57
|
+
out_ref+=("$a")
|
|
58
|
+
;;
|
|
59
|
+
"") ;;
|
|
60
|
+
*)
|
|
61
|
+
err "Unknown agent: $a"
|
|
62
|
+
exit 1
|
|
63
|
+
;;
|
|
64
|
+
esac
|
|
65
|
+
done
|
|
66
|
+
|
|
67
|
+
# unique preserve order
|
|
68
|
+
local -A seen=()
|
|
69
|
+
local unique=()
|
|
70
|
+
for a in "${out_ref[@]}"; do
|
|
71
|
+
if [[ -z "${seen[$a]:-}" ]]; then
|
|
72
|
+
seen[$a]=1
|
|
73
|
+
unique+=("$a")
|
|
74
|
+
fi
|
|
75
|
+
done
|
|
76
|
+
out_ref=("${unique[@]}")
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
select_agents_interactive() {
|
|
80
|
+
cat <<MENU
|
|
81
|
+
Which coding agents do you use? (multi-select)
|
|
82
|
+
|
|
83
|
+
1) Claude Code
|
|
84
|
+
2) Codex CLI
|
|
85
|
+
3) OpenCode
|
|
86
|
+
4) Pi coding agent
|
|
87
|
+
|
|
88
|
+
Enter one or more numbers, comma-separated (example: 1,2)
|
|
89
|
+
MENU
|
|
90
|
+
|
|
91
|
+
read -r -p "Selection: " pick
|
|
92
|
+
pick="$(echo "$pick" | tr -d ' ')"
|
|
93
|
+
if [[ -z "$pick" ]]; then
|
|
94
|
+
err "No agents selected"
|
|
95
|
+
exit 1
|
|
96
|
+
fi
|
|
97
|
+
|
|
98
|
+
local mapped=()
|
|
99
|
+
IFS=',' read -r -a nums <<< "$pick"
|
|
100
|
+
for n in "${nums[@]}"; do
|
|
101
|
+
case "$n" in
|
|
102
|
+
1) mapped+=("claude") ;;
|
|
103
|
+
2) mapped+=("codex") ;;
|
|
104
|
+
3) mapped+=("opencode") ;;
|
|
105
|
+
4) mapped+=("pi") ;;
|
|
106
|
+
*) err "Invalid selection: $n"; exit 1 ;;
|
|
107
|
+
esac
|
|
108
|
+
done
|
|
109
|
+
|
|
110
|
+
# unique preserve order
|
|
111
|
+
local -A seen=()
|
|
112
|
+
AGENTS=()
|
|
113
|
+
for a in "${mapped[@]}"; do
|
|
114
|
+
if [[ -z "${seen[$a]:-}" ]]; then
|
|
115
|
+
seen[$a]=1
|
|
116
|
+
AGENTS+=("$a")
|
|
117
|
+
fi
|
|
118
|
+
done
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
while [[ $# -gt 0 ]]; do
|
|
122
|
+
case "$1" in
|
|
123
|
+
--repo)
|
|
124
|
+
REPO_URL="$2"; shift 2 ;;
|
|
125
|
+
--target)
|
|
126
|
+
TARGET_DIR="$2"; shift 2 ;;
|
|
127
|
+
--branch)
|
|
128
|
+
BRANCH="$2"; shift 2 ;;
|
|
129
|
+
--agents)
|
|
130
|
+
AGENTS_RAW="$2"; shift 2 ;;
|
|
131
|
+
--force)
|
|
132
|
+
FORCE=true; shift ;;
|
|
133
|
+
--yes)
|
|
134
|
+
ASSUME_YES=true; shift ;;
|
|
135
|
+
-h|--help)
|
|
136
|
+
usage; exit 0 ;;
|
|
137
|
+
*)
|
|
138
|
+
err "Unknown argument: $1"
|
|
139
|
+
usage
|
|
140
|
+
exit 1 ;;
|
|
141
|
+
esac
|
|
142
|
+
done
|
|
143
|
+
|
|
144
|
+
if ! command -v git >/dev/null 2>&1; then
|
|
145
|
+
err "git is required"
|
|
146
|
+
exit 1
|
|
147
|
+
fi
|
|
148
|
+
|
|
149
|
+
mkdir -p "$TARGET_DIR"
|
|
150
|
+
TARGET_DIR="$(cd "$TARGET_DIR" && pwd)"
|
|
151
|
+
|
|
152
|
+
AGENTS=()
|
|
153
|
+
if [[ -n "$AGENTS_RAW" ]]; then
|
|
154
|
+
parse_agents "$AGENTS_RAW" AGENTS
|
|
155
|
+
else
|
|
156
|
+
select_agents_interactive
|
|
157
|
+
fi
|
|
158
|
+
|
|
159
|
+
if [[ ${#AGENTS[@]} -eq 0 ]]; then
|
|
160
|
+
err "No agents selected"
|
|
161
|
+
exit 1
|
|
162
|
+
fi
|
|
163
|
+
|
|
164
|
+
CORE_PATHS=(
|
|
165
|
+
"HANDBOOK.md"
|
|
166
|
+
"AGENTS.md"
|
|
167
|
+
".project"
|
|
168
|
+
".delano"
|
|
169
|
+
".agents/README.md"
|
|
170
|
+
".agents/common"
|
|
171
|
+
".agents/scripts"
|
|
172
|
+
".agents/rules"
|
|
173
|
+
".agents/hooks"
|
|
174
|
+
".agents/skills"
|
|
175
|
+
".agents/logs"
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
declare -A ADAPTER_PATHS
|
|
179
|
+
ADAPTER_PATHS[claude]=".agents/adapters/claude CLAUDE.md"
|
|
180
|
+
ADAPTER_PATHS[codex]=".agents/adapters/codex CODEX.md"
|
|
181
|
+
ADAPTER_PATHS[opencode]=".agents/adapters/opencode OPENCODE.md"
|
|
182
|
+
ADAPTER_PATHS[pi]=".agents/adapters/pi PI.md"
|
|
183
|
+
|
|
184
|
+
paths=("${CORE_PATHS[@]}")
|
|
185
|
+
for a in "${AGENTS[@]}"; do
|
|
186
|
+
# shellcheck disable=SC2206
|
|
187
|
+
extra=( ${ADAPTER_PATHS[$a]} )
|
|
188
|
+
paths+=("${extra[@]}")
|
|
189
|
+
done
|
|
190
|
+
|
|
191
|
+
# unique paths preserve order
|
|
192
|
+
unique_paths=()
|
|
193
|
+
declare -A path_seen=()
|
|
194
|
+
for p in "${paths[@]}"; do
|
|
195
|
+
if [[ -z "${path_seen[$p]:-}" ]]; then
|
|
196
|
+
path_seen[$p]=1
|
|
197
|
+
unique_paths+=("$p")
|
|
198
|
+
fi
|
|
199
|
+
done
|
|
200
|
+
|
|
201
|
+
if [[ -z "$BRANCH" ]]; then
|
|
202
|
+
BRANCH="$(git ls-remote --symref "$REPO_URL" HEAD 2>/dev/null | awk '/^ref:/ {sub("refs/heads/","",$2); print $2; exit}')"
|
|
203
|
+
BRANCH="${BRANCH:-main}"
|
|
204
|
+
fi
|
|
205
|
+
|
|
206
|
+
log "Installing Delano from: $REPO_URL"
|
|
207
|
+
log "Branch: $BRANCH"
|
|
208
|
+
log "Target: $TARGET_DIR"
|
|
209
|
+
log "Agents: ${AGENTS[*]}"
|
|
210
|
+
log "Mode: legacy bridge installer"
|
|
211
|
+
log ""
|
|
212
|
+
|
|
213
|
+
tmp="$(mktemp -d)"
|
|
214
|
+
cleanup() {
|
|
215
|
+
rm -rf "$tmp"
|
|
216
|
+
}
|
|
217
|
+
trap cleanup EXIT
|
|
218
|
+
|
|
219
|
+
git -C "$tmp" init -q
|
|
220
|
+
git -C "$tmp" remote add origin "$REPO_URL"
|
|
221
|
+
git -C "$tmp" config advice.detachedHead false
|
|
222
|
+
|
|
223
|
+
if git -C "$tmp" sparse-checkout init --cone >/dev/null 2>&1; then
|
|
224
|
+
git -C "$tmp" sparse-checkout set "${unique_paths[@]}" >/dev/null 2>&1 || true
|
|
225
|
+
else
|
|
226
|
+
mkdir -p "$tmp/.git/info"
|
|
227
|
+
: > "$tmp/.git/info/sparse-checkout"
|
|
228
|
+
for p in "${unique_paths[@]}"; do
|
|
229
|
+
printf '%s\n' "$p" >> "$tmp/.git/info/sparse-checkout"
|
|
230
|
+
printf '%s/**\n' "$p" >> "$tmp/.git/info/sparse-checkout"
|
|
231
|
+
done
|
|
232
|
+
git -C "$tmp" config core.sparseCheckout true
|
|
233
|
+
fi
|
|
234
|
+
|
|
235
|
+
if ! git -C "$tmp" fetch --depth 1 origin "$BRANCH" >/dev/null 2>&1; then
|
|
236
|
+
err "Could not fetch branch '$BRANCH' from $REPO_URL"
|
|
237
|
+
exit 1
|
|
238
|
+
fi
|
|
239
|
+
git -C "$tmp" checkout -q FETCH_HEAD
|
|
240
|
+
|
|
241
|
+
copy_item() {
|
|
242
|
+
local rel="$1"
|
|
243
|
+
local src="$tmp/$rel"
|
|
244
|
+
local dst="$TARGET_DIR/$rel"
|
|
245
|
+
|
|
246
|
+
if [[ ! -e "$src" && ! -L "$src" ]]; then
|
|
247
|
+
warn "Path not found in source repo, skipping: $rel"
|
|
248
|
+
return 0
|
|
249
|
+
fi
|
|
250
|
+
|
|
251
|
+
if [[ -e "$dst" || -L "$dst" ]]; then
|
|
252
|
+
if [[ "$FORCE" == "true" ]]; then
|
|
253
|
+
rm -rf "$dst"
|
|
254
|
+
else
|
|
255
|
+
if confirm "Overwrite existing '$rel'?"; then
|
|
256
|
+
rm -rf "$dst"
|
|
257
|
+
else
|
|
258
|
+
warn "Skipped existing: $rel"
|
|
259
|
+
return 0
|
|
260
|
+
fi
|
|
261
|
+
fi
|
|
262
|
+
fi
|
|
263
|
+
|
|
264
|
+
mkdir -p "$(dirname "$dst")"
|
|
265
|
+
if [[ -d "$src" && ! -L "$src" ]]; then
|
|
266
|
+
cp -a "$src" "$(dirname "$dst")/"
|
|
267
|
+
else
|
|
268
|
+
cp -a "$src" "$dst"
|
|
269
|
+
fi
|
|
270
|
+
|
|
271
|
+
log "✓ Installed: $rel"
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
for rel in "${unique_paths[@]}"; do
|
|
275
|
+
copy_item "$rel"
|
|
276
|
+
done
|
|
277
|
+
|
|
278
|
+
# Compatibility symlink for runtime scripts
|
|
279
|
+
if [[ -e "$TARGET_DIR/.agents" ]]; then
|
|
280
|
+
if [[ -L "$TARGET_DIR/.claude" ]]; then
|
|
281
|
+
current_target="$(readlink "$TARGET_DIR/.claude" || true)"
|
|
282
|
+
if [[ "$current_target" != ".agents" ]]; then
|
|
283
|
+
if [[ "$FORCE" == "true" ]] || confirm "Replace existing .claude symlink target '$current_target'?"; then
|
|
284
|
+
rm -f "$TARGET_DIR/.claude"
|
|
285
|
+
fi
|
|
286
|
+
fi
|
|
287
|
+
elif [[ -e "$TARGET_DIR/.claude" ]]; then
|
|
288
|
+
if [[ "$FORCE" == "true" ]] || confirm "Replace existing .claude directory/file with symlink?"; then
|
|
289
|
+
rm -rf "$TARGET_DIR/.claude"
|
|
290
|
+
fi
|
|
291
|
+
fi
|
|
292
|
+
|
|
293
|
+
if [[ ! -e "$TARGET_DIR/.claude" && ! -L "$TARGET_DIR/.claude" ]]; then
|
|
294
|
+
if (cd "$TARGET_DIR" && ln -s .agents .claude) 2>/dev/null; then
|
|
295
|
+
log "✓ Created compatibility symlink: .claude -> .agents"
|
|
296
|
+
else
|
|
297
|
+
warn "Could not create symlink (.claude). Falling back to directory copy."
|
|
298
|
+
cp -a "$TARGET_DIR/.agents" "$TARGET_DIR/.claude"
|
|
299
|
+
fi
|
|
300
|
+
fi
|
|
301
|
+
else
|
|
302
|
+
warn "Runtime missing at .agents, skipped .claude compatibility link"
|
|
303
|
+
fi
|
|
304
|
+
|
|
305
|
+
log ""
|
|
306
|
+
log "Done."
|
|
307
|
+
log "Next steps:"
|
|
308
|
+
log "1) Read HANDBOOK.md"
|
|
309
|
+
log "2) Read AGENTS.md"
|
|
310
|
+
log "3) Validate scaffold: bash .agents/scripts/pm/validate.sh"
|
|
311
|
+
log "4) Prefer @bvdm/delano for the conservative v1 install path when you adopt the npm CLI flow."
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bvdm/delano",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Thin npm CLI for the Delano delivery runtime.",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"bin": {
|
|
7
|
+
"delano": "bin/delano.js"
|
|
8
|
+
},
|
|
9
|
+
"type": "commonjs",
|
|
10
|
+
"engines": {
|
|
11
|
+
"node": ">=18"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"bin/",
|
|
15
|
+
"src/",
|
|
16
|
+
"assets/",
|
|
17
|
+
"README.md",
|
|
18
|
+
"HANDBOOK.md",
|
|
19
|
+
"install-delano.sh"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build:assets": "node scripts/build-npm-assets.mjs",
|
|
23
|
+
"prepack": "npm run build:assets",
|
|
24
|
+
"test": "node --test"
|
|
25
|
+
}
|
|
26
|
+
}
|