container-superposition 0.1.6 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (238) hide show
  1. package/README.md +24 -15
  2. package/dist/scripts/init.js +1 -1534
  3. package/dist/scripts/init.js.map +1 -1
  4. package/dist/tool/cli/args.d.ts +20 -0
  5. package/dist/tool/cli/args.d.ts.map +1 -0
  6. package/dist/tool/cli/args.js +325 -0
  7. package/dist/tool/cli/args.js.map +1 -0
  8. package/dist/tool/cli/run.d.ts +2 -0
  9. package/dist/tool/cli/run.d.ts.map +1 -0
  10. package/dist/tool/cli/run.js +318 -0
  11. package/dist/tool/cli/run.js.map +1 -0
  12. package/dist/tool/commands/adopt.d.ts.map +1 -1
  13. package/dist/tool/commands/adopt.js +1 -27
  14. package/dist/tool/commands/adopt.js.map +1 -1
  15. package/dist/tool/commands/doctor.d.ts +3 -0
  16. package/dist/tool/commands/doctor.d.ts.map +1 -1
  17. package/dist/tool/commands/doctor.js +1068 -70
  18. package/dist/tool/commands/doctor.js.map +1 -1
  19. package/dist/tool/commands/explain.d.ts.map +1 -1
  20. package/dist/tool/commands/explain.js +18 -0
  21. package/dist/tool/commands/explain.js.map +1 -1
  22. package/dist/tool/commands/migrate.d.ts +7 -0
  23. package/dist/tool/commands/migrate.d.ts.map +1 -0
  24. package/dist/tool/commands/migrate.js +52 -0
  25. package/dist/tool/commands/migrate.js.map +1 -0
  26. package/dist/tool/questionnaire/answers.d.ts +16 -0
  27. package/dist/tool/questionnaire/answers.d.ts.map +1 -0
  28. package/dist/tool/questionnaire/answers.js +102 -0
  29. package/dist/tool/questionnaire/answers.js.map +1 -0
  30. package/dist/tool/questionnaire/composer.d.ts +3 -3
  31. package/dist/tool/questionnaire/composer.d.ts.map +1 -1
  32. package/dist/tool/questionnaire/composer.js +902 -37
  33. package/dist/tool/questionnaire/composer.js.map +1 -1
  34. package/dist/tool/questionnaire/presets.d.ts +60 -0
  35. package/dist/tool/questionnaire/presets.d.ts.map +1 -0
  36. package/dist/tool/questionnaire/presets.js +164 -0
  37. package/dist/tool/questionnaire/presets.js.map +1 -0
  38. package/dist/tool/questionnaire/questionnaire.d.ts +10 -0
  39. package/dist/tool/questionnaire/questionnaire.d.ts.map +1 -0
  40. package/dist/tool/questionnaire/questionnaire.js +580 -0
  41. package/dist/tool/questionnaire/questionnaire.js.map +1 -0
  42. package/dist/tool/schema/manifest-migrations.d.ts +5 -0
  43. package/dist/tool/schema/manifest-migrations.d.ts.map +1 -1
  44. package/dist/tool/schema/manifest-migrations.js +45 -0
  45. package/dist/tool/schema/manifest-migrations.js.map +1 -1
  46. package/dist/tool/schema/overlay-loader.d.ts.map +1 -1
  47. package/dist/tool/schema/overlay-loader.js +25 -0
  48. package/dist/tool/schema/overlay-loader.js.map +1 -1
  49. package/dist/tool/schema/project-config.d.ts +14 -2
  50. package/dist/tool/schema/project-config.d.ts.map +1 -1
  51. package/dist/tool/schema/project-config.js +277 -34
  52. package/dist/tool/schema/project-config.js.map +1 -1
  53. package/dist/tool/schema/target-rules.d.ts +78 -0
  54. package/dist/tool/schema/target-rules.d.ts.map +1 -0
  55. package/dist/tool/schema/target-rules.js +367 -0
  56. package/dist/tool/schema/target-rules.js.map +1 -0
  57. package/dist/tool/schema/types.d.ts +123 -12
  58. package/dist/tool/schema/types.d.ts.map +1 -1
  59. package/dist/tool/utils/merge.d.ts.map +1 -1
  60. package/dist/tool/utils/merge.js +9 -0
  61. package/dist/tool/utils/merge.js.map +1 -1
  62. package/dist/tool/utils/parameters.d.ts +76 -0
  63. package/dist/tool/utils/parameters.d.ts.map +1 -0
  64. package/dist/tool/utils/parameters.js +125 -0
  65. package/dist/tool/utils/parameters.js.map +1 -0
  66. package/dist/tool/utils/paths.d.ts +2 -0
  67. package/dist/tool/utils/paths.d.ts.map +1 -0
  68. package/dist/tool/utils/paths.js +31 -0
  69. package/dist/tool/utils/paths.js.map +1 -0
  70. package/docs/creating-overlays.md +151 -2
  71. package/docs/deployment-targets.md +88 -56
  72. package/docs/examples.md +20 -17
  73. package/docs/filesystem-contract.md +5 -0
  74. package/docs/minimal-and-editor.md +65 -5
  75. package/docs/overlay-imports.md +202 -101
  76. package/docs/overlays.md +162 -34
  77. package/docs/quick-reference.md +99 -0
  78. package/docs/specs/003-mkdocs2-overlay/spec.md +114 -0
  79. package/docs/specs/004-doctor-fix/spec.md +70 -0
  80. package/docs/specs/005-cuda-overlay/spec.md +101 -0
  81. package/docs/specs/006-rocm-overlay/spec.md +109 -0
  82. package/docs/specs/007-init-project-file/spec.md +66 -0
  83. package/docs/specs/007-target-aware-generation/spec.md +126 -0
  84. package/docs/specs/008-project-file-canonical/spec.md +83 -0
  85. package/docs/specs/009-project-env/spec.md +147 -0
  86. package/docs/specs/010-compose-env-materialization/spec.md +130 -0
  87. package/docs/specs/011-overlay-parameters/spec.md +235 -0
  88. package/overlays/.shared/README.md +105 -21
  89. package/overlays/.shared/compose/common-healthchecks.md +60 -0
  90. package/overlays/.shared/compose/nvidia-gpu-devcontainer.yml +22 -0
  91. package/overlays/.shared/vscode/recommended-extensions.json +15 -11
  92. package/overlays/alertmanager/setup.sh +4 -19
  93. package/overlays/alertmanager/verify.sh +8 -9
  94. package/overlays/all/README.md +43 -0
  95. package/overlays/all/devcontainer.patch.json +6 -0
  96. package/overlays/all/overlay.yml +14 -0
  97. package/overlays/amp/setup.sh +5 -0
  98. package/overlays/bun/setup.sh +10 -1
  99. package/overlays/bun/verify.sh +6 -1
  100. package/overlays/claude-code/setup.sh +5 -0
  101. package/overlays/cloudflared/setup.sh +9 -12
  102. package/overlays/codex/README.md +9 -6
  103. package/overlays/codex/devcontainer.patch.json +7 -1
  104. package/overlays/codex/setup.sh +5 -0
  105. package/overlays/codex/verify.sh +8 -0
  106. package/overlays/comfyui/.env.example +34 -0
  107. package/overlays/comfyui/README.md +342 -0
  108. package/overlays/comfyui/devcontainer.patch.json +15 -0
  109. package/overlays/comfyui/docker-compose.yml +39 -0
  110. package/overlays/comfyui/overlay.yml +20 -0
  111. package/overlays/comfyui/setup.sh +36 -0
  112. package/overlays/comfyui/verify.sh +103 -0
  113. package/overlays/commitlint/setup.sh +5 -0
  114. package/overlays/cuda/README.md +179 -0
  115. package/overlays/cuda/devcontainer.patch.json +7 -0
  116. package/overlays/cuda/overlay.yml +17 -0
  117. package/overlays/cuda/setup.sh +32 -0
  118. package/overlays/cuda/verify.sh +38 -0
  119. package/overlays/devcontainer-cli/README.md +50 -0
  120. package/overlays/devcontainer-cli/devcontainer.patch.json +13 -0
  121. package/overlays/devcontainer-cli/overlay.yml +16 -0
  122. package/overlays/devcontainer-cli/setup.sh +14 -0
  123. package/overlays/direnv/devcontainer.patch.json +6 -0
  124. package/overlays/direnv/setup.sh +7 -6
  125. package/overlays/dotnet/setup.sh +14 -7
  126. package/overlays/duckdb/devcontainer.patch.json +1 -2
  127. package/overlays/gcloud/devcontainer.patch.json +0 -6
  128. package/overlays/gcloud/setup.sh +51 -0
  129. package/overlays/gemini-cli/setup.sh +5 -0
  130. package/overlays/git-helpers/devcontainer.patch.json +2 -1
  131. package/overlays/go/setup.sh +15 -14
  132. package/overlays/jaeger/overlay.yml +2 -0
  133. package/overlays/just/setup.sh +5 -17
  134. package/overlays/k3d/README.md +201 -0
  135. package/overlays/k3d/devcontainer.patch.json +9 -0
  136. package/overlays/k3d/overlay.yml +19 -0
  137. package/overlays/k3d/setup.sh +34 -0
  138. package/overlays/k3d/verify.sh +38 -0
  139. package/overlays/keycloak/docker-compose.yml +6 -4
  140. package/overlays/keycloak/verify.sh +4 -3
  141. package/overlays/kind/devcontainer.patch.json +1 -2
  142. package/overlays/kind/setup.sh +8 -17
  143. package/overlays/minio/setup.sh +10 -18
  144. package/overlays/mkdocs/overlay.yml +2 -1
  145. package/overlays/mkdocs2/README.md +135 -0
  146. package/overlays/mkdocs2/devcontainer.patch.json +19 -0
  147. package/overlays/mkdocs2/overlay.yml +17 -0
  148. package/overlays/mkdocs2/setup.sh +67 -0
  149. package/overlays/mkdocs2/verify.sh +35 -0
  150. package/overlays/modern-cli-tools/devcontainer.patch.json +7 -1
  151. package/overlays/modern-cli-tools/setup.sh +21 -71
  152. package/overlays/mongodb/devcontainer.patch.json +0 -6
  153. package/overlays/mongodb/setup.sh +59 -0
  154. package/overlays/mysql/verify.sh +4 -3
  155. package/overlays/nats/.env.example +1 -1
  156. package/overlays/nats/README.md +1 -1
  157. package/overlays/nats/docker-compose.yml +1 -1
  158. package/overlays/ngrok/setup.sh +9 -6
  159. package/overlays/nodejs/setup.sh +5 -0
  160. package/overlays/ollama/.env.example +14 -0
  161. package/overlays/ollama/README.md +325 -0
  162. package/overlays/ollama/devcontainer.patch.json +14 -0
  163. package/overlays/ollama/docker-compose.yml +24 -0
  164. package/overlays/ollama/overlay.yml +22 -0
  165. package/overlays/ollama/setup.sh +106 -0
  166. package/overlays/ollama/verify.sh +99 -0
  167. package/overlays/open-webui/.env.example +5 -0
  168. package/overlays/open-webui/README.md +162 -0
  169. package/overlays/open-webui/devcontainer.patch.json +14 -0
  170. package/overlays/open-webui/docker-compose.yml +23 -0
  171. package/overlays/open-webui/overlay.yml +38 -0
  172. package/overlays/openapi-tools/devcontainer.patch.json +1 -2
  173. package/overlays/openapi-tools/setup.sh +9 -8
  174. package/overlays/opencode/setup.sh +5 -0
  175. package/overlays/otel-collector/overlay.yml +2 -0
  176. package/overlays/otel-collector/setup.sh +3 -16
  177. package/overlays/otel-demo-nodejs/verify.sh +8 -9
  178. package/overlays/otel-demo-python/verify.sh +16 -10
  179. package/overlays/pandoc/README.md +22 -15
  180. package/overlays/pandoc/devcontainer.patch.json +6 -2
  181. package/overlays/pandoc/setup.sh +217 -18
  182. package/overlays/pandoc/verify.sh +16 -4
  183. package/overlays/pgvector/.env.example +6 -0
  184. package/overlays/pgvector/README.md +215 -0
  185. package/overlays/pgvector/devcontainer.patch.json +23 -0
  186. package/overlays/pgvector/docker-compose.yml +32 -0
  187. package/overlays/pgvector/overlay.yml +44 -0
  188. package/overlays/playwright/devcontainer.patch.json +3 -1
  189. package/overlays/playwright/setup.sh +37 -0
  190. package/overlays/postgres/.env.example +5 -5
  191. package/overlays/postgres/devcontainer.patch.json +4 -4
  192. package/overlays/postgres/docker-compose.yml +15 -5
  193. package/overlays/postgres/overlay.yml +19 -1
  194. package/overlays/powershell/setup.sh +49 -13
  195. package/overlays/pre-commit/setup.sh +12 -3
  196. package/overlays/prometheus/overlay.yml +2 -0
  197. package/overlays/promtail/verify.sh +16 -10
  198. package/overlays/pulumi/devcontainer.patch.json +1 -1
  199. package/overlays/python/setup.sh +28 -9
  200. package/overlays/python/verify.sh +4 -2
  201. package/overlays/qdrant/.env.example +4 -0
  202. package/overlays/qdrant/README.md +216 -0
  203. package/overlays/qdrant/devcontainer.patch.json +20 -0
  204. package/overlays/qdrant/docker-compose.yml +25 -0
  205. package/overlays/qdrant/overlay.yml +40 -0
  206. package/overlays/redpanda/docker-compose.yml +3 -5
  207. package/overlays/rocm/README.md +227 -0
  208. package/overlays/rocm/devcontainer.patch.json +4 -0
  209. package/overlays/rocm/overlay.yml +17 -0
  210. package/overlays/rocm/setup.sh +45 -0
  211. package/overlays/rocm/verify.sh +47 -0
  212. package/overlays/rust/setup.sh +11 -18
  213. package/overlays/skaffold/README.md +256 -0
  214. package/overlays/skaffold/devcontainer.patch.json +9 -0
  215. package/overlays/skaffold/overlay.yml +20 -0
  216. package/overlays/skaffold/setup.sh +33 -0
  217. package/overlays/skaffold/verify.sh +24 -0
  218. package/overlays/spec-kit/setup.sh +7 -3
  219. package/overlays/sqlite/setup.sh +14 -14
  220. package/overlays/sqlserver/docker-compose.yml +3 -3
  221. package/overlays/sqlserver/verify.sh +22 -5
  222. package/overlays/tempo/verify.sh +16 -10
  223. package/overlays/tilt/devcontainer.patch.json +1 -2
  224. package/overlays/tilt/setup.sh +14 -4
  225. package/overlays/windsurf-cli/setup.sh +27 -4
  226. package/overlays/windsurf-cli/verify.sh +13 -3
  227. package/package.json +4 -2
  228. package/templates/scripts/setup-utils.sh +228 -0
  229. package/tool/schema/config.schema.json +141 -9
  230. package/tool/schema/overlay-manifest.schema.json +38 -0
  231. package/overlays/.shared/compose/common-healthchecks.yml +0 -38
  232. /package/overlays/otel-demo-nodejs/{Dockerfile-otel-demo-nodejs → Dockerfile} +0 -0
  233. /package/overlays/otel-demo-nodejs/{package-otel-demo-nodejs.json → package.json} +0 -0
  234. /package/overlays/otel-demo-nodejs/{server-otel-demo-nodejs.js → server.js} +0 -0
  235. /package/overlays/otel-demo-nodejs/{tracing-otel-demo-nodejs.js → tracing.js} +0 -0
  236. /package/overlays/otel-demo-python/{Dockerfile-otel-demo-python → Dockerfile} +0 -0
  237. /package/overlays/otel-demo-python/{app-otel-demo-python.py → app.py} +0 -0
  238. /package/overlays/otel-demo-python/{requirements-otel-demo-python.txt → requirements.txt} +0 -0
@@ -1,6 +1,6 @@
1
1
  # PostgreSQL Configuration
2
- POSTGRES_VERSION=16
3
- POSTGRES_DB=devdb
4
- POSTGRES_USER=postgres
5
- POSTGRES_PASSWORD=postgres
6
- POSTGRES_PORT=5432
2
+ POSTGRES_VERSION={{cs.POSTGRES_VERSION}}
3
+ POSTGRES_DB={{cs.POSTGRES_DB}}
4
+ POSTGRES_USER={{cs.POSTGRES_USER}}
5
+ POSTGRES_PASSWORD={{cs.POSTGRES_PASSWORD}}
6
+ POSTGRES_PORT={{cs.POSTGRES_PORT}}
@@ -13,9 +13,9 @@
13
13
  },
14
14
  "remoteEnv": {
15
15
  "POSTGRES_HOST": "postgres",
16
- "POSTGRES_PORT": "5432",
17
- "POSTGRES_DB": "devdb",
18
- "POSTGRES_USER": "postgres",
19
- "POSTGRES_PASSWORD": "postgres"
16
+ "POSTGRES_PORT": "{{cs.POSTGRES_PORT}}",
17
+ "POSTGRES_DB": "{{cs.POSTGRES_DB}}",
18
+ "POSTGRES_USER": "{{cs.POSTGRES_USER}}",
19
+ "POSTGRES_PASSWORD": "{{cs.POSTGRES_PASSWORD}}"
20
20
  }
21
21
  }
@@ -2,18 +2,28 @@ version: '3.8'
2
2
 
3
3
  services:
4
4
  postgres:
5
- image: postgres:${POSTGRES_VERSION:-16}-alpine
5
+ image: postgres:${POSTGRES_VERSION:-{{cs.POSTGRES_VERSION}}}-alpine
6
6
  restart: unless-stopped
7
7
  volumes:
8
8
  - postgres-data:/var/lib/postgresql/data
9
9
  environment:
10
- POSTGRES_DB: ${POSTGRES_DB:-devdb}
11
- POSTGRES_USER: ${POSTGRES_USER:-postgres}
12
- POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres}
10
+ POSTGRES_DB: ${POSTGRES_DB:-{{cs.POSTGRES_DB}}}
11
+ POSTGRES_USER: ${POSTGRES_USER:-{{cs.POSTGRES_USER}}}
12
+ POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-{{cs.POSTGRES_PASSWORD}}}
13
13
  ports:
14
- - '${POSTGRES_PORT:-5432}:5432'
14
+ - '${POSTGRES_PORT:-{{cs.POSTGRES_PORT}}}:5432'
15
15
  networks:
16
16
  - devnet
17
+ healthcheck:
18
+ test:
19
+ [
20
+ 'CMD-SHELL',
21
+ 'pg_isready -U ${POSTGRES_USER:-{{cs.POSTGRES_USER}}} -d ${POSTGRES_DB:-{{cs.POSTGRES_DB}}}',
22
+ ]
23
+ interval: 10s
24
+ timeout: 5s
25
+ retries: 5
26
+ start_period: 10s
17
27
 
18
28
  volumes:
19
29
  postgres-data:
@@ -6,7 +6,8 @@ supports:
6
6
  - compose
7
7
  requires: []
8
8
  suggests: []
9
- conflicts: []
9
+ conflicts:
10
+ - pgvector
10
11
  tags:
11
12
  - database
12
13
  - sql
@@ -18,3 +19,20 @@ ports:
18
19
  description: PostgreSQL database connection
19
20
  onAutoForward: notify
20
21
  connectionStringTemplate: 'postgresql://{postgres_user}:{postgres_password}@{host}:{port}/{postgres_db}'
22
+ parameters:
23
+ POSTGRES_DB:
24
+ description: Name of the database to create
25
+ default: devdb
26
+ POSTGRES_USER:
27
+ description: PostgreSQL superuser name
28
+ default: postgres
29
+ POSTGRES_PASSWORD:
30
+ description: PostgreSQL superuser password
31
+ default: postgres
32
+ sensitive: true
33
+ POSTGRES_PORT:
34
+ description: Host port mapped to PostgreSQL (5432 inside container)
35
+ default: '5432'
36
+ POSTGRES_VERSION:
37
+ description: PostgreSQL major version
38
+ default: '16'
@@ -5,25 +5,61 @@ set -e
5
5
 
6
6
  echo "🔧 Setting up PowerShell development environment..."
7
7
 
8
- # Verify PowerShell is installed
9
- if command -v pwsh &> /dev/null; then
10
- PWSH_VERSION=$(pwsh -NoProfile -Command '$PSVersionTable.PSVersion.ToString()')
11
- echo "✓ PowerShell found: v$PWSH_VERSION"
12
- else
8
+ # Verify PowerShell is installed and responds within 10 s.
9
+ # If pwsh doesn't respond quickly (e.g. shared library issue, slow startup),
10
+ # there is no point proceeding — all subsequent pwsh calls would also hang.
11
+ if ! command -v pwsh &>/dev/null; then
13
12
  echo "⚠️ PowerShell not found"
14
13
  exit 1
15
14
  fi
16
15
 
17
- # Install common PowerShell modules
18
- echo "📦 Installing PowerShell modules..."
16
+ # --kill-after ensures pwsh child processes are SIGKILL-ed after grace period.
17
+ PWSH_VERSION=$(timeout --kill-after=5s 10s \
18
+ pwsh -NoProfile -NonInteractive -Command '$PSVersionTable.PSVersion.ToString()' \
19
+ 2>/dev/null) || true
20
+
21
+ if [ -z "$PWSH_VERSION" ]; then
22
+ echo "⚠️ pwsh did not respond within 10 s — skipping module installation"
23
+ echo "✓ PowerShell setup complete (modules skipped)"
24
+ exit 0
25
+ fi
19
26
 
20
- # PSScriptAnalyzer (Linting and best practices)
21
- pwsh -NoProfile -Command 'Install-Module -Name PSScriptAnalyzer -Force -Scope CurrentUser -AllowClobber' || echo "⚠️ PSScriptAnalyzer installation failed"
27
+ echo "✓ PowerShell found: v$PWSH_VERSION"
28
+
29
+ # Trust PSGallery non-interactively.
30
+ # PowerShell 7+ bundles the NuGet provider — Install-PackageProvider is not
31
+ # needed and will fail with "No match found" on PS7. Call it only on PS5.
32
+ echo "🔧 Configuring PSGallery..."
33
+ timeout --kill-after=5s 60s \
34
+ pwsh -NoProfile -NonInteractive -Command '
35
+ $major = $PSVersionTable.PSVersion.Major
36
+ if ($major -lt 7) {
37
+ Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -Scope CurrentUser | Out-Null
38
+ }
39
+ Set-PSRepository -Name PSGallery -InstallationPolicy Trusted
40
+ ' || echo "⚠️ Failed to configure PSGallery (network may be unavailable) — skipping modules"
41
+
42
+ # Install common PowerShell modules.
43
+ # Each module runs in its own pwsh call with a per-module timeout so a slow
44
+ # PSGallery download doesn't block the remaining modules.
45
+ echo "📦 Installing PowerShell modules..."
22
46
 
23
- # Pester (Testing framework)
24
- pwsh -NoProfile -Command 'Install-Module -Name Pester -Force -Scope CurrentUser -AllowClobber -SkipPublisherCheck' || echo "⚠️ Pester installation failed"
47
+ _install_psmodule() {
48
+ local name="$1"; shift # remaining args passed as extra Install-Module params
49
+ local extra="$*"
50
+ timeout --kill-after=5s 90s \
51
+ pwsh -NoProfile -NonInteractive -Command "
52
+ try {
53
+ Install-Module -Name '$name' -Force -Scope CurrentUser -AllowClobber -Repository PSGallery $extra -ErrorAction Stop
54
+ Write-Host ' ✓ $name'
55
+ } catch {
56
+ Write-Host ' ⚠️ $name failed: ' + \$_
57
+ }
58
+ " 2>/dev/null || echo " ⚠️ $name timed out"
59
+ }
25
60
 
26
- # PowerShellGet (Module management)
27
- pwsh -NoProfile -Command 'Install-Module -Name PowerShellGet -Force -Scope CurrentUser -AllowClobber' || echo "⚠️ PowerShellGet installation failed"
61
+ _install_psmodule PSScriptAnalyzer
62
+ _install_psmodule Pester -SkipPublisherCheck
63
+ _install_psmodule PowerShellGet
28
64
 
29
65
  echo "✓ PowerShell setup complete"
@@ -5,10 +5,19 @@ set -e
5
5
 
6
6
  echo "🔍 Setting up pre-commit framework..."
7
7
 
8
- # Install pre-commit using pip
9
- pip install --user pre-commit
8
+ # Install pre-commit prefer pipx (avoids --user conflicts inside virtualenvs)
9
+ if command -v pipx &> /dev/null; then
10
+ pipx install pre-commit
11
+ elif command -v pip3 &> /dev/null; then
12
+ pip3 install pre-commit 2>/dev/null || pip3 install --break-system-packages pre-commit
13
+ elif command -v pip &> /dev/null; then
14
+ pip install pre-commit 2>/dev/null || pip install --break-system-packages pre-commit
15
+ else
16
+ echo "✗ No pip/pipx found — cannot install pre-commit"
17
+ exit 1
18
+ fi
10
19
 
11
- # Add to PATH if not already there
20
+ # pipx installs to ~/.local/bin
12
21
  export PATH="$HOME/.local/bin:$PATH"
13
22
 
14
23
  # Verify installation
@@ -20,3 +20,5 @@ ports:
20
20
  path: /
21
21
  onAutoForward: openBrowser
22
22
  order: 1
23
+ imports:
24
+ - .shared/otel/instrumentation.env
@@ -6,19 +6,25 @@ echo "🔍 Verifying Promtail installation..."
6
6
  # Track overall success
7
7
  ALL_CHECKS_PASSED=true
8
8
 
9
- # Check if Promtail service is running
10
- if docker ps --format '{{.Names}}' | grep -q promtail; then
11
- echo "✓ Promtail service is running"
12
- else
13
- echo " Promtail service is not running"
9
+ # Wait for Promtail /ready endpoint (primary health signal).
10
+ # docker ps is informational only not reliably accessible in all devcontainers.
11
+ PROMTAIL_READY=false
12
+ for i in {1..40}; do
13
+ if curl -s -o /dev/null -w "%{http_code}" http://promtail:3101/ready 2>/dev/null | grep -q "200"; then
14
+ echo "✓ Promtail is ready (HTTP /ready)"
15
+ PROMTAIL_READY=true
16
+ break
17
+ fi
18
+ sleep 3
19
+ done
20
+ if [ "$PROMTAIL_READY" = false ]; then
21
+ echo "✗ Promtail /ready endpoint not responding after 120 s (http://promtail:3101/ready)"
14
22
  ALL_CHECKS_PASSED=false
15
23
  fi
16
24
 
17
- # Check if Promtail can access Docker socket
18
- if docker exec promtail test -S /var/run/docker.sock 2>/dev/null; then
19
- echo "✓ Promtail has access to Docker socket"
20
- else
21
- echo "⚠️ Promtail cannot access Docker socket"
25
+ # Informational: check via docker ps if available.
26
+ if docker ps --format '{{.Names}}' 2>/dev/null | grep -q promtail; then
27
+ echo "✓ Promtail container visible in docker ps"
22
28
  fi
23
29
 
24
30
  # Final result
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://raw.githubusercontent.com/devcontainers/spec/main/schemas/devContainer.base.schema.json",
3
3
  "features": {
4
- "ghcr.io/devcontainers/features/pulumi:1": {
4
+ "ghcr.io/devcontainers-extra/features/pulumi:1": {
5
5
  "version": "latest"
6
6
  }
7
7
  },
@@ -13,6 +13,23 @@ WORKSPACE_ROOT="${PWD}"
13
13
  VENV_DIR="${WORKSPACE_ROOT}/.venv"
14
14
 
15
15
  # Create virtual environment if it doesn't exist
16
+ # Helper: validate that the venv's Python interpreter is actually executable.
17
+ # A stale .venv (e.g., leftover from a previous container build) can have a
18
+ # bin/python that is a dangling symlink, causing "cannot execute: required
19
+ # file not found" when pip or other venv scripts are invoked.
20
+ venv_is_valid() {
21
+ "${VENV_DIR}/bin/python" -c "import sys" &>/dev/null
22
+ }
23
+
24
+ if [ -d "${VENV_DIR}" ]; then
25
+ if venv_is_valid; then
26
+ echo "✓ Virtual environment already exists at .venv"
27
+ else
28
+ echo "⚠️ Existing .venv is invalid (stale interpreter), recreating..."
29
+ rm -rf "${VENV_DIR}"
30
+ fi
31
+ fi
32
+
16
33
  if [ ! -d "${VENV_DIR}" ]; then
17
34
  echo "📦 Creating virtual environment at .venv..."
18
35
  if ! command -v python3 >/dev/null 2>&1; then
@@ -21,49 +38,51 @@ if [ ! -d "${VENV_DIR}" ]; then
21
38
  fi
22
39
  python3 -m venv "${VENV_DIR}"
23
40
  echo "✓ Virtual environment created"
24
- else
25
- echo "✓ Virtual environment already exists at .venv"
26
41
  fi
27
42
 
28
- # Activate virtual environment
43
+ # Use the venv's Python directly to invoke pip — this is more robust than
44
+ # calling the pip wrapper script, whose shebang can point to a stale path.
45
+ PYTHON="${VENV_DIR}/bin/python"
46
+
47
+ # Activate virtual environment for PATH and VIRTUAL_ENV
29
48
  # shellcheck source=/dev/null
30
49
  source "${VENV_DIR}/bin/activate"
31
50
 
32
51
  # Upgrade pip, setuptools, and wheel inside the venv
33
52
  echo "⬆️ Upgrading pip, setuptools, and wheel..."
34
- pip install --upgrade pip setuptools wheel
53
+ "${PYTHON}" -m pip install --upgrade pip setuptools wheel
35
54
  echo "✓ pip, setuptools, and wheel upgraded"
36
55
 
37
56
  # Install overlay-specific packages (if requirements-overlay.txt exists)
38
57
  if [ -f ".devcontainer/requirements-overlay-${OVERLAY_NAME}.txt" ]; then
39
58
  echo "📦 Installing overlay packages from requirements-overlay-${OVERLAY_NAME}.txt..."
40
- pip install -r ".devcontainer/requirements-overlay-${OVERLAY_NAME}.txt"
59
+ "${PYTHON}" -m pip install -r ".devcontainer/requirements-overlay-${OVERLAY_NAME}.txt"
41
60
  echo "✓ Overlay packages installed"
42
61
  fi
43
62
 
44
63
  # Install from root requirements.txt (project production dependencies)
45
64
  if [ -f "requirements.txt" ]; then
46
65
  echo "📦 Installing dependencies from requirements.txt..."
47
- pip install -r requirements.txt
66
+ "${PYTHON}" -m pip install -r requirements.txt
48
67
  echo "✓ Dependencies installed from requirements.txt"
49
68
  fi
50
69
 
51
70
  # Install from requirements-dev.txt (project development dependencies)
52
71
  if [ -f "requirements-dev.txt" ]; then
53
72
  echo "📦 Installing dev dependencies from requirements-dev.txt..."
54
- pip install -r requirements-dev.txt
73
+ "${PYTHON}" -m pip install -r requirements-dev.txt
55
74
  echo "✓ Dev dependencies installed from requirements-dev.txt"
56
75
  fi
57
76
 
58
77
  # Install project in editable mode if pyproject.toml exists (modern Python projects)
59
78
  if [ -f "pyproject.toml" ]; then
60
79
  echo "📦 Found pyproject.toml, installing project in editable mode..."
61
- pip install -e .
80
+ "${PYTHON}" -m pip install -e .
62
81
  echo "✓ Project installed in editable mode"
63
82
  elif [ -f "setup.py" ]; then
64
83
  # Fallback for legacy Python projects
65
84
  echo "📦 Found setup.py, installing project in editable mode..."
66
- pip install -e .
85
+ "${PYTHON}" -m pip install -e .
67
86
  echo "✓ Project installed in editable mode"
68
87
  fi
69
88
 
@@ -18,10 +18,12 @@ else
18
18
  fi
19
19
 
20
20
  # Check pip is installed
21
+ # Use `python3 -m pip` instead of calling pip3 directly — the wrapper script
22
+ # inside a .venv has a shebang that can point to a stale interpreter path.
21
23
  echo ""
22
24
  echo "2️⃣ Checking pip..."
23
- if command -v pip3 &> /dev/null; then
24
- pip3 --version
25
+ if python3 -m pip --version &> /dev/null; then
26
+ python3 -m pip --version
25
27
  echo " ✅ pip found"
26
28
  else
27
29
  echo " ❌ pip not found"
@@ -0,0 +1,4 @@
1
+ # Qdrant Configuration
2
+ QDRANT_VERSION={{cs.QDRANT_VERSION}}
3
+ QDRANT_PORT={{cs.QDRANT_PORT}}
4
+ QDRANT_GRPC_PORT={{cs.QDRANT_GRPC_PORT}}
@@ -0,0 +1,216 @@
1
+ # Qdrant Overlay
2
+
3
+ Adds [Qdrant](https://qdrant.tech) as a Docker Compose service, providing a high-performance vector database for similarity search and embedding-based retrieval.
4
+
5
+ ## Features
6
+
7
+ - **Qdrant vector database** — Store, index, and query high-dimensional embedding vectors at scale
8
+ - **REST API on port 6333** — Full-featured HTTP API for collections, points, and search
9
+ - **gRPC API on port 6334** — High-throughput binary protocol for production workloads
10
+ - **Persistent storage** — Named Docker volume preserves data across container rebuilds
11
+ - **Pre-configured `QDRANT_URL`** — Container environment variable set for easy SDK usage
12
+ - **Health check** — Compose readiness check against `/readyz` before dependent services start
13
+
14
+ ## How It Works
15
+
16
+ Qdrant runs as a Docker Compose service alongside your devcontainer. The devcontainer connects to it using the hostname `qdrant` on port `6333` (REST) or `6334` (gRPC).
17
+
18
+ **Service configuration:**
19
+
20
+ - Image: `qdrant/qdrant:latest`
21
+ - Network: `devnet` (shared with the dev container)
22
+ - Ports: `6333` (REST API), `6334` (gRPC)
23
+ - Volume: `qdrant-data` for persistent vector storage
24
+
25
+ The following environment variables are pre-set in the devcontainer:
26
+
27
+ | Variable | Value |
28
+ | ------------- | -------------------- |
29
+ | `QDRANT_HOST` | `qdrant` |
30
+ | `QDRANT_PORT` | `6333` |
31
+ | `QDRANT_URL` | `http://qdrant:6333` |
32
+
33
+ ## Common Commands
34
+
35
+ ### REST API
36
+
37
+ ```bash
38
+ # Health check
39
+ curl http://qdrant:6333/healthz
40
+
41
+ # Create a collection
42
+ curl -X PUT http://qdrant:6333/collections/my_collection \
43
+ -H "Content-Type: application/json" \
44
+ -d '{
45
+ "vectors": {
46
+ "size": 1536,
47
+ "distance": "Cosine"
48
+ }
49
+ }'
50
+
51
+ # Insert points
52
+ curl -X PUT http://qdrant:6333/collections/my_collection/points \
53
+ -H "Content-Type: application/json" \
54
+ -d '{
55
+ "points": [
56
+ {
57
+ "id": 1,
58
+ "vector": [0.1, 0.2, 0.3],
59
+ "payload": {"text": "example document"}
60
+ }
61
+ ]
62
+ }'
63
+
64
+ # Search for similar vectors
65
+ curl -X POST http://qdrant:6333/collections/my_collection/points/search \
66
+ -H "Content-Type: application/json" \
67
+ -d '{
68
+ "vector": [0.1, 0.2, 0.3],
69
+ "limit": 5
70
+ }'
71
+
72
+ # List collections
73
+ curl http://qdrant:6333/collections
74
+ ```
75
+
76
+ ### Python SDK
77
+
78
+ ```bash
79
+ pip install qdrant-client
80
+
81
+ python - <<'EOF'
82
+ from qdrant_client import QdrantClient
83
+ from qdrant_client.models import Distance, VectorParams, PointStruct
84
+
85
+ client = QdrantClient(url="http://qdrant:6333")
86
+
87
+ # Create collection
88
+ client.create_collection(
89
+ collection_name="my_collection",
90
+ vectors_config=VectorParams(size=1536, distance=Distance.COSINE),
91
+ )
92
+
93
+ # Insert vectors
94
+ client.upsert(
95
+ collection_name="my_collection",
96
+ points=[
97
+ PointStruct(id=1, vector=[0.1] * 1536, payload={"text": "hello"})
98
+ ],
99
+ )
100
+
101
+ # Search
102
+ results = client.search(
103
+ collection_name="my_collection",
104
+ query_vector=[0.1] * 1536,
105
+ limit=5,
106
+ )
107
+ print(results)
108
+ EOF
109
+ ```
110
+
111
+ ### Node.js SDK
112
+
113
+ ```bash
114
+ npm install @qdrant/js-client-rest
115
+
116
+ node - <<'EOF'
117
+ import { QdrantClient } from "@qdrant/js-client-rest";
118
+
119
+ const client = new QdrantClient({ url: "http://qdrant:6333" });
120
+
121
+ await client.createCollection("my_collection", {
122
+ vectors: { size: 1536, distance: "Cosine" },
123
+ });
124
+
125
+ const results = await client.search("my_collection", {
126
+ vector: Array(1536).fill(0.1),
127
+ limit: 5,
128
+ });
129
+ console.log(results);
130
+ EOF
131
+ ```
132
+
133
+ ## Configuration
134
+
135
+ ### Environment Variables
136
+
137
+ | Variable | Default | Description |
138
+ | ------------------ | -------- | ----------------------- |
139
+ | `QDRANT_VERSION` | `latest` | Qdrant Docker image tag |
140
+ | `QDRANT_PORT` | `6333` | Host port for REST API |
141
+ | `QDRANT_GRPC_PORT` | `6334` | Host port for gRPC API |
142
+
143
+ ### Port Customization
144
+
145
+ ```bash
146
+ # .devcontainer/.env
147
+ QDRANT_PORT=6335
148
+ QDRANT_GRPC_PORT=6336
149
+ ```
150
+
151
+ ## Use Cases
152
+
153
+ - **RAG (Retrieval-Augmented Generation)** — Store embeddings for document chunks; retrieve context for LLM queries
154
+ - **Semantic search** — Find similar documents, images, or code snippets by embedding similarity
155
+ - **Recommendation systems** — Surface similar items based on learned embeddings
156
+ - **Anomaly detection** — Identify outliers in high-dimensional embedding spaces
157
+ - **Local AI pipelines** — Pair with `ollama` for fully offline embedding + retrieval workflows
158
+
159
+ **Integrates well with:**
160
+
161
+ - `ollama` — Generate embeddings locally (`ollama pull nomic-embed-text`)
162
+ - `python` — LangChain, LlamaIndex, or raw `qdrant-client` integrations
163
+ - `nodejs` — `@qdrant/js-client-rest` for JavaScript embeddings workflows
164
+
165
+ ## Troubleshooting
166
+
167
+ ### Service Not Ready
168
+
169
+ ```bash
170
+ # Check service status
171
+ docker compose ps qdrant
172
+
173
+ # View Qdrant logs
174
+ docker compose logs qdrant
175
+
176
+ # Test health endpoint
177
+ curl http://qdrant:6333/healthz
178
+ ```
179
+
180
+ ### Port Conflict
181
+
182
+ If ports 6333 or 6334 are already in use:
183
+
184
+ ```bash
185
+ # .devcontainer/.env
186
+ QDRANT_PORT=6335
187
+ QDRANT_GRPC_PORT=6336
188
+ ```
189
+
190
+ ### Data Persistence
191
+
192
+ Qdrant data is stored in the `qdrant-data` named Docker volume. It persists across container rebuilds but is scoped to the Docker environment:
193
+
194
+ ```bash
195
+ # Inspect the volume
196
+ docker volume inspect qdrant-data
197
+
198
+ # Backup data
199
+ docker run --rm -v qdrant-data:/data -v $(pwd):/backup alpine \
200
+ tar czf /backup/qdrant-backup.tar.gz /data
201
+ ```
202
+
203
+ ## References
204
+
205
+ - [Qdrant Documentation](https://qdrant.tech/documentation/)
206
+ - [Qdrant REST API Reference](https://qdrant.github.io/qdrant/redoc/index.html)
207
+ - [Qdrant Docker Hub](https://hub.docker.com/r/qdrant/qdrant)
208
+ - [Python SDK](https://python-client.qdrant.tech/)
209
+ - [JavaScript SDK](https://github.com/qdrant/qdrant-js)
210
+
211
+ **Related Overlays:**
212
+
213
+ - [`pgvector`](../pgvector/README.md) — PostgreSQL-native vector storage (alternative; conflicts with `postgres`)
214
+ - [`ollama`](../ollama/README.md) — Local LLM and embedding generation
215
+ - [`python`](../python/README.md) — Python development environment
216
+ - [`nodejs`](../nodejs/README.md) — Node.js development environment
@@ -0,0 +1,20 @@
1
+ {
2
+ "$schema": "https://raw.githubusercontent.com/devcontainers/spec/main/schemas/devContainer.base.schema.json",
3
+ "runServices": ["qdrant"],
4
+ "forwardPorts": [6333, 6334],
5
+ "portsAttributes": {
6
+ "6333": {
7
+ "label": "Qdrant REST API",
8
+ "onAutoForward": "notify"
9
+ },
10
+ "6334": {
11
+ "label": "Qdrant gRPC",
12
+ "onAutoForward": "ignore"
13
+ }
14
+ },
15
+ "containerEnv": {
16
+ "QDRANT_HOST": "qdrant",
17
+ "QDRANT_PORT": "6333",
18
+ "QDRANT_URL": "http://qdrant:6333"
19
+ }
20
+ }
@@ -0,0 +1,25 @@
1
+ version: '3.8'
2
+
3
+ services:
4
+ qdrant:
5
+ image: qdrant/qdrant:${QDRANT_VERSION:-{{cs.QDRANT_VERSION}}}
6
+ restart: unless-stopped
7
+ volumes:
8
+ - qdrant-data:/qdrant/storage
9
+ ports:
10
+ - '${QDRANT_PORT:-{{cs.QDRANT_PORT}}}:6333'
11
+ - '${QDRANT_GRPC_PORT:-{{cs.QDRANT_GRPC_PORT}}}:6334'
12
+ networks:
13
+ - devnet
14
+ healthcheck:
15
+ test: ['CMD-SHELL', 'curl -sf http://localhost:6333/readyz || exit 1']
16
+ interval: 10s
17
+ timeout: 5s
18
+ retries: 5
19
+ start_period: 10s
20
+
21
+ volumes:
22
+ qdrant-data:
23
+
24
+ networks:
25
+ devnet:
@@ -0,0 +1,40 @@
1
+ id: qdrant
2
+ name: Qdrant
3
+ description: High-performance vector database for similarity search and embeddings
4
+ category: database
5
+ supports:
6
+ - compose
7
+ requires: []
8
+ suggests:
9
+ - ollama
10
+ - python
11
+ - nodejs
12
+ conflicts: []
13
+ tags:
14
+ - database
15
+ - vector
16
+ - embeddings
17
+ - search
18
+ - qdrant
19
+ ports:
20
+ - port: 6333
21
+ service: qdrant
22
+ protocol: http
23
+ description: Qdrant REST API
24
+ onAutoForward: notify
25
+ connectionStringTemplate: 'http://{host}:{port}'
26
+ - port: 6334
27
+ service: qdrant
28
+ protocol: grpc
29
+ description: Qdrant gRPC API
30
+ onAutoForward: ignore
31
+ parameters:
32
+ QDRANT_VERSION:
33
+ description: Qdrant Docker image tag
34
+ default: latest
35
+ QDRANT_PORT:
36
+ description: Host port mapped to Qdrant REST API (6333 inside container)
37
+ default: '6333'
38
+ QDRANT_GRPC_PORT:
39
+ description: Host port mapped to Qdrant gRPC API (6334 inside container)
40
+ default: '6334'