init-home.sh 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. #!/bin/bash
  2. # init-home.sh
  3. #
  4. # Host-side initialization script. Invoked from devcontainer.json's initializeCommand
  5. # before `docker compose up`, so that bind-mount target directories exist with the
  6. # correct ownership/permission on the host. Without this, Docker creates the missing
  7. # host directories as root, breaking writes from the non-root vscode user inside
  8. # the container.
  9. #
  10. # Idempotent: safe to re-run; never destroys existing content.
  11. #
  12. # - Pre-create ~/.claude/, ~/.config/gh/, ~/.config/glab-cli/ on the host so the
  13. # compose bind mounts succeed.
  14. # - Generate .devcontainer/compose.extend.yml as an empty-stub if missing, so
  15. # `docker compose up` does not fail with a missing-file error before the user
  16. # has authored their own extension.
  17. # - Write UID/GID into .devcontainer/.env (merge, do not clobber existing keys)
  18. # so compose.yml can expand ${UID}/${GID} without depending on shell exports.
  19. #
  20. # POSIX-portable (bash + coreutils). No GNU-only flags so macOS/Linux both work.
  21. set -euo pipefail
  22. SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
  23. DEVCONTAINER_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
  24. DEVCONTAINER_ENV="${DEVCONTAINER_DIR}/.env"
  25. COMPOSE_EXTEND="${DEVCONTAINER_DIR}/compose.extend.yml"
  26. # ---------------------------------------------------------------------------
  27. # Pre-create bind-mount target directories on the host.
  28. # mkdir -p is idempotent and preserves existing contents.
  29. # Creating them here (as the host user) prevents Docker from creating them
  30. # as root when the bind mount is first applied.
  31. # ---------------------------------------------------------------------------
  32. mkdir -p \
  33. "${HOME}/.claude" \
  34. "${HOME}/.config/gh" \
  35. "${HOME}/.config/glab-cli"
  36. # ---------------------------------------------------------------------------
  37. # Stub compose.extend.yml: prevents file-not-found errors on `docker compose up`
  38. # for users who have not authored their own overrides yet.
  39. # ---------------------------------------------------------------------------
  40. if [ ! -f "${COMPOSE_EXTEND}" ]; then
  41. cat > "${COMPOSE_EXTEND}" <<'EOF'
  42. services:
  43. {}
  44. EOF
  45. fi
  46. # ---------------------------------------------------------------------------
  47. # Merge UID/GID into .devcontainer/.env without clobbering other keys.
  48. # compose.yml and docker compose auto-load this file as a variable source.
  49. # id -u / id -g are POSIX-standard on both macOS and Linux.
  50. # ---------------------------------------------------------------------------
  51. HOST_UID="$(id -u)"
  52. HOST_GID="$(id -g)"
  53. if [ -f "${DEVCONTAINER_ENV}" ]; then
  54. # Drop any existing UID=/GID= lines, then append fresh values.
  55. tmp_env="$(mktemp)"
  56. grep -Ev '^(UID|GID)=' "${DEVCONTAINER_ENV}" > "${tmp_env}" || true
  57. mv "${tmp_env}" "${DEVCONTAINER_ENV}"
  58. fi
  59. {
  60. echo "UID=${HOST_UID}"
  61. echo "GID=${HOST_GID}"
  62. } >> "${DEVCONTAINER_ENV}"
  63. echo "init-home.sh: initialization complete"
  64. echo " host dirs: ~/.claude, ~/.config/gh, ~/.config/glab-cli"
  65. echo " ${DEVCONTAINER_ENV}: UID=${HOST_UID}, GID=${HOST_GID}"