A brew-installable CLI that stands up the prod-like memex stack on Colima k3s,
1:1 with LocalColimaMac.md
— same defaults, same topology, no substitutions. It orchestrates
colima / helm / kubectl / mkcert / ollama; it does not reimplement
the chart. The deploy/helm chart + values stay the single source of
truth.
Why: the manual doc has ~14 steps across colima, image build, ingress, mkcert, Helm, Ollama, and a launchd port-forward. This packages all of it behind
memex-local up(idempotent) andmemex-local down.
brew tap systemorph/memex # https://github.com/Systemorph/homebrew-memex
brew trust systemorph/memex # Homebrew refuses a third-party tap's formulae until the tap is trusted
brew install memex-localThe tap is published by this repository's own CI: .github/workflows/homebrew.yml
installs and tests the formula from every PR that touches deploy/homebrew/** or
deploy/helm/** (on a macOS runner, under macOS's bash 3.2), and on every merge to
main attaches a tarball of exactly those two directories to a release of the tap and
commits the formula with its sha256. The version is 0.2.<main commit count>, so
brew upgrade memex-local follows main. The formula declares the exact brew
toolchain LocalColimaMac.md §1 installs — colima, kubernetes-cli (kubectl),
helm, mkcert, ollama, socket_vmnet — plus azure-cli for the registry-mode
image pull. It vendors a snapshot of deploy/helm so the install works standalone.
The .NET SDK (10.0) is not a dependency: only the local-build image path (Option B,
§3) needs it, depends_on cask: is rejected by current Homebrew, and the registry-mode
default pulls the CI-built image instead. Install it separately for Option B
(brew install --cask dotnet-sdk or the standalone installer).
Developing memex-local itself? Run it straight from the checkout — it resolves the
chart + share assets relative to the script — or install a local tap over the template
formula (brew tap-new systemorph/memex-dev, copy Formula/memex-local.rb in, brew install --HEAD systemorph/memex-dev/memex-local). A brew install's wrapper pins
MEMEX_CHART_DIR to the vendored chart; run-from-checkout uses the live deploy/helm
(or MEMEX_REPO/MEMEX_CHART_DIR) directly.
| Mode | memex-local registry status says |
Plugins | Module binaries (Radzen, Analysis, EntityViews, GoogleMaps, Speech, Mcp…) | Image |
|---|---|---|---|---|
| Registry (§17, recommended) | REGISTRY MODE — consumes https://memex.meshweaver.cloud |
installed from the cloud registry, per the instance's grant | land from the registry's bundles into /data |
CI-built multi-arch from ACR (az login) |
| Self-registry (§16) | SELF-REGISTRY MODE |
served from a MeshWeaver.Plugins checkout beside MEMEX_REPO |
🚨 never — a checkout has source, not assemblies (MeshWeaver#2417); the five required ones are blanked | built from source (Option B) |
Registry mode is one command, and needs no key by default — an un-keyed registration is an open one, which the default public registry enrols into its default plan, the free tier:
memex-local registry https://memex.meshweaver.cloud [--id my-mac] # free tier, no key
memex-local registry https://memex.meshweaver.cloud --key mwr_… # a plan an admin minted a key for
memex-local up # or `update` on an existing install~/.memex-local/registry.yaml (0600) then carries pluginCatalog.registryUrl /
instanceId — and the bootstrap key, when one was given; helm_deploy layers it last. On
first boot the portal registers itself (presenting the key once if it has one), is issued
its own instance key (stored encrypted in its database, so it survives every update),
installs everything it is granted and lands the modules; verify --repair performs the one
activation restart. What it is granted is the registry's decision — a plan-scoped grant,
raised by a platform admin there (Instance grants ▸ Plan), never something the install can
ask for — see
PluginRegistry.md
→ Plans. memex-local registry off returns to serving a checkout.
memex-local registry <url> [--key mwr_…] # REGISTRY MODE: consume a remote plugin registry (§17); no key = free tier
memex-local registry status|off # which mode this install is in / back to self-registry
memex-local up # full stack, idempotent (registry mode: ACR image; else local build)
memex-local up --from-acr # pull the multi-arch image from ACR explicitly (Option A)
memex-local status # colima / pods / ingress / port-forward / health
memex-local logs # tail the portal logs (verbose; see "Full logging")
memex-local logs --migration # tail the migration job
memex-local update # roll portal+migration to a newer image, refresh forward
memex-local verify # is the portal USABLE? serves + /login routed + view packs present
memex-local autoroll up # AUTO-redeploy portal+migration whenever a fresh image is built
memex-local autoroll status # show the watcher + last-rolled portal/migration digests
memex-local autoroll down # stop auto-rolling
memex-local observability # Grafana/Loki/Promtail/Prometheus (§11)
memex-local doctor # preflight: tools, chart/assets, cluster
memex-local instance up # ramp a NEW portal that self-registers + installs plugins (§16)
memex-local instance status # what it registered / installed
memex-local instance down # remove it and RELEASE its instance id on the registry
memex-local down # uninstall release (KEEPS the Postgres PVC)
memex-local down --purge # also delete namespace + PVC (data loss) + ingress-nginx🚨
memex-localuses your ambientkubectlcontext. With a cloud context selected,up/updatedeploy there, and the port-forward breaks. Runkubectl config use-context colimafirst — see LocalColimaMac §14.
Open https://memex.localhost:8443 once up finishes.
The default image path is Option B (build native arm64 straight into Colima's
Docker store — the no-cloud-creds path the doc leads with for un-pushed source),
which needs the MeshWeaver source: set MEMEX_REPO to your checkout, or run from
a checkout. Option A (--from-acr) pulls the now-multi-arch image from
meshweaver.azurecr.io (run az acr login -n meshweaver first).
On first up, the CLI generates ~/.memex-local/values.local.yaml from the
template in share/values.local.yaml, substituting a
freshly generated Postgres password and AI master key. Edit that file to fill
in your Microsoft Entra ClientId / TenantId / ClientSecret (LocalColimaMac.md
§9), or uncomment Authentication__EnableDevLogin for a no-Azure login. Re-run
memex-local up to apply.
On AKS the portal self-updates by polling ACR and patching its own Deployment
(SelfUpdateHostedService, per ReleaseStrategy.md).
That in-pod poll cannot work locally — the local images are built straight into
Colima's Docker store, never pushed to a registry the pod can list (the in-pod
AcrTagLister would fail the Azure→ACR token exchange). So locally the same
outcome is driven from the host instead:
memex-local autoroll up # arm it (once)This installs a launchd agent (com.memex.local.autoroll) that, every 30s:
- Pins the portal Deployment to the moving tag
…/memex-portal-ai:latest(imagePullPolicy: IfNotPresent— k3s reuses the Docker-store image, no pull). - Watches the portal and migration
…-local:latestimage digests. When a build changes one, it first retags that fresh…-local:latestonto the chart ref the cluster actually runs (…/memex-portal-ai:latest,…/memex-migration:latest) — so even a baredotnet publish(which only writes…-local:latest) goes live — then:- migration first — re-runs the migration as a one-shot Job against the
main DB and waits for it (the portal's
DbVersionGateblocks boot until the schema is current; if the migration fails it leaves everything on the current images and retries — it never rolls the portal onto a schema it can't run); - then
rollout restartthe portal so the rebuilt image goes live.
- migration first — re-runs the migration as a one-shot Job against the
main DB and waits for it (the portal's
So after autoroll up, any rebuild — memex-local update, memex-local up --build, or a bare dotnet publish -t:PublishContainer of the portal/migration
— auto-deploys within ~30s, with no manual kubectl set image (the retag in
step 2 is what makes the bare-publish case work — without it the roll would
re-run the old chart-ref image).
Do you need to install anything first? No.
autorolluses launchd (built into macOS) plusdocker+kubectl, which are alreadymemex-localprerequisites (LocalColimaMac.md§1). Nothing new to install.
autoroll status shows whether the watcher is running and the last-rolled portal
and migration digests; autoroll down stops it (the portal stays on its current
image). The log is ~/.memex-local/autoroll.log. Only the portal Deployment is
rolled in place; the migration is re-run as a Job (it has no Deployment).
| Doc section | Manual step | CLI implementation (function in bin/memex-local) |
|---|---|---|
| §1 Prerequisites | brew install colima kubectl helm mkcert ollama socket_vmnet + .NET SDK |
Formula depends_on; preflight() re-checks at runtime |
| §2 Colima k3s | colima start --kubernetes --cpu 8 --memory 16; verify context/node |
start_colima() |
| §3 Image (A) | pull multi-arch from ACR, verify arm64 in manifest, retag |
image_pull_acr() (up --from-acr) |
| §3 Image (B) | dotnet publish -t:PublishContainer portal+migration, docker tag to chart name |
image_build_local() (default) |
| §4 Helm | helm upgrade --install memex deploy/helm -f values.yaml -f overlay -n memex |
helm_deploy() + ensure_overlay() |
| §4 Postgres PVC | shipped by the chart (StatefulSet, 10Gi PVC, pgvector pg17) | unchanged — chart is source of truth |
| §5 ingress-nginx | helm upgrade --install ingress-nginx … ClusterIP, no admission webhooks |
install_ingress_nginx() |
| §5 mkcert TLS | mkcert -install + mint cert + kubectl create secret tls memex-portal-tls |
setup_tls() |
| §6 Hostname | memex.localhost (auto-resolves), port 8443 |
constants HOSTNAME_LOCAL / HOST_PORT |
| §7 Durable access | port-forward.sh + com.memex.local.plist, launchctl bootstrap |
install_launchd() (assets in share/) |
| §10 Local LLM | OLLAMA_HOST=0.0.0.0:11434 ollama serve; ollama pull qwen3.6; ollama cp … qwen3.6-code |
setup_ollama() + overlay ollama.external + OpenAICompatible__* |
| §11 Observability | helm upgrade --install loki grafana/loki-stack … |
cmd_observability() |
| §12 Instance identity | Portal__InstanceName/Color |
overlay config.memex_portal |
| §14 Verify | assert the portal is USABLE — it serves, /login is routed, and the DefaultViews/GraphViews packs are present |
verify_usable() (up / update / verify; behaviour-tested in test/run-tests.sh) |
| §14 Troubleshoot (stale forward) | restart the port-forward after a rollout | cmd_port_forward(); update auto-refreshes it |
| §16 Plugin registry | mount the plugin checkouts + configure them as sources/grants | plugin_repo_paths() + the pluginCatalog.* --sets in helm_deploy() |
| §16 New instance | mint an mwr_ key → own DB → deploy a self-registering portal → verify |
cmd_instance() (inst_mint_key, inst_registered_id, inst_installed_packages) |
| Self-update (ReleaseStrategy) | in-pod patch per Admin/UpdatePolicy (Continuous default) — can't see local-built images |
cmd_update() = manual roll; cmd_autoroll() = host-side auto-roll on a new local build (the local stand-in for the in-pod poll; see "Auto-update" above) |
down reverses §7 (launchd) and §4 (Helm release) while retaining the Postgres
PVC so data survives — exactly the "survives reboot" property the doc emphasises.
--purge is the explicit data-wipe.
LocalColimaMac.md wants logs turned up locally. The chart's portal ConfigMap
passes a config.memex_portal key it does not name through verbatim, so the
overlay's level reaches the pod — but memex-local also honours MEMEX_LOG_LEVEL
at run time, without a re-render. So the verbose level is applied two
complementary ways:
- Declared in the overlay (
config.memex_portal.Logging__LogLevel__Default: "Debug") — rendered into the ConfigMap by the chart's pass-through. - Applied as a deployment-config override by
apply_logging()after every Helm upgrade:kubectl set env deployment/memex-portal-deployment Logging__LogLevel__Default=$MEMEX_LOG_LEVEL. A containerenventry wins overenvFrom, and it's idempotent (same value → no rollout).
Set MEMEX_LOG_LEVEL=Trace for maximum verbosity. Logs are one command away:
memex-local logs (portal), --migration, --postgres.
🚨 This installer never edits any committed
src/**/appsettings*.json— perAGENTS.mdthose are production contract. Verbose logging is purely a runtime deployment-config override on your local cluster.
Postgres is the chart's in-cluster StatefulSet (pgvector/pgvector:pg17) on a
10Gi PVC via volumeClaimTemplates — unchanged. down keeps it; only
down --purge deletes it. The password is generated once into the overlay and
reused across the migration/portal secret groups (the chart builds the connection
strings from it).
| Path | What |
|---|---|
Formula/memex-local.rb |
Homebrew formula (deps + install + caveats + test) |
bin/memex-local |
the orchestration CLI (all subcommands) |
share/values.local.yaml |
local Helm overlay template (full logging + pg + ingress + ollama + instance id) |
share/port-forward.sh |
the §7 port-forward script (started by launchd) |
share/com.memex.local.plist |
the §7 launchd login-agent template |
State lives in ~/.memex-local/ (overlay, mkcert cert/key, port-forward script +
log, ollama log, grafana password) — exactly the paths the doc uses.
| Var | Default | Purpose |
|---|---|---|
MEMEX_REPO |
auto-detected from checkout | repo root for chart + local build |
MEMEX_CHART_DIR |
$MEMEX_REPO/deploy/helm or vendored copy |
explicit chart dir |
MEMEX_LOG_LEVEL |
Debug |
verbose log level (Trace for max) |
MEMEX_COLIMA_CPU / MEMEX_COLIMA_MEM |
8 / 16 |
VM sizing (§2) |
MEMEX_PORT |
8443 |
host port for the forward (§6/§7) |
MEMEX_LOCAL_HOME |
~/.memex-local |
state directory |
Validated here (syntax / correct-by-construction):
ruby -c Formula/memex-local.rb— formula parses.bash -n bin/memex-local share/port-forward.sh— scripts parse.shellcheckclean (if installed).- Every
LocalColimaMac.mdmanual step traces to a CLI function (table above).
Cannot be run in this environment — verify on a real Apple-Silicon Mac:
brew installof the formula (needs Homebrew + network).colima start --kubernetes(needs virtualization +socket_vmnet).mkcert -install(writes the CA to the System keychain — interactive auth).ollama serve+ollama pull qwen3.6(downloads the model; needs the Metal GPU for performance).- The local-build image path (
dotnet publish -t:PublishContainer) and/or the ACR pull (az acr login). - The end-to-end
curl https://memex.localhost:8443/returninghttp=200.