-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy pathMakefile
More file actions
415 lines (346 loc) Β· 23.4 KB
/
Copy pathMakefile
File metadata and controls
415 lines (346 loc) Β· 23.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
# ==============================================================================
# EdgeCrab β Makefile
#
# Quick start:
# make build # release binary
# make test # run all Rust tests
# make ci # full CI gate (fmt + lint + test + SDKs)
# make test-python # Python SDK tests
# make test-node # Node.js SDK tests
# make test-sdks # all SDK tests
# make site-dev # start Astro docs site in dev mode
# make site-build # build Astro docs site for production
# make site-preview # preview the production build locally
# make site-deploy # trigger live GitHub Pages deployment
# ==============================================================================
.DEFAULT_GOAL := help
.PHONY: help \
build build-debug build-fast build-native build-termux dev run run-release check fmt fmt-check lint test test-lsp test-web-search-e2e ci \
install install-fast install-native uninstall \
test-python test-node test-sdks \
publish-rust publish-rust-dry \
publish-python publish-python-dry \
publish-node publish-node-dry \
publish-npm-cli publish-npm-cli-dry \
publish-pypi-cli publish-pypi-cli-dry \
publish-all publish-all-dry \
publish-python-local publish-node-local publish-npm-cli-local publish-pypi-cli-local \
publish-local verify-release \
version-bump tag-release \
site-dev site-build site-preview site-install site-deploy site-deploy-status \
clean clean-all
# ββ Colours ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
BOLD := \033[1m
GREEN := \033[0;32m
CYAN := \033[0;36m
YELLOW := \033[0;33m
RED := \033[0;31m
DIM := \033[2m
RESET := \033[0m
# ββ Paths ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
BINARY := target/release/edgecrab
# ββ Version (read from the canonical release-version helper) ββββββββββββββββββ
VERSION := $(shell ./scripts/release-version.sh print)
# ββ Helper macros ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
define log
@printf "$(BOLD)$(GREEN) βΆ$(RESET) $(GREEN)$(1)$(RESET)\n"
endef
define ok
@printf "$(BOLD)$(GREEN) β$(RESET) $(1)\n"
endef
define warn
@printf "$(BOLD)$(YELLOW) β $(RESET) $(YELLOW)$(1)$(RESET)\n"
endef
define err
@printf "$(BOLD)$(RED) β$(RESET) $(RED)$(1)$(RESET)\n"
endef
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# HELP
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
help: ## Show this help screen
@printf "\n$(BOLD)EdgeCrab$(RESET) β Rust-native autonomous coding agent\n"
@printf "$(DIM)https://github.com/raphaelmansuy/edgecrab$(RESET)\n\n"
@printf "$(BOLD)Usage$(RESET)\n"
@printf " make $(CYAN)<target>$(RESET)\n\n"
@printf "$(BOLD)Targets$(RESET)\n"
@awk 'BEGIN {FS = ":.*##"; section=""} \
/^## / { printf "\n $(BOLD)%s$(RESET)\n", substr($$0, 4); next } \
/^[a-zA-Z_-]+:.*##/ { printf " $(CYAN)%-26s$(RESET) %s\n", $$1, $$2 }' \
$(MAKEFILE_LIST)
@printf "\n"
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
## Build
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
build: ## Build optimised portable release binary (full LTO, single CGU). Use for distribution.
$(call log,cargo build --release -p edgecrab-cli)
@cargo build --release -p edgecrab-cli
$(call ok,Binary ready: $(BINARY))
@printf "$(DIM) Size: %s\n$(RESET)" "$$(du -h $(BINARY) | cut -f1)"
build-fast: ## Release-grade binary without LTO (faster link; ~5-10%% slower runtime). Use during release-mode iteration.
$(call log,cargo build --profile release-fast -p edgecrab-cli)
@cargo build --profile release-fast -p edgecrab-cli
$(call ok,Binary ready: target/release-fast/edgecrab)
build-native: ## Maximum-perf release binary tuned for THIS machine's CPU (NOT PORTABLE).
$(call log,cargo build --release -p edgecrab-cli [RUSTFLAGS=-C target-cpu=native])
@RUSTFLAGS="-C target-cpu=native" cargo build --release -p edgecrab-cli
$(call ok,Binary ready: $(BINARY) (do not ship β uses host-specific instructions))
dev: ## Fast debug build of CLI only (preferred during development)
$(call log,cargo build -p edgecrab-cli)
@cargo build -p edgecrab-cli
$(call ok,Debug binary ready: target/debug/edgecrab)
build-debug: ## Build debug binary (alias for dev)
$(call log,cargo build -p edgecrab-cli)
@cargo build -p edgecrab-cli
build-termux: ## Cross-compile for Termux/Android (aarch64-linux-android)
$(call log,cargo build --release --target aarch64-linux-android --features termux)
@cargo build --release --target aarch64-linux-android --features termux
$(call ok,Termux binary ready: target/aarch64-linux-android/release/edgecrab)
run: ## Run the edgecrab CLI from the workspace root (debug build). Pass ARGS='...'
$(call log,cargo run -p edgecrab-cli --bin edgecrab -- $(ARGS))
@cargo run -p edgecrab-cli --bin edgecrab -- $(ARGS)
run-release: ## Run the edgecrab CLI from the workspace root (release build). Pass ARGS='...'
$(call log,cargo run --release -p edgecrab-cli --bin edgecrab -- $(ARGS))
@cargo run --release -p edgecrab-cli --bin edgecrab -- $(ARGS)
check: ## Fast compile-check of CLI (no binary produced)
$(call log,cargo check -p edgecrab-cli)
@cargo check -p edgecrab-cli
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
## Code quality
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
fmt: ## Auto-format all crates
$(call log,cargo fmt --all)
@cargo fmt --all
fmt-check: ## Verify formatting without changes (CI gate)
$(call log,cargo fmt --all -- --check)
@cargo fmt --all -- --check
lint: ## Run Clippy β warnings promoted to errors
$(call log,cargo clippy -- -D warnings)
@cargo clippy -- -D warnings
test: ## Run all Rust unit and integration tests across the workspace
$(call log,cargo test --workspace)
@cargo test --workspace
test-lsp: ## Run the dedicated LSP crate tests and integration coverage
$(call log,cargo test -p edgecrab-lsp)
@cargo test -p edgecrab-lsp
test-web-search-e2e: ## Web search E2E: mock edge cases + Docker SearXNG live test
$(call log,web search unit + mock integration tests)
@cargo test -p edgecrab-tools --lib web::search -- --test-threads=1 --nocapture
@cargo test -p edgecrab-tools --test web_search_e2e_edge --test web_search_e2e_config --test web_search_e2e_setup --test web_search_e2e_setup_web --test web_search_e2e_wizard --test web_search_e2e_chain --test web_search_e2e_doctor --test web_search_ddgs_e2e --test web_search_ddgs_edge_e2e --test file_write_tmp_e2e --test web_extract_backend_e2e --test web_extract_config_e2e --test web_extract_registry_e2e --test web_extract_policy_e2e -- --test-threads=1 --nocapture
@cargo test -p edgecrab-tools --test web_search_e2e -- --test-threads=1 --nocapture
$(call log,Docker SearXNG live E2E)
@specs/001-gap-analysis-v14/014-web-search-backends/e2e/run-searxng-e2e.sh
$(call ok,Web search E2E passed)
ci: fmt-check lint test-lsp test test-sdks ## Full CI gate: fmt β lint β LSP β workspace test β SDK tests
$(call ok,All CI checks passed)
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
## Install
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
install: ## Install edgecrab to ~/.cargo/bin using the full release profile (LTO, slowest build, fastest runtime)
$(call log,cargo install --path crates/edgecrab-cli --locked)
@cargo install --path crates/edgecrab-cli --locked
$(call ok,Installed: $$(which edgecrab))
install-fast: ## Install edgecrab to ~/.cargo/bin using release-fast (no LTO; ~3-4x faster build, ~5-10%% slower runtime)
$(call log,cargo install --path crates/edgecrab-cli --profile release-fast --locked)
@cargo install --path crates/edgecrab-cli --profile release-fast --locked
$(call ok,Installed: $$(which edgecrab) [release-fast profile])
install-native: ## Install edgecrab to ~/.cargo/bin tuned for THIS machine's CPU (NOT PORTABLE β local-only)
$(call log,RUSTFLAGS='-C target-cpu=native' cargo install --path crates/edgecrab-cli --locked)
@RUSTFLAGS="-C target-cpu=native" cargo install --path crates/edgecrab-cli --locked
$(call ok,Installed: $$(which edgecrab) [native CPU tuning])
uninstall: ## Remove edgecrab from ~/.cargo/bin
$(call warn,Removing edgecrab from ~/.cargo/bin ...)
@cargo uninstall edgecrab-cli || true
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
## SDK Tests
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
test-python: ## Run Python SDK tests and packaging checks
$(call log,Python SDK tests)
@cd sdks/python && python3 -m pip install -q --upgrade build twine pytest pytest-asyncio && python3 -m pip install -e . -q && PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 python3 -m pytest -p pytest_asyncio.plugin tests/test_sdk_e2e.py -v && python3 -m build --sdist && python3 -m twine check dist/*
test-node: ## Run public and native Node.js SDK tests
$(call log,Node.js SDK tests)
@cd sdks/node && npm ci --silent && npm run build && npm test && npm pack --dry-run
@cd sdks/nodejs-native && npm ci --silent && npm run build && npm test
test-sdks: test-python test-node ## Run all SDK test suites
$(call ok,All SDK tests passed)
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
## Publish
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# ββ Rust / crates.io ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Dry-run every crate in publish order. Uses --no-verify + --allow-dirty so
# workspace path deps don't cause false failures locally.
publish-rust-dry: ## Dry-run: verify all 12 crates package cleanly
$(call log,Dry-run: all Rust crates ...)
@for crate in edgecrab-types edgecrab-security edgecrab-state edgecrab-cron edgecrab-tools edgecrab-plugins edgecrab-lsp edgecrab-core edgecrab-gateway edgecrab-acp edgecrab-migrate edgecrab-cli; do \
printf " $(CYAN)β$(RESET) cargo publish -p $$crate --dry-run\n"; \
cargo publish -p $$crate --dry-run --allow-dirty --no-verify 2>&1 | grep -v 'Uploading' || true; \
done
$(call ok,Rust dry-run passed)
# Publishes all crates in strict topological order. Between each publish
# we sleep 30 s so crates.io has time to index the crate before the next
# dependent crate is submitted. Errors due to "already published" are
# treated as non-fatal; all other errors abort immediately.
publish-rust: ## Publish all 12 crates to crates.io (dependency order)
$(call log,Publishing edgecrab-types ...)
@OUTPUT=$$(cargo publish -p edgecrab-types 2>&1); STATUS=$$?; \
echo "$$OUTPUT"; \
if [ $$STATUS -ne 0 ]; then \
echo "$$OUTPUT" | grep -q 'already exists' && echo ' (already published β skipping)' || exit 1; \
fi
$(call log,Waiting 30 s for index propagation ...)
@sleep 30
$(call log,Publishing remaining crates ...)
@for crate in edgecrab-security edgecrab-state edgecrab-cron edgecrab-tools edgecrab-plugins edgecrab-lsp edgecrab-core edgecrab-gateway edgecrab-acp edgecrab-migrate edgecrab-cli; do \
printf " $(CYAN)β$(RESET) cargo publish -p $$crate --no-verify\n"; \
OUTPUT=$$(cargo publish -p $$crate --no-verify 2>&1); STATUS=$$?; \
echo "$$OUTPUT"; \
if [ $$STATUS -ne 0 ]; then \
echo "$$OUTPUT" | grep -q 'already exists' && echo ' (already published β skipping)' || exit 1; \
fi; \
sleep 30; \
done
$(call ok,Rust crates published)
# ββ Python / PyPI βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
publish-python-dry: ## Dry-run: build Python sdist and check with twine
$(call log,Building Python sdist [dry-run])
@cd sdks/python && python -m build --sdist
@twine check sdks/python/dist/*
$(call ok,Python dry-run passed)
publish-python: ## Build and upload Python SDK to PyPI
$(call log,Building Python wheels ...)
@cd sdks/python && python -m build
$(call log,Uploading to PyPI ...)
@twine upload sdks/python/dist/*
$(call ok,Python SDK published to PyPI)
publish-python-local: ## Build Python SDK wheel and install it locally with pip
$(call log,Building Python SDK wheel ...)
@cd sdks/python && python -m build
$(call log,Installing Python SDK locally ...)
@pip install --force-reinstall sdks/python/dist/edgecrab-*.whl
$(call ok,Python SDK installed locally)
# ββ Node.js / npm ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
publish-node-dry: ## Dry-run: build and pack Node.js SDK
$(call log,Building Node.js SDK [dry-run])
@cd sdks/node && npm ci && npm run build
@cd sdks/node && npm pack --dry-run
$(call ok,Node.js dry-run passed)
publish-node: ## Build and publish Node.js SDK to npm
$(call log,Building Node.js SDK ...)
@cd sdks/node && npm ci && npm run build
$(call log,Publishing to npm ...)
@cd sdks/node && npm publish --access public
$(call ok,Node.js SDK published to npm)
publish-node-local: ## Build Node.js SDK, pack it, and install it locally via npm link
$(call log,Building Node.js SDK ...)
@cd sdks/node && npm ci && npm run build
$(call log,Linking Node.js SDK locally ...)
@cd sdks/node && npm link --force
$(call ok,Node.js SDK linked locally β use 'npm link edgecrab-sdk' in your project)
# ββ npm CLI (edgecrab-cli wrapper) βββββββββββββββββββββββββββββββββββββββββββ
publish-npm-cli-dry: ## Dry-run: pack npm CLI wrapper package
$(call log,npm CLI dry-run pack)
@cd sdks/npm-cli && npm pack --dry-run
$(call ok,npm CLI dry-run passed)
publish-npm-cli: ## Publish npm CLI wrapper to npm registry
$(call log,Publishing npm CLI wrapper ...)
@cd sdks/npm-cli && npm publish --access public
$(call ok,npm CLI published to npm)
publish-npm-cli-local: ## Pack npm CLI wrapper and install it globally via npm link
$(call log,Linking npm CLI wrapper locally ...)
@cd sdks/npm-cli && npm link
$(call ok,npm CLI linked globally β 'edgecrab' command now available)
# ββ PyPI CLI (edgecrab-cli wrapper) ββββββββββββββββββββββββββββββββββββββββββ
publish-pypi-cli-dry: ## Dry-run: build PyPI CLI wrapper and check with twine
$(call log,Building PyPI CLI wrapper [dry-run])
@cd sdks/pypi-cli && python -m build --sdist
@twine check sdks/pypi-cli/dist/*
$(call ok,PyPI CLI dry-run passed)
publish-pypi-cli: ## Build and upload PyPI CLI wrapper to PyPI
$(call log,Building PyPI CLI wrapper ...)
@cd sdks/pypi-cli && python -m build
$(call log,Uploading to PyPI ...)
@twine upload sdks/pypi-cli/dist/*
$(call ok,PyPI CLI published)
publish-pypi-cli-local: ## Build PyPI CLI wrapper wheel and install it locally with pip
$(call log,Building PyPI CLI wrapper wheel ...)
@cd sdks/pypi-cli && python -m build
$(call log,Installing PyPI CLI wrapper locally ...)
@pip install --force-reinstall sdks/pypi-cli/dist/edgecrab_cli-*.whl
$(call ok,PyPI CLI installed locally)
# ββ Publish all βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Dry-run preflight for every package β run before tagging a release.
publish-all-dry: publish-rust-dry publish-python-dry publish-node-dry publish-npm-cli-dry publish-pypi-cli-dry ## Dry-run all packages (preflight before tagging)
$(call ok,All dry-runs passed β safe to tag and release)
publish-all: publish-rust publish-python publish-node publish-npm-cli publish-pypi-cli ## Publish all packages (crates.io + PyPI + npm)
$(call ok,All packages published)
publish-local: publish-python-local publish-node-local publish-npm-cli-local publish-pypi-cli-local ## Build and install/link all Python + npm packages locally (no registry)
$(call ok,All packages published locally)
verify-release: ## Verify public release publication. Usage: make verify-release VERSION=0.7.0
@[ -n "$(VERSION)" ] || (printf "$(RED)ERROR: VERSION is required. Example: make verify-release VERSION=0.7.0$(RESET)\n"; exit 1)
$(call log,Verifying npm publication for $(VERSION) ...)
@./scripts/release-verify.sh npm edgecrab-sdk "$(VERSION)"
$(call log,Verifying PyPI publication for $(VERSION) ...)
@./scripts/release-verify.sh pypi edgecrab "$(VERSION)"
$(call log,Verifying GHCR publication for $(VERSION) ...)
@./scripts/release-verify.sh ghcr ghcr.io/raphaelmansuy/edgecrab "$(VERSION)" linux/amd64 linux/arm64
$(call ok,All public release assets verified)
# ββ Version bump ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Bump the canonical release version and sync every derived manifest.
# Usage: make version-bump VERSION=0.2.0
version-bump: ## Bump version in all manifests. Usage: make version-bump VERSION=0.2.0
@[ -n "$(VERSION)" ] || (printf "$(RED)ERROR: VERSION is required. Example: make version-bump VERSION=0.2.0$(RESET)\n"; exit 1)
$(call log,Setting canonical release version to $(VERSION) ...)
@./scripts/release-version.sh set "$(VERSION)"
@./scripts/release-version.sh check
$(call ok,Version bumped to $(VERSION))
@printf "$(DIM) Next: git add -A && git commit -m 'chore: bump version to $(VERSION)' && make tag-release VERSION=$(VERSION)$(RESET)\n"
# ββ Tag release βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Create and push an annotated release tag. This triggers all release-*.yml
# workflows on GitHub Actions (crates.io + npm + PyPI + Docker + binaries).
# Run `make publish-all-dry` first as a preflight check.
# Usage: make tag-release VERSION=0.2.0
tag-release: ## Create and push release tag. Usage: make tag-release VERSION=0.2.0
@[ -n "$(VERSION)" ] || (printf "$(RED)ERROR: VERSION is required. Example: make tag-release VERSION=0.2.0$(RESET)\n"; exit 1)
$(call log,Creating annotated tag v$(VERSION) ...)
@git tag -a "v$(VERSION)" -m "Release v$(VERSION)"
$(call log,Pushing tag v$(VERSION) to origin ...)
@git push origin "v$(VERSION)"
$(call ok,Tag v$(VERSION) pushed β CI will publish all packages)
@printf "$(DIM) Monitor: gh run list --limit 10$(RESET)\n"
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
## Documentation Site (Astro)
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
SITE_DIR := site
site-install: ## Install Astro site dependencies
$(call log,Installing site dependencies ...)
@cd $(SITE_DIR) && pnpm install
$(call ok,Site dependencies installed)
site-dev: ## Start Astro docs site in dev mode (hot-reload)
$(call log,Starting Astro dev server β http://localhost:4321)
@cd $(SITE_DIR) && pnpm dev
site-build: ## Build Astro docs site for production (output: site/dist/)
$(call log,Building Astro site for production ...)
@cd $(SITE_DIR) && pnpm build
$(call ok,Site built β $(SITE_DIR)/dist/)
site-preview: site-build ## Build then preview the production site locally
$(call log,Previewing production build β http://localhost:4321)
@cd $(SITE_DIR) && pnpm preview
site-deploy: ## Trigger GitHub Pages deployment via workflow_dispatch (pushes live to www.edgecrab.com)
$(call log,Triggering GitHub Pages deployment ...)
@GH_PAGER='' gh workflow run deploy-site.yml --ref main
$(call ok,Deployment triggered β monitor at: https://github.com/raphaelmansuy/edgecrab/actions/workflows/deploy-site.yml)
site-deploy-status: ## Check the latest GitHub Pages deployment status
$(call log,Checking latest deployment status ...)
@GH_PAGER='' gh run list --workflow=deploy-site.yml --limit 3
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
## Clean
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
clean: ## Remove Rust build artifacts
$(call log,cargo clean)
@cargo clean
clean-all: clean ## Remove all build artifacts (Rust + SDKs + site)
@rm -rf sdks/node/dist sdks/node/node_modules
@rm -rf sdks/python/dist sdks/python/*.egg-info
@rm -rf sdks/npm-cli/bin/edgecrab sdks/npm-cli/bin/edgecrab.exe
@rm -rf sdks/pypi-cli/dist sdks/pypi-cli/*.egg-info sdks/pypi-cli/edgecrab_cli/_bin
@rm -rf $(SITE_DIR)/dist $(SITE_DIR)/.astro
$(call ok,All build artifacts removed)