Add CLAUDE.md, collection scaffold, and MemPalace wing

Establish this repo as a collection of independent script folders for the
self-hosted environment (odin, an Unraid host).

- CLAUDE.md: repo conventions, the odin stack, and MemPalace usage. The
  infrastructure facts are carried over from the FamilySync project, where
  they are documented and verified; the mapping of the name "odin" to that
  host is assumed and flagged for confirmation, along with the SSH/deploy
  gaps marked "?".
- Core rule: each collection is a self-contained top-level folder owning its
  own docs, config, and dependencies. No shared/ or utils/ at the root —
  duplication is preferred over coupling so a collection stays independently
  deletable.
- _template/: scaffold making that rule concrete. The bash entrypoint ships
  strict mode, --dry-run, and a required-env guard (all four paths tested).
- mempalace.yaml: wing "odin-scripts", set explicitly because basename
  auto-detection would produce the colliding wing "scripts". Tracked rather
  than gitignored so a fresh clone keeps the config; entities.json stays
  ignored.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Lucas Berger
2026-08-15 20:24:16 -04:00
co-authored by Claude Opus 5
parent 4437ff5e54
commit c6be0dc9d6
7 changed files with 355 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
# Copy to .env and fill in. Never commit the filled-in .env.
EXAMPLE_HOST=odin.bergerhouse.net
EXAMPLE_TOKEN=replace-me
+36
View File
@@ -0,0 +1,36 @@
# <collection-name>
One sentence: what this collection does and why it exists.
## Prerequisites
- Where it runs: `odin` (Unraid) / this workstation / either
- Interpreters: bash / Python 3 / Node 22
- External tools: e.g. `docker`, `tea`, `curl`
- Access needed: e.g. SSH to odin, Gitea API token
## Configuration
Copy `.env.example` to `.env` and fill it in. Real values live in `<where>`.
| Variable | Required | Description |
| --- | --- | --- |
| `EXAMPLE_HOST` | yes | Target host to operate against |
## Usage
```bash
bin/example --dry-run # preview, changes nothing
bin/example # apply
```
## Behaviour notes
- Idempotent: yes/no — and what happens on a re-run.
- Destructive operations: list them, or state "none".
- Scheduling: cron entry / Unraid User Scripts / manual only.
## Gotchas
Anything that cost time to discover. This is the section that earns the collection its
own folder — keep it honest and current.
+55
View File
@@ -0,0 +1,55 @@
#!/usr/bin/env bash
# Template entrypoint. Copy, rename, and replace main().
set -euo pipefail
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly COLLECTION_DIR="$(dirname "$SCRIPT_DIR")"
DRY_RUN=0
usage() {
cat <<'EOF'
Usage: example [--dry-run] [--help]
--dry-run Show what would happen without changing anything.
--help Show this message.
EOF
}
log() { printf '%s\n' "$*"; }
warn() { printf '%s\n' "$*" >&2; }
die() { warn "error: $*"; exit 1; }
# Run a mutating command, or describe it under --dry-run.
run() {
if (( DRY_RUN )); then
log "[dry-run] $*"
else
"$@"
fi
}
load_env() {
local env_file="$COLLECTION_DIR/.env"
[[ -f "$env_file" ]] || return 0
set -a; . "$env_file"; set +a
}
main() {
while (( $# )); do
case "$1" in
--dry-run) DRY_RUN=1 ;;
--help|-h) usage; exit 0 ;;
*) die "unknown argument: $1" ;;
esac
shift
done
load_env
: "${EXAMPLE_HOST:?EXAMPLE_HOST is not set — see .env.example}"
log "target: $EXAMPLE_HOST"
run true # replace with the real work
}
main "$@"