Claude-skill-registry sayt-cnt
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/cnt" ~/.claude/skills/majiayu000-claude-skill-registry-sayt-cnt && rm -rf "$T"
manifest:
skills/data/cnt/SKILL.mdsource content
launch / integrate — Docker Compose Containerization
sayt launch starts a containerized development environment. sayt integrate runs integration tests in containers. Both use Docker Compose with a specific service convention.
How It Works
sayt launch
sayt launch- Cleans up any leftover containers:
docker compose down -v --timeout 0 --remove-orphans - Sets up Docker-in-Docker (dind) environment with a socat proxy
- Runs:
docker compose run --build --service-ports develop - Cleans up the socat container on exit
sayt integrate
sayt integrate- Cleans up:
docker compose down -v --timeout 0 --remove-orphans - If
: builds without Docker layer cache first--no-cache - Sets up dind environment
- Runs:
docker compose up integrate --abort-on-container-failure --exit-code-from integrate --force-recreate --build --renew-anon-volumes --remove-orphans --attach-dependencies - On success: cleans up containers
- On failure: leaves containers running for inspection (run
ordocker compose logs
when done)docker compose down -v
The compose.yaml Convention
sayt expects two services in
compose.yaml:
develop
service (for sayt launch
)
developsayt launchThe development service runs your app with hot reload, debugging, port mapping, etc.
services: develop: command: ./gradlew dev -t # Your dev command ports: - "8080:8080" # Expose ports to host build: network: host context: ../.. # Monorepo root (or ".") dockerfile: services/myapp/Dockerfile secrets: - host.env target: debug # Dockerfile stage for dev volumes: - //var/run/docker.sock:/var/run/docker.sock entrypoint: - /monorepo/plugins/devserver/dind.sh secrets: - host.env network_mode: host
integrate
service (for sayt integrate
)
integratesayt integrateThe integration service runs your test suite in an isolated container.
services: integrate: command: "true" # Overridden by Dockerfile CMD build: network: host context: ../.. dockerfile: services/myapp/Dockerfile secrets: - host.env target: integrate # Dockerfile stage for integration
Secrets
secrets: host.env: environment: HOST_ENV # Injected by sayt's dind helper
The
HOST_ENV secret contains Docker credentials, Kubernetes config, and dind connection info.
Dockerfile Multi-Stage Pattern
sayt expects Dockerfiles with at least two targets:
debug
target (used by develop
)
debugdevelopContains the full development environment with source code, tools, and hot reload:
FROM node:22 AS debug WORKDIR /app COPY package.json pnpm-lock.yaml ./ RUN pnpm install COPY . . CMD ["pnpm", "dev"]
integrate
target (used by integrate
)
integrateintegrateExtends debug with integration test execution:
FROM debug AS integrate COPY tests/ tests/ CMD ["pnpm", "test:int"]
Full Multi-Stage Example (JVM)
# Base with tools FROM eclipse-temurin:21 AS debug WORKDIR /app COPY gradlew gradlew.bat gradle.properties settings.gradle.kts build.gradle.kts ./ COPY gradle/ gradle/ RUN ./gradlew dependencies COPY src/main/ src/main/ COPY .vscode/ .vscode/ RUN ./gradlew assemble COPY src/test/ src/test/ # Integration tests FROM debug AS integrate COPY src/it/ src/it/ CMD ["./gradlew", "integrationTest"]
Full Multi-Stage Example (Node.js)
FROM node:22 AS debug WORKDIR /app COPY package.json pnpm-lock.yaml ./ RUN corepack enable && pnpm install --frozen-lockfile COPY . . RUN pnpm build CMD ["pnpm", "dev"] FROM debug AS integrate CMD ["pnpm", "test:int", "--run"]
Docker-in-Docker (dind) Support
sayt provides dind helpers for scenarios where containers need to talk to Docker (e.g., testcontainers):
- socat proxy — A socat container is started to proxy the Docker socket over TCP
- Environment variables —
,DOCKER_HOST
, andTESTCONTAINERS_HOST_OVERRIDE
are injectedDOCKER_AUTH_CONFIG - host.env secret — All dind connection info is passed as a build secret
This enables testcontainers-based integration tests to create sibling containers.
Host Networking
sayt services use
network_mode: host by default. This means:
- Services can reach each other via
localhost - No port mapping conflicts
- Testcontainers can connect back to the host Docker daemon
- Works on Linux natively; on macOS, Docker Desktop provides host networking emulation
Complete compose.yaml Example
volumes: root-dot-docker-cache-mount: {} services: develop: command: ./gradlew dev -t ports: - "8080:8080" build: network: host context: ../.. dockerfile: services/tracker/Dockerfile secrets: - host.env target: debug volumes: - //var/run/docker.sock:/var/run/docker.sock - ${HOME:-~}/.skaffold/cache:/root/.skaffold/cache entrypoint: - /monorepo/plugins/devserver/dind.sh secrets: - host.env network_mode: host integrate: command: "true" build: network: host context: ../.. dockerfile: services/tracker/Dockerfile secrets: - host.env target: integrate secrets: host.env: environment: HOST_ENV
Cleanup Behavior
- Success:
automatically runssayt integrate
to clean updocker compose down -v - Failure: Containers are left running so you can inspect logs:
docker compose logs # View all logs docker compose logs integrate # View integration service logs docker compose down -v # Clean up manually when done
Writing Good Compose Files for sayt
- Always define
anddevelop
— These are the services sayt expectsintegrate - Use
in build —target:
for develop,debug
for integrateintegrate - Set
to monorepo root — Usuallycontext
from a service directory../.. - Include the
secret — Required for dind and credential forwardinghost.env - Use
for develop — Simplifies networkingnetwork_mode: host - Set
for integrate — Let the Dockerfile CMD handle executioncommand: "true"
Current flags
!
sayt help launch 2>&1 || true
!sayt help integrate 2>&1 || true