From container-plugin
Configures Skaffold file sync to copy changed files to running containers without image rebuilds, speeding up development loops for interpreted languages and static assets.
npx claudepluginhub laurigates/claude-plugins --plugin container-pluginThis skill is limited to using the following tools:
File sync copies changed files directly to running containers, avoiding image rebuilds. This dramatically speeds up the development loop for interpreted languages and static assets.
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
File sync copies changed files directly to running containers, avoiding image rebuilds. This dramatically speeds up the development loop for interpreted languages and static assets.
Without sync: Edit → Build Image → Deploy → Restart Pod → Test (~30-60s)
With sync: Edit → Copy File → Test (~1-2s)
| Mode | Configuration | Best For |
|---|---|---|
| Manual | Explicit src/dest mappings | Full control, complex layouts |
| Infer | Derived from Dockerfile | Docker builds, simple projects |
| Auto | Zero-config for known builders | Buildpacks, Jib |
Important: Cannot mix modes - choose one per artifact.
Explicitly map source files to container destinations.
apiVersion: skaffold/v4beta13
kind: Config
build:
artifacts:
- image: my-app
context: .
docker:
dockerfile: Dockerfile
sync:
manual:
- src: "src/**/*.js"
dest: /app/src
- src: "public/**/*"
dest: /app/public
Use strip to remove directory levels from the source path:
sync:
manual:
# src/components/Button.js → /app/Button.js (strips 'src/components/')
- src: "src/components/**/*.js"
dest: /app
strip: "src/components/"
# assets/images/logo.png → /var/www/static/logo.png
- src: "assets/images/**/*"
dest: /var/www/static
strip: "assets/images/"
sync:
manual:
# HTML files to nginx root
- src: "static/*.html"
dest: /usr/share/nginx/html
# CSS with directory structure preserved
- src: "static/css/**/*.css"
dest: /usr/share/nginx/html/css
strip: "static/css/"
# Images
- src: "static/images/**/*"
dest: /usr/share/nginx/html/images
strip: "static/images/"
build:
artifacts:
- image: node-app
sync:
manual:
- src: "src/**/*.ts"
dest: /app/src
- src: "src/**/*.tsx"
dest: /app/src
- src: "*.json"
dest: /app
Pair with nodemon or ts-node-dev in container:
CMD ["npx", "nodemon", "--watch", "/app/src", "src/index.ts"]
build:
artifacts:
- image: python-app
sync:
manual:
- src: "app/**/*.py"
dest: /app
- src: "templates/**/*.html"
dest: /app/templates
strip: "templates/"
Pair with Flask debug mode or uvicorn reload:
CMD ["uvicorn", "main:app", "--reload", "--host", "0.0.0.0"]
Skaffold automatically determines destinations from Dockerfile COPY/ADD instructions.
build:
artifacts:
- image: my-app
docker:
dockerfile: Dockerfile
sync:
infer:
- "**/*.js"
- "**/*.css"
- "**/*.html"
Given this Dockerfile:
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY src/ ./src/ # Skaffold infers: src/* → /app/src/*
COPY public/ ./public/ # Skaffold infers: public/* → /app/public/*
Skaffold analyzes COPY instructions to determine sync destinations.
| Limitation | Workaround |
|---|---|
| File deletion triggers full rebuild | Use manual sync for delete support |
| Multi-stage builds may confuse inference | Use manual sync |
| Complex COPY patterns | Use manual sync |
Zero-configuration sync for supported builders.
build:
artifacts:
- image: my-app
buildpacks:
builder: gcr.io/buildpacks/builder:v1
sync:
auto: true # Enabled by default for buildpacks
Supported languages:
.go files.java, .kt, .properties, .xml files.js, .ts, .json filesDisable auto sync:
sync:
auto: false
build:
artifacts:
- image: my-app
jib: {}
sync:
auto: true # Enabled by default for Jib
Auto-syncs:
apiVersion: skaffold/v4beta13
kind: Config
metadata:
name: node-app
build:
local:
push: false
useBuildkit: true
artifacts:
- image: node-app
context: .
docker:
dockerfile: Dockerfile
sync:
manual:
- src: "src/**/*.ts"
dest: /app/src
- src: "src/**/*.tsx"
dest: /app/src
- src: "public/**/*"
dest: /app/public
deploy:
kubeContext: orbstack
kubectl:
manifests:
- k8s/*.yaml
apiVersion: skaffold/v4beta13
kind: Config
metadata:
name: fastapi-app
build:
local:
push: false
artifacts:
- image: fastapi-app
sync:
manual:
- src: "app/**/*.py"
dest: /code/app
- src: "templates/**/*.html"
dest: /code/templates
strip: "templates/"
- src: "static/**/*"
dest: /code/static
strip: "static/"
deploy:
kubeContext: orbstack
kubectl:
manifests:
- k8s/*.yaml
apiVersion: skaffold/v4beta13
kind: Config
metadata:
name: go-app
build:
artifacts:
- image: go-app
sync:
manual:
- src: "**/*.go"
dest: /app
- src: "go.mod"
dest: /app
- src: "go.sum"
dest: /app
deploy:
kubeContext: orbstack
kubectl:
manifests:
- k8s/*.yaml
With Air in Dockerfile:
FROM golang:1.22-alpine
RUN go install github.com/cosmtrek/air@latest
WORKDIR /app
COPY . .
CMD ["air", "-c", ".air.toml"]
apiVersion: skaffold/v4beta13
kind: Config
metadata:
name: static-site
build:
artifacts:
- image: static-site
sync:
manual:
- src: "dist/**/*"
dest: /usr/share/nginx/html
strip: "dist/"
deploy:
kubeContext: orbstack
kubectl:
manifests:
- k8s/*.yaml
| Requirement | Reason |
|---|---|
tar command available | Used to extract synced files |
| Writable target directories | Cannot sync to read-only paths |
| Container user has write permissions | Files must be modifiable by container UID |
| Scenario | Solution |
|---|---|
| Builder-generated files | Full rebuild required |
| Files requiring compilation | Use hot-reload tools (nodemon, air) |
| System files / package installs | Full rebuild required |
| Permission changes | Full rebuild required |
| Change Type | Sync | Rebuild |
|---|---|---|
| Source code (interpreted) | Yes | - |
| Static assets | Yes | - |
| Config files | Yes | - |
| Dockerfile | - | Yes |
| Dependencies (package.json, go.mod) | - | Yes |
| Build scripts | - | Yes |
# Watch Skaffold output for sync messages
skaffold dev -v info
# Look for:
# Syncing 1 files for my-app:latest
# Watching for changes...
kubectl exec -it <pod> -- which tar
# Should output: /bin/tar or /usr/bin/tar
kubectl exec -it <pod> -- ls -la /app/src/
# Check files are writable by container user
# Verify destination exists in container
kubectl exec -it <pod> -- ls -la /app/
# Check container user
kubectl exec -it <pod> -- whoami
profiles:
# Fast iteration - sync enabled
- name: dev
build:
artifacts:
- image: my-app
sync:
manual:
- src: "src/**/*"
dest: /app/src
# CI/Production - no sync, full rebuilds
- name: ci
build:
artifacts:
- image: my-app
# No sync configuration
| Context | Command |
|---|---|
| Dev with sync | skaffold dev --kube-context=orbstack |
| Verbose sync debug | skaffold dev -v info |
| Force rebuild (skip sync) | skaffold dev --force=true |
| Single rebuild | skaffold build && skaffold deploy |
| Check sync status | skaffold dev -v debug 2>&1 | grep -i sync |
| Field | Description | Required |
|---|---|---|
src | Glob pattern for source files | Yes |
dest | Destination path in container | Yes |
strip | Directory prefix to remove | No |
| Feature | Manual | Infer | Auto |
|---|---|---|---|
| Explicit mapping | Yes | No | No |
| Delete support | Yes | No | Yes |
| Multi-stage Docker | Yes | Limited | N/A |
| Zero-config | No | Partial | Yes |
| Buildpacks support | No | No | Yes |
| Jib support | No | No | Yes |
| Pattern | Matches |
|---|---|
*.js | JS files in root only |
**/*.js | JS files in all directories |
src/**/* | All files under src/ |
{src,lib}/**/*.ts | TS files in src/ or lib/ |