container-plugin/skills/skaffold-filesync/SKILL.md
Skaffold file sync — copy changed files to containers without rebuilding. Use when optimizing the dev loop, configuring sync rules, or the user mentions hot reload or fast iteration.
npx skillsauth add laurigates/claude-plugins skaffold-filesyncInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
| Use this skill when... | Use a sibling Skaffold/container skill instead when... |
|---|---|
| Configuring Skaffold sync rules (manual / infer / auto) | Wiring OrbStack networking or Ingress (skaffold-orbstack) |
| Optimizing the inner edit -> running-container loop for hot reload | Adding pre-deploy test or post-deploy verify stages (skaffold-testing) |
| Debugging why files are not syncing into a running pod | Writing or hardening the Dockerfile itself (container-development) |
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/ |
testing
Verify accumulated bug claims at upstream HEAD and dedup against trackers before filing issues. Use when filing upstream reports from backlogs, audit docs, or git-history findings.
documentation
Gate outward-bound text (upstream issues, docs, PR bodies) through isolated haiku fresh-reader critique before publishing. Use when an artifact must survive a reader with zero project context.
tools
Suggest improvements to SKILL.md content, descriptions, or tool config from eval results. Use when raising pass rates, fixing triggering, or iterating on a skill after evaluation.
tools
deadbranch CLI for stale-branch cleanup — dry-run preview, TUI or non-interactive delete, protects main/develop/WIP. Use when asked to clean up branches, prune branches, or remove stale branches.