Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -245,5 +245,6 @@
},
"postCreateCommand": "./.devcontainer/scripts/postCreateCommand.sh",
"postAttachCommand": "./.devcontainer/scripts/postAttachCommand.sh",
"postStartCommand": "./.devcontainer/scripts/postStartCommand.sh"
"postStartCommand": "./.devcontainer/scripts/postStartCommand.sh",
"waitFor": "postStartCommand"
}
7 changes: 7 additions & 0 deletions .devcontainer/scripts/codebase-memory-mcp-install.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#!/usr/bin/env bash
set -euo pipefail

script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

# Wire the codebase-memory-mcp binary (installed system-wide by the dev_tools
# Ansible role at image-build time) into the current user's agent config.
#
Expand Down Expand Up @@ -74,6 +76,9 @@ restore_claude_json_symlink() {
# and strand later config writes outside the persistent volume.
trap restore_claude_json_symlink EXIT

# Revert any previous patch to codex's config.toml, otherwise codebase-memory-mcp freaks out and refuses to install
"$script_dir/codebase-memory-mcp-patch-codex.py" --revert

install_status=0
CBM_LOG_LEVEL="${CBM_LOG_LEVEL:-debug}" codebase-memory-mcp install -y --force || install_status=$?

Expand All @@ -97,3 +102,5 @@ if ((install_status != 0)); then

exit "$install_status"
fi

"$script_dir/codebase-memory-mcp-patch-codex.py"
64 changes: 64 additions & 0 deletions .devcontainer/scripts/codebase-memory-mcp-patch-codex.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#!/usr/bin/env python3
"""Configure Codex's persistent user settings inside the devcontainer."""

import argparse
import os
from pathlib import Path
import tempfile

import toml

# https://github.com/DeusData/codebase-memory-mcp#environment-variables
CMB_KNOWN_ENV_VARS = [
'CBM_ALLOWED_ROOT',
'CBM_CACHE_DIR',
'CBM_DIAGNOSTICS',
'CBM_DOWNLOAD_URL',
'CBM_LOG_LEVEL',
'CBM_WORKERS',
'CBM_MEM_BUDGET_MB',
'CBM_DUMP_VERIFY_MIN_RATIO',
]


def main(args: argparse.Namespace) -> None:
"""Patch codebase-memory-mcp codex configuration for custom environment."""
codex_home = Path(os.environ.get('CODEX_HOME', Path.home() / '.codex'))
config_path = codex_home / 'config.toml'

codex_home.mkdir(mode=0o700, parents=True, exist_ok=True)
os.chmod(codex_home, 0o700)
config = toml.load(config_path) if config_path.exists() else {}

cbm_server = config.get('mcp_servers', {}).get('codebase-memory-mcp')
if isinstance(cbm_server, dict):
if args.revert:
cbm_server.pop('env_vars', None)
else:
cbm_server['env_vars'] = CMB_KNOWN_ENV_VARS

with tempfile.NamedTemporaryFile(
mode='w',
encoding='utf-8',
dir=codex_home,
prefix='config.toml.',
delete=False,
) as config_file:
toml.dump(config, config_file)
temporary_path = Path(config_file.name)

temporary_path.chmod(0o600)
temporary_path.replace(config_path)


if __name__ == '__main__':
argument_parser = argparse.ArgumentParser(
description='Patch codebase-memory-mcp codex configuration for custom environment.'
)
argument_parser.add_argument(
'--revert',
action='store_true',
help="Revert any previous patch to codex's config.toml",
)
args = argument_parser.parse_args()
main(args)
37 changes: 0 additions & 37 deletions .devcontainer/scripts/configure-codex.py

This file was deleted.

4 changes: 3 additions & 1 deletion .devcontainer/scripts/postStartCommand.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#!/usr/bin/env bash
# This script is run after the container is started, but before the VSCode extension host is started.
# This allows to avoid race conditions and setup safe environment for the extension host to run in.

set -euo pipefail

script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
Expand All @@ -9,7 +12,6 @@ script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
"$script_dir/setup-keyring.sh"
"$script_dir/firewall.sh"
/start-xpra.sh --background
"$script_dir/configure-codex.py"

# Repairs the shared auth.json symlink if a `codex logout` during this container's
# previous run destroyed it; see link-codex-auth.sh for why that can happen.
Expand Down
40 changes: 20 additions & 20 deletions docs/repository-structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ ansible/ + docker/ + catalog publisher source
|
postStartCommand (each start)
|
pre-commit, keyring, firewall, Xpra, Codex policy,
CBM daemon, pre-commit, keyring, firewall, Xpra,
and a workspace catalog override when one exists
```

Expand All @@ -61,25 +61,25 @@ template files below even though it does not need the catalog publisher source.
The default devcontainer surface is the complete tracked `.devcontainer/` directory plus
two root companions:

| Path | Responsibility |
| ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `.devcontainer/devcontainer.json` | Dev Container entry point, features, mounts, ports, editor configuration, and lifecycle commands. |
| `.devcontainer/docker-compose.yml` | Devcontainer service, MCP gateway, worktree mounts, and persistent Claude/Codex volumes. |
| `.devcontainer/devcontainer-init.sh` | Generates host-specific Compose state and creates shared agent volumes before startup. |
| `.devcontainer/devcontainer-lock.json` | Locks the Docker-in-Docker and SSH feature digests. |
| `.devcontainer/firewall-allowlist.txt` | Project-owned allowlist read when the opt-in firewall starts. |
| `.devcontainer/scripts/postCreateCommand.sh` | Sets up persistent Claude and Codex auth state, syncs the uv environment, and installs the image-staged catalog. |
| `.devcontainer/scripts/postStartCommand.sh` | Starts repository hooks, keyring, firewall, Xpra, Codex policy, and workspace catalog override. |
| `.devcontainer/scripts/uv-sync.sh` | Runs `uv sync` and links the cached environment to `.venv`. |
| `.devcontainer/scripts/setup-pre-commit.sh` | Trusts the checkout and installs pre-commit and pre-push hooks. |
| `.devcontainer/scripts/setup-keyring.sh` | Starts and persists the headless keyring used by authenticated tooling. |
| `.devcontainer/scripts/firewall.sh` | Activates the image-provided egress firewall when enabled. |
| `.devcontainer/scripts/configure-codex.py` | Sets devcontainer-only Codex sandbox and approval policy. |
| `.devcontainer/scripts/link-codex-auth.sh` | Persists Codex's `auth.json` in the shared `agentdev-agents-auth` volume and symlinks it into place. |
| `.devcontainer/scripts/reinstall-agentdev-claude.sh` | Installs the staged Claude plugin and overrides it with a workspace marketplace when present. |
| `.devcontainer/scripts/reinstall-agentdev-codex.sh` | Performs the equivalent Codex marketplace/plugin installation. |
| `compose.pins.yml` | Supplies the Renovate-managed tag-plus-digest image override referenced by `devcontainer.json`. |
| `.mcp.json` | Points repository agents at the MCP gateway sidecar. |
| Path | Responsibility |
| ---------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `.devcontainer/devcontainer.json` | Dev Container entry point, features, mounts, ports, editor configuration, and lifecycle commands. |
| `.devcontainer/docker-compose.yml` | Devcontainer service, MCP gateway, worktree mounts, and persistent Claude/Codex volumes. |
| `.devcontainer/devcontainer-init.sh` | Generates host-specific Compose state and creates shared agent volumes before startup. |
| `.devcontainer/devcontainer-lock.json` | Locks the Docker-in-Docker and SSH feature digests. |
| `.devcontainer/firewall-allowlist.txt` | Project-owned allowlist read when the opt-in firewall starts. |
| `.devcontainer/scripts/postCreateCommand.sh` | Sets up persistent Claude and Codex auth state, syncs the uv environment, and installs the image-staged catalog. |
| `.devcontainer/scripts/postStartCommand.sh` | Starts the CBM daemon, repository hooks, keyring, firewall, Xpra, and workspace catalog override. |
| `.devcontainer/scripts/uv-sync.sh` | Runs `uv sync` and links the cached environment to `.venv`. |
| `.devcontainer/scripts/setup-pre-commit.sh` | Trusts the checkout and installs pre-commit and pre-push hooks. |
| `.devcontainer/scripts/setup-keyring.sh` | Starts and persists the headless keyring used by authenticated tooling. |
| `.devcontainer/scripts/firewall.sh` | Activates the image-provided egress firewall when enabled. |
| `.devcontainer/scripts/codebase-memory-mcp-patch-codex.py` | Forwards the CBM environment variables to the Codex MCP entry; `--revert` undoes it before reinstall. |
| `.devcontainer/scripts/link-codex-auth.sh` | Persists Codex's `auth.json` in the shared `agentdev-agents-auth` volume and symlinks it into place. |
| `.devcontainer/scripts/reinstall-agentdev-claude.sh` | Installs the staged Claude plugin and overrides it with a workspace marketplace when present. |
| `.devcontainer/scripts/reinstall-agentdev-codex.sh` | Performs the equivalent Codex marketplace/plugin installation. |
| `compose.pins.yml` | Supplies the Renovate-managed tag-plus-digest image override referenced by `devcontainer.json`. |
| `.mcp.json` | Points repository agents at the MCP gateway sidecar. |

These files are one runtime unit. Copying only `devcontainer.json` and
`docker-compose.yml` leaves direct references unresolved.
Expand Down
Loading