Commit Graph

44 Commits

Author SHA1 Message Date
Joakim Persson 1683650240 Bake mempalace-toolkit wrappers into the image
Validate / docs-check (push) Successful in 14s
Validate / validate-base (push) Successful in 14m44s
Validate / validate-omos (push) Successful in 17m51s
Publish Docker Image / build-omos (push) Failing after 25m7s
Publish Docker Image / build-base (push) Failing after 55m51s
Publish Docker Image / update-description (push) Has been skipped
The scheduler templates in mempalace-toolkit's contrib/ assume
mempalace-session is available inside the container, but the image
never actually installed it. Users following the *-devbox scheduler
docs would silently lose the wrappers on every container recreate,
because the only way to get them was a post-hoc install.sh inside
the container — which lives in the ephemeral layer. The host-side
systemd timer would then fire, docker exec in, and hit
"mempalace-session: command not found".

Caught during runtime validation on 2026-04-30: host-side systemd
unit ran cleanly at 16:15 today, then the container was rebuilt
and recreated, and the wrappers were gone. The rebuild produced
an image that the scheduler template's own documented precondition
did not hold for.

Fix: new Dockerfile block clones mempalace-toolkit at build time
(depth-1) to /opt/mempalace-toolkit/, symlinks bin/mempalace-session
and bin/mempalace-docs into /usr/local/bin/, asserts both respond
to --help before the layer succeeds. Gated by
INSTALL_MEMPALACE_TOOLKIT=true (defaults on, depends on
INSTALL_MEMPALACE=true). Floated ref via MEMPALACE_TOOLKIT_REF=main
for auto-picking-up toolkit updates; override for reproducible
builds once the toolkit starts tagging releases.

Smoke test gains three assertions (mempalace-session --help,
mempalace-docs --help, symlink target check). Resolved-versions
preamble logs the toolkit git short-SHA alongside the other
floated components, so CI logs always record what got baked in.

README gains a Scheduled mining (mempalace-toolkit) subsection
and a build-args row. DOCKER_HUB.md regenerated; sync-check passes.
2026-04-30 20:56:58 +00:00
joakimp 23bae2ab7d Use mempalace-mcp entry point directly, drop redundant wrapper
Validate / docs-check (push) Successful in 20s
Validate / validate-base (push) Successful in 11m32s
Validate / validate-omos (push) Successful in 15m18s
Publish Docker Image / build-base (push) Successful in 53m5s
Publish Docker Image / build-omos (push) Successful in 1h11m3s
Publish Docker Image / update-description (push) Successful in 15s
The mempalace Python package ships a 'mempalace-mcp' console entry
point; 'uv tool install' places it on PATH as a shim whose shebang
points at the isolated venv's Python. Our hand-rolled wrapper at
/usr/local/bin/mempalace-mcp-server was duplicating what uv installs
for free — one less file to maintain.

Fixes the MCP error users saw after the v1.14.28b → v1.14.29 upgrade
path: custom opencode.json files typically had the pre-v1.14.29
command ['python3', '-m', 'mempalace.mcp_server'] which worked with
the old pip install but fails silently after the uv-tool migration
because system python3 cannot import from the venv. Opencode surfaced
this as 'MCP error -32000: connection closed'.

- generate-config.py now emits ['mempalace-mcp'] and keys its detect
  on shutil.which('mempalace-mcp').
- Dockerfile drops 'COPY rootfs/usr/local/bin/' and the chmod of the
  wrapper. Build shrinks from 30 to 29 stages.
- rootfs/usr/local/bin/ removed entirely.
- Smoke test asserts /usr/local/bin/mempalace-mcp is executable and
  prints its symlink target.
- README's MemPalace section shows ['mempalace-mcp'] and explicitly
  warns against the old pattern with the observed failure mode.
- CHANGELOG adds a v1.14.29c entry.
2026-04-29 15:27:30 +02:00
joakimp 113c9f0bb0 Infrastructure pass: CI smoke tests, floating versions, chown sentinel, generate-config script
Main changes:

- Extract opencode.json generation from entrypoint-user.sh into a
  standalone Python script (rootfs/usr/local/lib/opencode-devbox/
  generate-config.py). Preserves the never-overwrite-existing-config
  guarantee. Cuts entrypoint-user.sh from 176 to 97 lines.

- Install MemPalace via 'uv tool install' into an isolated venv at
  /opt/uv-tools/mempalace/ with a /usr/local/bin/mempalace-mcp-server
  wrapper, replacing the 'pip install --break-system-packages' escape
  hatch. The wrapper is what generate-config.py references in the
  auto-generated opencode.json. Also fix 'mempalace init' in
  entrypoint-user.sh to use --yes so first-start initialization isn't
  interactive (this used to hang or print prompts into the user's
  terminal). Gated by INSTALL_MEMPALACE build arg (default true) so
  users who don't need AI memory can shave ~300 MB.

- Sentinel-file pattern in entrypoint.sh volume-ownership loop: write
  .devbox-owner after a successful chown -R, skip the recursive walk
  on subsequent starts when the sentinel matches FINAL_UID:FINAL_GID.
  Cuts multi-second startup costs to milliseconds on large volumes
  (nvim plugins, palace data). UID changes still trigger a full chown.

- Float all GitHub/Gitea-hosted binary versions: gosu, fzf, git-lfs,
  neovim, bat, eza, zoxide, uv, gitea-mcp now default to 'latest' and
  resolve the newest upstream release at build time via the /releases/
  latest redirect. Go (go.dev JSON feed) and oh-my-opencode-slim (npm
  @latest) likewise. Intentional pins still in place: OPENCODE_VERSION,
  NODE_VERSION=22, DEBIAN_VERSION=trixie-slim. Each *_VERSION ARG
  accepts an explicit value to lock a specific version when needed.

- New scripts/smoke-test.sh verifies binary presence, opencode startup,
  entrypoint user drop, generate-config idempotency, bun's presence-
  per-variant, and image size against thresholds (2500 MB base, 3000
  MB OMOS). Prints resolved component versions as its first step so
  CI logs always record what got baked into a given image.

- New .gitea/workflows/validate.yml runs on push to main and PRs:
  single-arch amd64 build, smoke test, DOCKER_HUB.md sync check. Tag-
  triggered docker-publish.yml now smoke-tests each variant on amd64
  before the full multi-arch push.

- scripts/generate-dockerhub-md.py auto-generates DOCKER_HUB.md from
  README.md using explicit SECTION_RULES. --check mode fails CI when
  the committed file is out of sync. Enforces the 25 kB Docker Hub
  limit. Adding a new README section forces an explicit keep/drop/
  replace decision.

- Remove dead INSTALL_PYTHON build arg (was a no-op since mempalace
  added python3 unconditionally).
2026-04-28 23:28:43 +02:00
Joakim Persson 4efc4e8005 Remove dead INSTALL_PYTHON build arg
Python 3 has been unconditionally present since the Debian trixie
upgrade (e58962a, Apr 13) — python3 3.13 ships as a transitive
dependency of the trixie base image. python3-pip (e1029bb) and
python3-venv (3a7ec45) were later added to the base layer on Apr 23
so Mason could install Python-based LSPs (ruff, ansible-lint) into
venvs on nvim startup. MemPalace's pip install (b9c08c3) just
piggybacks on what was already there.

In other words, INSTALL_PYTHON=true has been a no-op reinstall of
already-installed packages for two weeks before MemPalace existed.
The flag is dead weight and the docs that advertise it as meaningful
are misleading. Remove it everywhere.

Users who want Python tooling should use the pre-installed uv/uvx.
2026-04-28 06:56:40 +00:00
joakimp ca44da71e1 Add official Gitea MCP server to base image
Publish Docker Image / build-base (push) Successful in 47m50s
Publish Docker Image / build-omos (push) Successful in 1h2m18s
Publish Docker Image / update-description (push) Successful in 14s
Install gitea-mcp v1.1.0 (Go binary from gitea.com/gitea/gitea-mcp)
using the same multi-arch pattern as gosu/fzf/bat. Provides 50+ MCP
tools for Gitea API — repos, issues, PRs, releases, branches, wiki,
and Actions.

Disabled by default in auto-generated opencode.json (requires
GITEA_ACCESS_TOKEN and GITEA_HOST to be useful). Users enable it by
setting those env vars in .env and flipping enabled to true in their
opencode.json.

Env vars forwarded into the container via docker-compose.yml and
docker-compose.shared.yml environment blocks. Same {env:VAR} pattern
as the GitHub MCP server.

Docs updated: README.md (new Gitea MCP section with setup steps),
DOCKER_HUB.md (tools list), CHANGELOG.md (v1.14.28b entry).
2026-04-27 22:28:15 +02:00
joakimp 7a8de0463f Separate ChromaDB model cache into its own named volume
The ONNX embedding model (~79 MB) downloads to ~/.cache/chroma/ on
first mempalace search. Without persistence it re-downloads on every
container recreation. Add a separate devbox-chroma-cache volume
rather than mixing it into the palace data volume — model cache is
disposable (delete and re-download), palace data is precious (back
up and migrate). Both volumes are commented out by default (opt-in).

Updated README.md storage section to explain the two-volume split
and the air-gapped pre-population path. Added chroma cache row to
DOCKER_HUB.md data storage table.
2026-04-27 20:05:45 +02:00
joakimp b9c08c3dbb Add MemPalace local-first AI memory system to base image
Install mempalace via pip in the Dockerfile. Provides 29 MCP tools
for semantic search over conversation history, knowledge graph
queries, agent diaries, and wing/room/drawer management. Everything
runs locally — no API keys, no data egress.

Integration:
- Dockerfile: pip install mempalace (with --break-system-packages
  for Debian trixie PEP 668 compliance)
- entrypoint-user.sh: auto-initializes palace for /workspace on
  first run (idempotent, skips if palace exists)
- entrypoint.sh: adds ~/.mempalace to the volume ownership-fix loop
- docker-compose.yml + shared: optional devbox-palace named volume
  at ~/.mempalace (commented out by default — user opts in)

Users configure MCP integration by adding a mempalace server entry
to their opencode.json. No wrapper plugin needed — the upstream
Python MCP server is used directly.

Docs updated: README.md (new MemPalace section with setup, MCP
config, usage examples, storage details), DOCKER_HUB.md (data
storage table + tools list), CHANGELOG.md (unreleased entry).
2026-04-27 19:25:38 +02:00
joakimp 8c919074dd Persist neovim plugin/Mason data across container recreations
Mason LSP installs and Lazy plugin cache live at ~/.local/share/nvim,
which was in the container's writable layer. Every --force-recreate
triggered a full re-download of all plugins and LSP servers on next
nvim launch — slow and wasteful.

Add devbox-nvim-data named volume in docker-compose.yml and
docker-compose.shared.yml, add to entrypoint ownership-fix loop,
update persistence tables in README.md and DOCKER_HUB.md.
2026-04-23 19:56:35 +02:00
joakimp c182ada0dd Persist zoxide directory history across container recreations
Publish Docker Image / build-base (push) Successful in 40m32s
Publish Docker Image / build-omos (push) Successful in 50m17s
Publish Docker Image / update-description (push) Successful in 13s
Zoxide stores its database at ~/.local/share/zoxide/db.zo. Without a
named volume, the 'z <fragment>' jump targets are lost on every
'docker compose up --force-recreate'.

Add devbox-zoxide named volume in docker-compose.yml and
docker-compose.shared.yml, add ~/.local/share/zoxide to the
entrypoint ownership-fix loop per AGENTS.md convention, and update
the data-persistence tables in README.md and DOCKER_HUB.md.
2026-04-23 09:17:39 +02:00
joakimp b37740bcce Fix incorrect 'Linux unaffected' claim in bind-mount caveat
The previous note scoped the single-file bind-mount staleness bug to
Docker Desktop only. It actually affects ALL platforms including native
Linux: Docker bind-mounts the inode, not the path. Editors that do
atomic save (vim, nvim, VS Code, sed -i) create a new inode via
rename(), leaving the container pinned to the old unlinked one. This
is a kernel limitation (moby/moby#15793, open since 2015, unfixable).

Rewrite both the README.md caveat and the docker-compose.yml inline
note to describe the real mechanism (inode replacement), name the
affected editors, note that append-only writes are safe, and link to
the upstream issue.
2026-04-23 00:27:07 +02:00
joakimp 3982e9f18c Document Docker Desktop single-file bind-mount gotcha
On Docker Desktop (macOS/Windows), single-file bind-mounts can
silently stop propagating host edits — the file gets materialized
onto the VM's ext4 disk and reused forever. This affects anyone who
uncomments the ~/.bash_aliases or ~/.inputrc mount lines.

Add a caveat note in README.md's 'Overriding the defaults / Option A'
section with the verification command and the directory-mount
workaround. Add a matching inline NOTE comment in docker-compose.yml
above the commented mount lines. Linux hosts are unaffected.
2026-04-23 00:25:01 +02:00
joakimp 425d53cb57 Update multi-user docs to reflect own-account vs shared-account modes
The shared-machine section in README.md still claimed named volumes
were isolated by directory-name prefixing alone, which was the bug
we just fixed. Rewrite to document both modes (own-account with
automatic $USER fallback, shared-account with explicit SIGNUM) and
explicitly note that the Docker daemon is system-wide — directory
name prefixing is NOT sufficient for volume isolation.
2026-04-22 21:24:59 +02:00
joakimp 8535f73ad3 Ship shell defaults via /etc/skel-devbox so user files are preserved
Publish Docker Image / build-base (push) Successful in 40m28s
Publish Docker Image / build-omos (push) Successful in 50m37s
Publish Docker Image / update-description (push) Successful in 15s
Previous behaviour (e4063b5) COPY'd .bash_aliases and .inputrc
directly into /home/developer/ during image build. That silently
shadowed any host bind-mount or in-container customization for users
upgrading from v1.14.19b — if you'd written your own .bash_aliases
and rebuilt the container, our baked version would overwrite it
without warning.

Ship the files to /etc/skel-devbox/ instead. The entrypoint copies
them to $HOME only if the target file does not already exist, so:

- Fresh containers get the defaults automatically (unchanged)
- Host bind-mounts win (they materialize before the entrypoint runs)
- Existing in-container customizations survive upgrades
- Defaults remain discoverable at /etc/skel-devbox/ for anyone who
  wants to copy, diff, or reset back to upstream

Docs (README.md, DOCKER_HUB.md, deploy/README.md) describe the new
skel layout and the restore/diff commands.
2026-04-21 19:44:29 +02:00
joakimp e4063b5559 Persist bash history and bake shell quality-of-life defaults
Two changes that address a longstanding frustration: bash history is
lost on every container recreate, and the container's ~/.bashrc and
~/.inputrc are stock Debian (no history tuning, no prefix search on
arrow keys, no integrations).

Added a named volume 'devbox-shell-history' mounted at ~/.cache/bash
with HISTFILE pointing there; history now survives 'docker compose up
--force-recreate'. The volume is added to both docker-compose.yml and
docker-compose.shared.yml, and ~/.cache/bash is registered in the
entrypoint ownership-fix loop per the AGENTS.md convention.

Baked rootfs/home/developer/.bash_aliases (sourced automatically by
Debian's default ~/.bashrc) and rootfs/home/developer/.inputrc into
the image. They give new containers: 100k-entry timestamped dedup
history with per-prompt flush, Up/Down arrow prefix history search,
case-insensitive coloured completion, aliases that prefer eza and
bat when present, git shortcuts, interactive rm/mv/cp, zoxide and
fzf (via 'fzf --bash') integration, and a [devbox] prompt marker.
The fzf integration uses 'fzf --bash' because we install fzf from
GitHub releases, not apt — the apt-path key-bindings aren't present.

Users who prefer their host's own shell config can uncomment two
commented bind-mount lines in docker-compose.yml to shadow the
baked defaults.
2026-04-21 19:30:22 +02:00
joakimp 3c19b836cf Clarify OMOS-only features and host-mount portability in docs
Two related documentation fixes for users mounting ~/.config/opencode
from the host:

1. Gate oh-my-opencode-slim references (file and agents) to the OMOS
   variant in the Custom opencode config sections and data persistence
   tables. Base-variant users no longer see oh-my-opencode-slim.json
   listed as if it were always present.

2. Add a portability note warning that host-absolute paths in
   opencode.json (e.g. file:///usr/local/lib/node_modules/... or
   file:///opt/homebrew/...) will not resolve inside the Linux
   container, and to prefer bare package specifiers that work on
   both macOS and Linux hosts.
2026-04-20 21:25:44 +02:00
joakimp b4d2f09e77 Document rsync in README and DOCKER_HUB tool lists 2026-04-20 20:27:09 +02:00
joakimp 3724519402 Document devbox-state volume for TUI settings persistence 2026-04-20 14:53:07 +02:00
joakimp e52ac46237 Document gcc and g++ in README and DOCKER_HUB tool lists 2026-04-20 10:26:52 +02:00
joakimp 0e4525ca53 Add git-crypt and age to base image for encrypted repo support 2026-04-18 16:40:52 +02:00
joakimp 43cecab0f7 Add shared-machine multi-user setup with per-user isolation via SIGNUM
For machines where multiple users share one OS account. Each user gets
isolated containers, config, and named volumes by running docker compose
from their own directory with a unique SIGNUM in .env.
2026-04-17 13:53:51 +02:00
joakimp 210cb7d1a1 Document Python 3.13 included by default in Trixie base image 2026-04-14 13:01:49 +02:00
joakimp 0a3e142b8f Document locale and editor override in README and DOCKER_HUB 2026-04-14 08:37:08 +02:00
joakimp 3e048218c3 Update Python example from 3.12 to 3.14 (current stable) 2026-04-13 19:14:33 +02:00
joakimp e58962a72c Upgrade base image from Debian bookworm to trixie (current stable)
Publish Docker Image / build-base (push) Successful in 32m39s
Publish Docker Image / build-omos (push) Successful in 39m41s
Publish Docker Image / update-description (push) Successful in 18s
Bookworm (Debian 12) reaches EOL June 2026. Trixie (Debian 13) has been
stable since August 2025 with support until 2028/LTS until 2030.
2026-04-13 13:57:45 +02:00
joakimp d2c0447147 Add VS Code server volume to docker-compose examples and persistence tables 2026-04-13 10:20:25 +02:00
joakimp 77a7daf67f Document VS Code Dev Containers integration for local and remote Docker 2026-04-13 10:14:27 +02:00
joakimp b3cfe641bb Document required host directories to prevent root-owned bind mount issues 2026-04-12 23:52:59 +02:00
joakimp f7bd21b9fe Add rustup for on-demand Rust support, document JS/TS development
Publish Docker Image / build-omos (push) Successful in 32m33s
Publish Docker Image / build-base (push) Successful in 32m41s
Publish Docker Image / update-description (push) Successful in 18s
Install rustup-init binary from Rust CDN. Users bootstrap Rust with
'rustup-init -y' — persists via devbox-rustup and devbox-cargo volumes.
Add JavaScript/TypeScript development docs (Node.js + npm in base, Bun in OMOS).
2026-04-12 21:36:57 +02:00
joakimp 1b97d98155 Add uv package manager to base image for on-demand Python support
Publish Docker Image / build-base (push) Successful in 30m41s
Publish Docker Image / build-omos (push) Successful in 35m39s
Publish Docker Image / update-description (push) Failing after 2s
Install uv from GitHub releases (~23MB). Users can install Python with
'uv python install 3.12' — persists across restarts via devbox-uv volume.
Eliminates need for a separate Python image variant.
2026-04-12 20:14:30 +02:00
joakimp 60c83568cd Switch to directory mount for opencode config, update docs with make
Publish Docker Image / build-omos (push) Has been cancelled
Publish Docker Image / update-description (push) Has been cancelled
Publish Docker Image / build-base (push) Has been cancelled
Mount ~/.config/opencode as a directory instead of individual files.
This persists all config changes (opencode.json, oh-my-opencode-slim.json,
skills) across container restarts. Add make to README architecture diagram.
2026-04-12 17:33:45 +02:00
joakimp a183ad7ac6 Add neovim 0.12, bat, eza, zoxide, tmux, htop to base image
Publish Docker Image / update-description (push) Has been cancelled
Publish Docker Image / build-omos (push) Has been cancelled
Publish Docker Image / build-base (push) Has been cancelled
Replace vim-tiny with neovim from GitHub releases (pinned, multi-arch).
Add bat, eza, zoxide from GitHub releases and tmux, htop, patch from apt.
Move tmux from OMOS-only to base image. Set EDITOR=nvim.
Add neovim config mount option to docker-compose and docs.
2026-04-12 16:59:31 +02:00
joakimp e50617d9b9 Clarify tmux is independently useful in OMOS variant documentation
Publish Docker Image / build-and-push (push) Has been cancelled
2026-04-11 16:36:15 +02:00
joakimp 4729131e4e Add optional oh-my-opencode-slim multi-agent orchestration support
Integrate oh-my-opencode-slim as an opt-in feature via INSTALL_OMOS build arg.
A single build arg installs Bun, tmux, and the plugin; runtime activation is
controlled by ENABLE_OMOS and related env vars in the entrypoint.
2026-04-11 16:15:47 +02:00
joakimp 73e94c7e54 Overhaul docs: fix docker-compose to use env_file, add AWS SSO setup guide, clarify exec -u developer 2026-04-10 20:10:18 +02:00
joakimp fa4739e061 Fix exec examples: specify -u developer since container starts as root 2026-04-10 19:40:19 +02:00
joakimp 4112d30a3e Add Linux install instructions for gitleaks 2026-04-10 15:49:10 +02:00
joakimp aaf7d66157 Update non-root user description to reflect UID auto-matching 2026-04-10 15:35:51 +02:00
joakimp 7685facb37 Add runtime UID/GID adjustment to match host workspace owner 2026-04-10 13:57:45 +02:00
joakimp 9b1f7d1028 Add optional skill directory mounts for host-based opencode skills 2026-04-10 13:06:58 +02:00
joakimp ca5efe1007 Document data persistence and storage locations 2026-04-10 10:00:51 +02:00
joakimp 084881b298 Add gitleaks pre-commit hook and bump opencode to 1.4.2 2026-04-09 19:12:27 +02:00
joakimp f40124296d Add usage section: how to connect and run commands inside the container 2026-04-09 14:31:55 +02:00
joakimp 298203a7cd Add AWS CLI v2 for headless SSO/Bedrock authentication
Includes device-code flow docs for browser-less SSO login from
remote/Docker environments.
2026-04-09 14:22:08 +02:00
joakimp 3dfc14c6c1 Initial scaffold: Debian-based opencode v1.4.0 dev container
Dockerfile with Node.js 22, git, ssh, fzf, ripgrep, fd, non-root user.
Entrypoint auto-configures provider from env vars.
docker-compose with workspace mount, SSH keys, and persistent data volume.
2026-04-09 00:26:48 +02:00