Skip to content

Migrate devcontainer to Docker Compose and update toolchain#681

Open
greenc-FNAL wants to merge 1 commit into
mainfrom
maintenance/devcontainer-docker-compose
Open

Migrate devcontainer to Docker Compose and update toolchain#681
greenc-FNAL wants to merge 1 commit into
mainfrom
maintenance/devcontainer-docker-compose

Conversation

@greenc-FNAL

@greenc-FNAL greenc-FNAL commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Switch devcontainer.json to use docker-compose.yml for service
definition, volume mounts, and environment variables to improve
configurability and consistency.

Key changes include:

  • Update Dockerfile to use a pinned base image (2026-06-24), install
    additional utilities (jq, tree, yq), and upgrade Node.js to 26.x.
  • Replace kiro-cli with @kilocode/cli installed via npm.
  • Refactor KILO_CONFIG_CONTENT handling: ensure-repos.sh now
    generates a .phlex-kilo.env file on the host which is loaded by
    Docker Compose. This ensures the VS Code plugin receives the correct
    configuration (including the host.docker.internal relay) at startup,
    replacing the previous .bashrc modification in post-create.sh.
  • Remove Copilot-related extensions and settings from the workspace
    and devcontainer configuration.
  • Devcontainer setup

    • Migrated the container definition from devcontainer.json-driven setup to docker-compose.yml for the main service, mounts, and environment wiring.
    • Added a new Compose-based phlex-dev service with workspace/sibling repo mounts, host config mounts, named volumes, and host.docker.internal connectivity.
  • Build/runtime image

    • Pinned the devcontainer base image to phlex-dev:2026-06-24.
    • Expanded the image toolset with jq, tree, yq, podman, ssh, and socat.
    • Upgraded Node.js to 26.x and switched global CLI installation from kiro-cli to @kilocode/cli.
  • Startup/config handling

    • Reworked ensure-repos.sh to generate a host-side .phlex-kilo.env file from ~/.config/kilo/kilo.jsonc, rewriting the provider base URL to use the headroom relay.
    • Removed the old .bashrc-based propagation of KILO_CONFIG_CONTENT from post-create.sh.
  • Workspace/devcontainer cleanup

    • Removed Copilot Chat and related Copilot settings/extensions from the devcontainer/workspace configuration.
    • Updated workspace recommendations to include GitHub Actions and Pull Requests extensions instead.
  • Script/host config changes

    • Simplified host config directory setup in ensure-repos.sh to only ensure gh, kilo, and gnupg paths needed by the new flow.
    • Removed the post-create installation step for kiro-cli.

Switch `devcontainer.json` to use `docker-compose.yml` for service
definition, volume mounts, and environment variables to improve
configurability and consistency.

Key changes include:
- Update `Dockerfile` to use a pinned base image (`2026-06-24`), install
  additional utilities (`jq`, `tree`, `yq`), and upgrade Node.js to 26.x.
- Replace `kiro-cli` with `@kilocode/cli` installed via npm.
- Refactor `KILO_CONFIG_CONTENT` handling: `ensure-repos.sh` now
  generates a `.phlex-kilo.env` file on the host which is loaded by
  Docker Compose. This ensures the VS Code plugin receives the correct
  configuration (including the `host.docker.internal` relay) at startup,
  replacing the previous `.bashrc` modification in `post-create.sh`.
- Remove Copilot-related extensions and settings from the workspace
  and devcontainer configuration.
@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR reworks the devcontainer setup: pins the base image, expands package installs (adds jq/tree/yq, Node.js 26, @kilocode/cli), migrates from a direct Docker build to docker-compose orchestration, removes github.copilot-chat references, and updates repo-setup/post-create scripts to generate a kilo config env file while dropping kiro-cli installation and bashrc export logic.

Changes

Devcontainer Configuration and Tooling Update

Layer / File(s) Summary
Dockerfile base image and dev tooling install
.devcontainer/Dockerfile
Pins base image to phlex-dev:2026-06-24; reworks package install to add jq/tree/yq, installs Node.js 26.x via NodeSource, and globally installs @kilocode/cli with allow-scripts config.
docker-compose service and devcontainer wiring
.devcontainer/docker-compose.yml, .devcontainer/devcontainer.json
Adds new compose file defining the phlex-dev service with mounts, env_file, env vars, and named volumes; devcontainer.json switches to reference this compose service and trims remoteEnv to KILO_API_KEY only.
Remove copilot-chat extension references
.devcontainer/codespace.code-workspace, .devcontainer/devcontainer.json
Drops github.copilot-chat from recommendations, settings, and extensions; adds GitHub Actions/PR extensions; removes ms-vscode.vscode-websearchforcopilot.
Kilo config env-file generation and post-create cleanup
.devcontainer/ensure-repos.sh, .devcontainer/post-create.sh
ensure-repos.sh trims bind-mount dir creation and generates ~/.phlex-kilo.env with rewritten fnal-litellm baseURL; post-create.sh removes bashrc KILO_CONFIG_CONTENT_DOCKER export and the kiro-cli install step.

Sequence Diagram(s)

sequenceDiagram
  participant ensurereposh as ensure-repos.sh
  participant kilojsonc as kilo.jsonc
  participant envfile as .phlex-kilo.env
  participant DockerCompose
  participant phlexdev as phlex-dev service
  ensurereposh->>kilojsonc: read existing config
  ensurereposh->>ensurereposh: rewrite fnal-litellm baseURL to host.docker.internal
  ensurereposh->>envfile: write KILO_CONFIG_CONTENT
  DockerCompose->>envfile: load via env_file
  DockerCompose->>phlexdev: start service with mounted volumes
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • marcpaterno
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly captures the main changes: moving the devcontainer to Docker Compose and updating the toolchain.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch maintenance/devcontainer-docker-compose

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.devcontainer/docker-compose.yml:
- Around line 20-21: The devcontainer compose config currently treats
${HOME}/.phlex-kilo.env as required even though ensure-repos.sh only creates it
conditionally, so update the wiring to avoid startup failure when the file is
missing. Either change ensure-repos.sh so it always creates .phlex-kilo.env
(even if empty) or adjust the env_file entry in docker-compose.yml to use an
optional/conditional path. Refer to ensure-repos.sh and the env_file setting in
docker-compose.yml when making the fix.

In @.devcontainer/Dockerfile:
- Line 107: Remove the global npm update step from the devcontainer image build
so the image does not drift against the live registry on each rebuild. Update
the Dockerfile build steps to install only the required tool, and pin that
install to an explicit `@kilocode/cli` version instead of relying on npm -g
update. Use the existing Dockerfile package-install section to make the change.
- Around line 108-109: The install flow in the Dockerfile still allows lifecycle
scripts to run because `npm config set allow-scripts=...` is only policy
metadata. Update the `npm install -g `@kilocode/cli`` step to actually block
install-time scripts, using `--ignore-scripts` or the npm allowlist mechanism
supported by this image’s npm version, and keep the change localized to the
install commands in the Dockerfile.

In @.devcontainer/ensure-repos.sh:
- Around line 192-199: The env file consumed by docker-compose is only written
inside the kilo.jsonc existence check, so .phlex-kilo.env can be missing or
stale on fresh or rerun setups. Update ensure-repos.sh so it always creates or
refreshes ${HOME}/.phlex-kilo.env before Compose starts, using the
KILO_CONFIG_CONTENT assignment path in the kilo.jsonc handling block and
ensuring the file is cleared or set to an empty value when the config is absent.
- Around line 197-198: Escape the JSONC-derived KILO_CONFIG_CONTENT before
writing the .phlex-kilo.env assignment, since ensure-repos.sh currently echoes a
single-quoted value that will break if the content contains apostrophes. Update
the logic around the KILO_CONFIG_CONTENT transformation and the echo that writes
"${HOME}/.phlex-kilo.env" so any embedded single quotes are safely escaped or
encoded before persisting the env file.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 4568aea2-d948-4677-8e64-99f520ae50ec

📥 Commits

Reviewing files that changed from the base of the PR and between cf6781a and d3ab6d9.

📒 Files selected for processing (6)
  • .devcontainer/Dockerfile
  • .devcontainer/codespace.code-workspace
  • .devcontainer/devcontainer.json
  • .devcontainer/docker-compose.yml
  • .devcontainer/ensure-repos.sh
  • .devcontainer/post-create.sh
💤 Files with no reviewable changes (2)
  • .devcontainer/codespace.code-workspace
  • .devcontainer/post-create.sh
📜 Review details
⚠️ CI failures not shown inline (8)

GitHub Actions: greenc-FNAL checking YAML files / yaml-check: greenc-FNAL checking YAML files

Conclusion: failure

View job details

##[group]Run REPO_NAME="${REPO##*/}"
 �[36;1mREPO_NAME="${REPO##*/}"�[0m
 �[36;1mif [ "success" = "success" ]; then�[0m
 �[36;1m  echo "✅ YAML check passed."�[0m
 �[36;1melse�[0m
 �[36;1m  echo "::error::YAML check failed."�[0m

GitHub Actions: greenc-FNAL checking YAML files / 0_yaml-check.txt: greenc-FNAL checking YAML files

Conclusion: failure

View job details

##[group]Run REPO_NAME="${REPO##*/}"
 �[36;1mREPO_NAME="${REPO##*/}"�[0m
 �[36;1mif [ "success" = "success" ]; then�[0m
 �[36;1m  echo "✅ YAML check passed."�[0m
 �[36;1melse�[0m
 �[36;1m  echo "::error::YAML check failed."�[0m

GitHub Actions: CodeQL Analysis / 2_determine-languages.txt: Migrate devcontainer to Docker Compose and update toolchain

Conclusion: failure

View job details

##[group]Run # If detection was skipped, use all languages or the provided language-matrix
 �[36;1m# If detection was skipped, use all languages or the provided language-matrix�[0m
 �[36;1mif [ "${SKIP_DETECTION}" = "true" ]; then�[0m
 �[36;1m  if [ "${GITHUB_EVENT_NAME}" = "workflow_call" ] && [ -n "${LANGUAGE_MATRIX}" ]; then�[0m
 �[36;1m    # Validate that language-matrix is valid JSON�[0m
 �[36;1m    if ! echo "${LANGUAGE_MATRIX}" | python3 -c "import sys, json; json.load(sys.stdin)" 2>/dev/null; then�[0m
 �[36;1m      echo "::error::Invalid language-matrix input: must be valid JSON array"�[0m

GitHub Actions: CodeQL Analysis / determine-languages: Migrate devcontainer to Docker Compose and update toolchain

Conclusion: failure

View job details

##[group]Run # If detection was skipped, use all languages or the provided language-matrix
 �[36;1m# If detection was skipped, use all languages or the provided language-matrix�[0m
 �[36;1mif [ "${SKIP_DETECTION}" = "true" ]; then�[0m
 �[36;1m  if [ "${GITHUB_EVENT_NAME}" = "workflow_call" ] && [ -n "${LANGUAGE_MATRIX}" ]; then�[0m
 �[36;1m    # Validate that language-matrix is valid JSON�[0m
 �[36;1m    if ! echo "${LANGUAGE_MATRIX}" | python3 -c "import sys, json; json.load(sys.stdin)" 2>/dev/null; then�[0m
 �[36;1m      echo "::error::Invalid language-matrix input: must be valid JSON array"�[0m

GitHub Actions: greenc-FNAL checking Python code / python-check: greenc-FNAL checking Python code

Conclusion: failure

View job details

##[group]Run REPO_NAME="${REPO##*/}"
 �[36;1mREPO_NAME="${REPO##*/}"�[0m
 �[36;1mif [ "success" = 'success' ] && [ "success" = 'success' ]; then�[0m
 �[36;1m  echo "✅ Python checks passed."�[0m
 �[36;1melse�[0m
 �[36;1m  echo "::error::Python checks failed. Comment '@${REPO_NAME}bot python-fix' on the PR to attempt auto-fix."�[0m

GitHub Actions: greenc-FNAL checking Python code / 0_python-check.txt: greenc-FNAL checking Python code

Conclusion: failure

View job details

##[group]Run REPO_NAME="${REPO##*/}"
 �[36;1mREPO_NAME="${REPO##*/}"�[0m
 �[36;1mif [ "success" = 'success' ] && [ "success" = 'success' ]; then�[0m
 �[36;1m  echo "✅ Python checks passed."�[0m
 �[36;1melse�[0m
 �[36;1m  echo "::error::Python checks failed. Comment '@${REPO_NAME}bot python-fix' on the PR to attempt auto-fix."�[0m

GitHub Actions: greenc-FNAL checking Python code / 1_scripts-test.txt: greenc-FNAL checking Python code

Conclusion: failure

View job details

%]
 scripts/test/test_check_codeql_alerts.py::TestMainSarifMode::test_no_alerts_returns_zero_no_comment PASSED [ 24%]
 scripts/test/test_check_codeql_alerts.py::TestMainSarifMode::test_below_threshold_alert_not_reported PASSED [ 24%]
 scripts/test/test_check_codeql_alerts.py::TestMainSarifMode::test_missing_sarif_exits_nonzero PASSED [ 24%]
 scripts/test/test_check_codeql_alerts.py::TestMainSarifMode::test_github_output_written PASSED [ 24%]
 scripts/test/test_check_codeql_alerts.py::TestMainSarifMode::test_github_output_false_when_no_alerts PASSED [ 25%]
 scripts/test/test_check_codeql_alerts.py::TestMainSarifMode::test_directory_of_sarif_files PASSED [ 25%]
 scripts/test/test_check_codeql_alerts.py::TestMainSarifMode::test_sarif_mode_pr_ref_produces_filtered_url PASSED [ 25%]
 scripts/test/test_check_codeql_alerts.py::TestMainSarifMode::test_non_integer_pr_ref_no_filtered_url PASSED [ 25%]
 scripts/test/test_check_codeql_alerts.py::TestMainApiMode::test_api_mode_new_alert PASSED [ 25%]
 scripts/test/test_check_codeql_alerts.py::TestMainApiMode::test_api_mode_min_level_filtering PASSED [ 26%]
 scripts/test/test_check_codeql_alerts.py::TestMainApiMode::test_api_mode_github_api_error_exits_2 PASSED [ 26%]
 scripts/test/test_check_codeql_alerts.py::TestMainApiMode::test_api_mode_missing_github_repository_exits_2 PASSED [ 26%]
 scripts/test/test_check_codeql_alerts.py::TestMainApiMode::test_api_mode_skipped_when_sarif_has_baseline PASSED [ 26%]
 scripts/test/test_check_codeql_alerts.py::TestMainApiModeWithPrRef::test_api_mode_pr_ref_produces_filtered_url PASSED [ 27%]
 scripts/test/test_check_codeql_alerts.py::TestMainEntrypoint::test_entrypoint_no_alerts_exits_zero PASSED [ 27%]
 scripts/test/test_clang_tidy_check_summary.py::TestLoadDiagnostics::test_reads_from_file PASSED [ 27%]
 scripts/test/test_clang_tidy_check_summary.py::TestLoadDiagnostics::test_reads_from_stdin PASSED [ 27%]
 scripts/test/test_clang_tidy_check_summary.py::TestLoadDiagnostics::test_invalid_...

GitHub Actions: greenc-FNAL checking Python code / scripts-test: greenc-FNAL checking Python code

Conclusion: failure

View job details

##[group]Run codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f
 with:
   files: coverage-scripts.xml
   flags: scripts
   name: phlex-scripts-coverage
   fail_ci_if_error: false
   verbose: true
   root_dir: phlex-src
   ***REDACTED***
   disable_file_fixes: false
   disable_search: false
   disable_safe_directory: false
   disable_telem: false
   dry_run: false
   git_service: github
   gcov_executable: gcov
   handle_no_reports_found: false
   recurse_submodules: false
   run_command: upload-coverage
   skip_validation: false
   use_legacy_upload_endpoint: false
   use_oidc: false
   use_pypi: false
   version: latest
 env:
   CODECOV_***REDACTED***
   UV_PYTHON_INSTALL_DIR: /home/runner/work/_temp/uv-python-dir
   UV_CACHE_DIR: /home/runner/work/_temp/setup-uv-cache
 ##[endgroup]
 ##[group]Run missing_deps=""
 �[36;1mmissing_deps=""�[0m
 �[36;1m�[0m
 �[36;1m# Check for always-required commands�[0m
 �[36;1mfor cmd in bash git curl; do�[0m
 �[36;1m  if ! command -v "$cmd" >/dev/null 2>&1; then�[0m
 �[36;1m    missing_deps="$missing_deps $cmd"�[0m
 �[36;1m  fi�[0m
 �[36;1mdone�[0m
 �[36;1m�[0m
 �[36;1m# Check for gpg only if validation is not being skipped�[0m
 �[36;1mif [ "$INPUT_SKIP_VALIDATION" != "true" ]; then�[0m
 �[36;1m  if ! command -v gpg >/dev/null 2>&1; then�[0m
 �[36;1m    missing_deps="$missing_deps gpg"�[0m
 �[36;1m  fi�[0m
 �[36;1mfi�[0m
 �[36;1m�[0m
 �[36;1m# Report missing required dependencies�[0m
 �[36;1mif [ -n "$missing_deps" ]; then�[0m
 �[36;1m  echo "Error: The following required dependencies are missing:$missing_deps"�[0m
 �[36;1m  echo "Please install these dependencies before using this action."�[0m
 �[36;1m  exit 1�[0m
 �[36;1mfi�[0m
 �[36;1m�[0m
 �[36;1mecho "All required system dependencies are available."�[0m
 shell: /usr/bin/sh -e {0}
 env:
   CODECOV_***REDACTED***
   UV_PYTHON_INSTALL_DIR: /home/runner/work/_temp/uv-python-dir
   UV_CACHE_DIR: /home/runner/work/_temp/setup-uv-cache
   INPUT_SKIP_VALIDATION: false
 ...
🧰 Additional context used
🪛 Checkov (3.3.2)
.devcontainer/Dockerfile

[low] 1-118: Ensure that HEALTHCHECK instructions have been added to container images

(CKV_DOCKER_2)


[low] 1-118: Ensure that a user for the container has been created

(CKV_DOCKER_3)

🪛 Hadolint (2.14.0)
.devcontainer/Dockerfile

[info] 93-93: Multiple consecutive RUN instructions. Consider consolidation.

(DL3059)


[info] 105-105: Multiple consecutive RUN instructions. Consider consolidation.

(DL3059)

🪛 Trivy (0.69.3)
.devcontainer/Dockerfile

[error] 1-1: Image user should not be 'root'

Specify at least 1 USER command in Dockerfile with non-root user as argument

Rule: DS-0002

Learn more

(IaC/Dockerfile)


[info] 1-1: No HEALTHCHECK defined

Add HEALTHCHECK instruction in your Dockerfile

Rule: DS-0026

Learn more

(IaC/Dockerfile)

🔇 Additional comments (1)
.devcontainer/devcontainer.json (1)

3-9: LGTM!

Comment on lines +20 to +21
env_file:
- ${HOME}/.phlex-kilo.env

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

This env_file is mandatory, but its producer is conditional.

.devcontainer/ensure-repos.sh:189-199 only creates ${HOME}/.phlex-kilo.env when ~/.config/kilo/kilo.jsonc exists. On a fresh machine without that file, Compose will try to load a missing env file and the devcontainer can fail before startup. Either make ensure-repos.sh always write an empty .phlex-kilo.env, or switch this wiring to an optional env-file path.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.devcontainer/docker-compose.yml around lines 20 - 21, The devcontainer
compose config currently treats ${HOME}/.phlex-kilo.env as required even though
ensure-repos.sh only creates it conditionally, so update the wiring to avoid
startup failure when the file is missing. Either change ensure-repos.sh so it
always creates .phlex-kilo.env (even if empty) or adjust the env_file entry in
docker-compose.yml to use an optional/conditional path. Refer to ensure-repos.sh
and the env_file setting in docker-compose.yml when making the fix.

Comment thread .devcontainer/Dockerfile

RUN bash <<'INSTALL_NPM_PACKAGES'
set -euo pipefail
npm -g update

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Drop npm -g update from the image build.

This makes the devcontainer drift on every rebuild against the live registry, which undercuts the new pinning work here. Install only the tool you need, ideally at an explicit @kilocode/cli version.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.devcontainer/Dockerfile at line 107, Remove the global npm update step from
the devcontainer image build so the image does not drift against the live
registry on each rebuild. Update the Dockerfile build steps to install only the
required tool, and pin that install to an explicit `@kilocode/cli` version instead
of relying on npm -g update. Use the existing Dockerfile package-install section
to make the change.

Comment thread .devcontainer/Dockerfile
Comment on lines +108 to +109
npm config set allow-scripts=@kilocode/cli --location=user
npm install -g @kilocode/cli

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Does npm support an allow-scripts config key for selectively allowing lifecycle scripts for one package, and what is the supported way to restrict install scripts in current npm?

💡 Result:

Yes, npm now supports an allowScripts configuration to selectively permit lifecycle scripts for specific packages, a feature introduced as part of an opt-in security policy in recent versions of npm (starting with v11.10.0) [1]. How to Manage Lifecycle Scripts: 1. Project-Level Control (Recommended): The supported way to manage this in a project is using the allowScripts field in your package.json [2][3]. You can maintain this list using two built-in commands: - npm approve-scripts : Adds a package to the allowlist in your package.json [3][4]. By default, this pins the approval to the specific version currently installed [3][5]. - npm deny-scripts : Explicitly denies a package, ensuring it cannot run install scripts even if future versions are updated [4]. 2. One-off and Global Contexts: For global installs (npm install -g) or one-off executions (npm exec, npx), where no project package.json exists, you can use the --allow-scripts CLI flag (e.g., --allow-scripts=pkg1,pkg2) [2][3][6]. Note that using --allow-scripts during a project-scoped npm install is considered an error, as team-wide policy should be managed via package.json or.npmrc to avoid inconsistency [2][7][6]. 3. Legacy/Alternative Restriction: If you want to globally restrict install scripts (the most secure approach), you can continue to use the ignore-scripts configuration [8][9][10]. - You can set this globally by running: npm config set ignore-scripts true [10]. - Alternatively, you can run any install command with the flag: npm install --ignore-scripts [8][9][10]. In the current version, the allowScripts policy is advisory; unapproved scripts will still execute, but they will be reported in an end-of-install summary [11][1][4]. Future releases of npm are planned to make these policies a hard block [2][1][4]. Top results: [2][3][11][6][4]

Citations:


allow-scripts doesn’t harden this install.
npm config set allow-scripts=@kilocode/cli is policy metadata, not a blocker, so `npm install -g `@kilocode/cli can still run lifecycle scripts. If the goal is to prevent install-time script execution, use --ignore-scripts or the npm allowlist mechanism supported by the image’s npm version.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.devcontainer/Dockerfile around lines 108 - 109, The install flow in the
Dockerfile still allows lifecycle scripts to run because `npm config set
allow-scripts=...` is only policy metadata. Update the `npm install -g
`@kilocode/cli`` step to actually block install-time scripts, using
`--ignore-scripts` or the npm allowlist mechanism supported by this image’s npm
version, and keep the change localized to the install commands in the
Dockerfile.

Comment on lines +192 to +199
if [ -f "${HOME}/.config/kilo/kilo.jsonc" ]; then
# Replace the baseURL for fnal-litellm specifically.
# The range /"fnal-litellm"/,/baseURL/ ensures we only modify the correct provider.
# We avoid stripping comments with sed to prevent corrupting URLs (https://),
# as the Kilo plugin's JSONC parser handles comments correctly.
KILO_CONFIG_CONTENT="$(perl -0777 -pe 's|("fnal-litellm".*?)"baseURL":\s*"[^"]*"|$1"baseURL": "http://host.docker.internal:'${HEADROOM_RELAY_PORT}'"|s; s/"[^"]*"(*SKIP)(*F)|\/\/.*//g; s/^\s+//gm; s/\n//g' "${HOME}/.config/kilo/kilo.jsonc")"
echo "KILO_CONFIG_CONTENT='${KILO_CONFIG_CONTENT}'" > "${HOME}/.phlex-kilo.env"
fi

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

Always create the env file Compose consumes.

.devcontainer/docker-compose.yml loads ${HOME}/.phlex-kilo.env unconditionally, but Line 192 only writes it when kilo.jsonc exists. Fresh hosts can fail before the devcontainer starts, and reruns can leave stale KILO_CONFIG_CONTENT if the config is removed.

🐛 Proposed fix
 # Generate .env file for the devcontainer to provide KILO_CONFIG_CONTENT
 # to the VS Code plugin. This must be done on the host because the plugin
 # needs this environment variable at server startup.
+KILO_ENV_FILE="${HOME}/.phlex-kilo.env"
+: > "${KILO_ENV_FILE}"
 if [ -f "${HOME}/.config/kilo/kilo.jsonc" ]; then
@@
-  echo "KILO_CONFIG_CONTENT='${KILO_CONFIG_CONTENT}'" > "${HOME}/.phlex-kilo.env"
+  echo "KILO_CONFIG_CONTENT='${KILO_CONFIG_CONTENT}'" > "${KILO_ENV_FILE}"
 fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if [ -f "${HOME}/.config/kilo/kilo.jsonc" ]; then
# Replace the baseURL for fnal-litellm specifically.
# The range /"fnal-litellm"/,/baseURL/ ensures we only modify the correct provider.
# We avoid stripping comments with sed to prevent corrupting URLs (https://),
# as the Kilo plugin's JSONC parser handles comments correctly.
KILO_CONFIG_CONTENT="$(perl -0777 -pe 's|("fnal-litellm".*?)"baseURL":\s*"[^"]*"|$1"baseURL": "http://host.docker.internal:'${HEADROOM_RELAY_PORT}'"|s; s/"[^"]*"(*SKIP)(*F)|\/\/.*//g; s/^\s+//gm; s/\n//g' "${HOME}/.config/kilo/kilo.jsonc")"
echo "KILO_CONFIG_CONTENT='${KILO_CONFIG_CONTENT}'" > "${HOME}/.phlex-kilo.env"
fi
KILO_ENV_FILE="${HOME}/.phlex-kilo.env"
: > "${KILO_ENV_FILE}"
if [ -f "${HOME}/.config/kilo/kilo.jsonc" ]; then
# Replace the baseURL for fnal-litellm specifically.
# The range /"fnal-litellm"/,/baseURL/ ensures we only modify the correct provider.
# We avoid stripping comments with sed to prevent corrupting URLs (https://),
# as the Kilo plugin's JSONC parser handles comments correctly.
KILO_CONFIG_CONTENT="$(perl -0777 -pe 's|("fnal-litellm".*?)"baseURL":\s*"[^"]*"|$1"baseURL": "http://host.docker.internal:'${HEADROOM_RELAY_PORT}'"|s; s/"[^"]*"(*SKIP)(*F)|\/\/.*//g; s/^\s+//gm; s/\n//g' "${HOME}/.config/kilo/kilo.jsonc")"
echo "KILO_CONFIG_CONTENT='${KILO_CONFIG_CONTENT}'" > "${KILO_ENV_FILE}"
fi
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.devcontainer/ensure-repos.sh around lines 192 - 199, The env file consumed
by docker-compose is only written inside the kilo.jsonc existence check, so
.phlex-kilo.env can be missing or stale on fresh or rerun setups. Update
ensure-repos.sh so it always creates or refreshes ${HOME}/.phlex-kilo.env before
Compose starts, using the KILO_CONFIG_CONTENT assignment path in the kilo.jsonc
handling block and ensuring the file is cleared or set to an empty value when
the config is absent.

Comment on lines +197 to +198
KILO_CONFIG_CONTENT="$(perl -0777 -pe 's|("fnal-litellm".*?)"baseURL":\s*"[^"]*"|$1"baseURL": "http://host.docker.internal:'${HEADROOM_RELAY_PORT}'"|s; s/"[^"]*"(*SKIP)(*F)|\/\/.*//g; s/^\s+//gm; s/\n//g' "${HOME}/.config/kilo/kilo.jsonc")"
echo "KILO_CONFIG_CONTENT='${KILO_CONFIG_CONTENT}'" > "${HOME}/.phlex-kilo.env"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

rg -n --hidden --glob '!**/.git/**' '\.phlex-kilo\.env|KILO_CONFIG_CONTENT|ensure-repos\.sh' .

Repository: Framework-R-D/phlex

Length of output: 1058


🏁 Script executed:

sed -n '1,80p' .devcontainer/docker-compose.yml

Repository: Framework-R-D/phlex

Length of output: 1211


🌐 Web query:

Docker Compose env_file single quotes escape rules apostrophe dotenv syntax

💡 Result:

In Docker Compose, environment files used with the env_file attribute follow specific parsing rules that differ from standard shell or some other dotenv implementations [1][2]. When using single quotes in these files, the following rules apply: Literal Interpretation: Single-quoted values are treated literally by Docker Compose [3]. No variable interpolation (e.g., $VAR) or special escape sequences (like \n or \t) are processed inside single quotes [3]. Use single quotes when you need to preserve characters that might otherwise be interpreted as placeholders or special escape sequences [1][3][4]. Escaping Single Quotes: If you need to include a literal single quote within a single-quoted string, you can escape it using a backslash (\) [3]. For example, VAR='Let\'s go!' will correctly resolve to the value Let's go! [3]. Inclusion of Quotes: A notable difference between Docker Compose and some other parsers is how it handles the quotes themselves. In Docker Compose, if a value is wrapped in single or double quotes, the quotes are stripped during the parsing process, and the remaining literal content is passed to the container [3]. This means VAR='value' results in value inside your container, not 'value' [3]. Comparison to Other Parsers: - Variable Interpolation: Unlike unquoted or double-quoted values, single-quoted values in Docker Compose are explicitly protected from variable interpolation [3]. - Escape Sequences: While double-quoted values in Docker Compose support common shell escape sequences (like \n, \r, \t, and \\), single-quoted values do not, except for escaping the single quote character itself [3]. - Portability: Because there is no universal specification for dotenv files, behavior can vary significantly between different tools (e.g., Docker Compose, Node.js dotenv, Python-dotenv) [1][2]. Docker Compose parsing is managed by the compose-go library, which is designed to handle interpolation and specific quoting rules [1][2][5]. If you require high portability across different environments or tools, avoid relying on complex quoting or interpolation features where possible [1].

Citations:


Escape KILO_CONFIG_CONTENT before writing the Compose env file. .devcontainer/docker-compose.yml loads ${HOME}/.phlex-kilo.env via env_file, and a raw ' inside the JSONC-derived value will break the single-quoted assignment or truncate it. Escape embedded apostrophes before writing the line.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.devcontainer/ensure-repos.sh around lines 197 - 198, Escape the
JSONC-derived KILO_CONFIG_CONTENT before writing the .phlex-kilo.env assignment,
since ensure-repos.sh currently echoes a single-quoted value that will break if
the content contains apostrophes. Update the logic around the
KILO_CONFIG_CONTENT transformation and the echo that writes
"${HOME}/.phlex-kilo.env" so any embedded single quotes are safely escaped or
encoded before persisting the env file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant