Skip to content
Back to skills

jig-operator

CSecurity

Use this when the user wants to deploy or operate applications with Jig, including bootstrapping a Jig server, connecting the Jig CLI, preparing deployment config, deploying apps, and handling mode-specific behavior for standalone Docker, Docker Compose, Swarm single-service, and Swarm stack deployments without diving into Jig internals.

  • 6 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added May 28, 2026
devopsrustgobashnodedockergitapidatabasebackend

Works with

  • cli
  • api

Security analysis

C71/100
  • criticalPipes output to a shell interpreter
  • mediumUses curl or wget to download content
  • criticalDownloads and executes remote scripts — classic supply chain attack

Pro scans all 19 files and shows the line behind each finding

Scanned May 28, 2026

npx -y skills add klirix/jig --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of jig-operator?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for jig-operator
[![Security: C — Skills Directory](https://www.skillsdirectory.com/api/skills/klirix-jig-operator/badge)](https://www.skillsdirectory.com/skills/klirix-jig-operator)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: jig-operator
description: Use this when the user wants to deploy or operate applications with Jig, including bootstrapping a Jig server, connecting the Jig CLI, preparing deployment config, deploying apps, and handling mode-specific behavior for standalone Docker, Docker Compose, Swarm single-service, and Swarm stack deployments without diving into Jig internals.
---

# Jig Operator

Act like a practical Jig operator. Focus on the workflows a user actually needs:

- bootstrap a Jig server
- install and authenticate the CLI
- prepare a project for deployment
- deploy, inspect, scale, roll back, and remove deployments
- manage secrets, tokens, and Swarm worker joins

Do not explain Jig internals unless the user explicitly asks for architecture or implementation details.

## First response behavior

Before giving commands, determine which of these four modes applies:

1. standalone single-container deployment
2. standalone compose deployment
3. swarm-backed single-service deployment
4. swarm-backed compose stack deployment

Use these defaults unless the user says otherwise:

- single host: standalone Docker
- private control plane: `tailscale` mode if Tailscale is already present
- otherwise: `public` mode with a domain
- deployment build path: server-side `jig deploy`
- compose apps: prefer explicit `x-jig` blocks on routed services

If the mode is ambiguous, ask only the minimum needed question:

- standalone or Swarm
- single-container or compose
- public or Tailscale control plane

## Server bootstrap

Recommend the bootstrap script first.

Requirements:

- Docker on the server
- for `public` mode: a domain pointed at the server
- for `tailscale` mode: Tailscale installed and connected on the server

Bootstrap command:

```bash
curl -fsSL https://deploywithjig.askh.at/init.sh | bash
```

What it does at a high level:

- installs or starts Jig
- configures Traefik for routing
- prompts for SSL email
- chooses `public` or `tailscale`
- prints a `jig login <endpoint+token>` command at the end

Selection guidance:

- choose `public` when the Jig API should be reachable on a public HTTPS domain
- choose `tailscale` when the Jig API should stay private on the tailnet

Important operational facts:

- client and server versions are expected to stay in sync
- the bootstrap login token is the main handoff to the workstation
- in Swarm mode, the internal registry at `127.0.0.1:5000` must never be publicly reachable

## Swarm worker joins

Use this only when the user wants multi-node deployment.

Worker bootstrap:

```bash
curl -fsSL https://deploywithjig.askh.at/worker.sh | bash
```

Useful manager-side commands:

```bash
jig cluster status
jig cluster join-token worker
jig cluster join-token manager
jig cluster join-worker
```

Operational caveats:

- `jig cluster join-token ...` and `jig cluster join-worker` only work on swarm-backed Jig instances
- every Swarm node must trust `127.0.0.1:5000` as an insecure registry
- inbound `5000/tcp` must be blocked from external networks

## Client install and login

CLI install:

```bash
curl -fsSL https://deploywithjig.askh.at/install.sh | bash
```

The installer places the binary at:

```bash
$HOME/.jig/jig
```

If needed, remind the user to add `$HOME/.jig` to `PATH`.

Login uses the bootstrap token:

```bash
jig login https://your-jig-endpoint.example.com+TOKEN
```

Token format matters:

- it must be a single string in the form `<endpoint>+<token>`
- successful login saves the server in `~/.jig/config.json`

Useful server selection commands:

```bash
jig servers ls
jig servers select <endpoint>
jig servers rm <endpoint>
```

One-off auth note:

- most commands accept `--token <endpoint+token>` for temporary auth
- `jig tokens create` is a CLI exception: treat it as requiring a normally selected server from `jig login`

## Project initialization

In a project directory:

```bash
jig init
```

This creates:

- `jig.json`
- `.jigignore`

Important caveats:

- `jig init` fails if `jig.json` already exists
- when it does run, it writes a fresh `.jigignore`; do not run it blindly in a directory with a curated ignore file
- the generated `jig.json` is minimal; the agent usually needs to add fields before deployment

## Upload and ignore behavior

Jig uploads the project directory as a tarball. The built-in ignore defaults are:

- `.git/**`
- `.gitignore`
- `.jig/**`
- `node_modules/**`

Important caveat:

- `.env` files are not ignored by default

Agent guidance:

- prefer Jig secrets over uploading local secret files
- add entries such as `.env*` to `.jigignore` unless the user explicitly wants them uploaded
- `.jigignore` supports glob patterns and `!` negation

## Mode selection rules

Use this matrix when deciding what to tell the user.

### Standalone single-container

Use this when there is no compose file and the server is not Swarm-backed.

Relevant `jig.json` fields:

- `name`
- `port`
- `domain`
- `rule`
- `hostname`
- `restartPolicy`
- `envs`
- `volumes`
- `exposePorts`
- `middlewares`

### Standalone compose

Use this when the project has a compose file and the server is not Swarm-backed.

Recommended pattern:

- top-level `jig.json` with `name`, `composeFile`, and any truly shared defaults
- `x-jig` blocks inside routed services

Services without `x-jig` still run, but Jig does not fully manage them as first-class deployments.

### Swarm single-service

Use this when there is no compose file and Jig is backed by Swarm.

Relevant `jig.json` fields are similar to standalone single-container, with one extra rule:

- bind mounts require `placement.requiredNodeLabels`

### Swarm stack

Use this when the project has a compose file and Jig is backed by Swarm.

Recommended pattern:

- top-level `jig.json` with `name`, `composeFile`, and shared defaults
- `x-jig` blocks on routed services
- compose file owns published ports and volumes

## Config rules the agent must follow

### Routing fields

Use these semantics:

- `rule` overrides `domain`
- `domain` is the simple convenience form for `Host(...)`
- `hostname` is an internal container or network alias, not the public route
- `port` is the backend container port that Traefik should send HTTP traffic to

Important caveat:

- if a service should be internal-only, set `middlewares.noHTTP: true`
- do not assume that omitting `domain` makes a service internal-only

If the user wants plain HTTP without HTTPS, use:

```json
{
  "middlewares": {
    "noTLS": true
  }
}
```

If the service should not be exposed through Traefik at all, use:

```json
{
  "middlewares": {
    "noHTTP": true
  }
}
```

### `exposePorts`

`exposePorts` publishes host ports. It is supported only for:

- standalone single-container deployments
- singular swarm service deployments

Example:

```json
{
  "exposePorts": {
    "5432": "5432",
    "53/udp": "53"
  }
}
```

Important caveat:

- compose deployments must publish ports in `docker-compose.yml`, not in `jig.json` or `x-jig`

### Volumes

Use `volumes` in `jig.json` only for non-compose deployments.

Format:

```json
{
  "volumes": [
    "/srv/app-data:/app/data"
  ]
}
```

Important caveats:

- compose deployments must define volumes in the compose file
- swarm deployments with bind mounts require `placement.requiredNodeLabels`
- the labels in `placement.requiredNodeLabels` must have non-empty keys and values

### Compose config rules

For compose projects, prefer `x-jig` on each routed service.

Per-service `x-jig` is the right place for:

- `name`
- `domain` or `rule`
- `port`
- `hostname`
- `envs`
- `middlewares`
- `restartPolicy`

Per-service `x-jig` must not set:

- `composeFile`
- `composeService`
- `volumes`
- `exposePorts`

Top-level compose `jig.json` should usually hold:

- `name`
- `composeFile`
- shared `envs`
- shared `restartPolicy`

Important inheritance caveats for `x-jig` services:

- top-level `envs` and `restartPolicy` are inherited
- top-level `domain`, `rule`, `hostname`, and `middlewares` also behave like defaults
- top-level `port`, `exposePorts`, `volumes`, `composeFile`, and `composeService` are not per-service defaults

Agent guidance:

- for multi-service compose, prefer putting route-specific fields inside each `x-jig` block
- avoid shared top-level `domain` or `rule` unless every routed service should actually share it
- keep `x-jig.name` values unique within a stack

### Legacy compose fallback

Jig still supports compose projects with no `x-jig` blocks by choosing one primary service.

How it selects the primary service:

1. `composeService` if set
2. a compose service whose name matches the top-level deployment `name`
3. otherwise the first service returned by `docker compose config --services`

Agent guidance:

- do not rely on the fallback order
- if using legacy compose, set `composeService` explicitly
- if you need explicit per-service routing behavior, prefer `x-jig` instead

Important caveat:

- legacy compose rejects top-level `port`, `volumes`, and `exposePorts`

## Deployment commands

Default deploy:

```bash
jig deploy
```

Useful variants:

```bash
jig deploy -v
jig deploy -c ./jig.json
jig deploy -l
```

Command guidance:

- prefer plain `jig deploy` unless the user specifically wants a local image build
- `jig deploy -l` works for single-container deployments, including swarm-backed single-service deployments
- `jig deploy -l` is not supported for compose deployments
- compose deployments require `docker compose` to exist on the server

## Command support matrix

Use these rules when suggesting operational commands.

### `jig ls`

Works in all modes.

Interpretation caveats:

- compose deployments appear as a stack parent plus child services
- services without `x-jig` do not show up as first-class Jig deployments

### `jig logs`

Supported forms:

```bash
jig logs <name>
jig logs <stack>
jig logs <stack:service>
```

Behavior caveats:

- `jig logs <stack>` only shows Jig-managed services in that stack
- internal compose-only services without `x-jig` are not exposed as separate Jig log targets

### `jig deployments rm`

Supported forms depend on mode.

Valid and useful:

- `jig deployments rm <name>` for singular deployments
- `jig deployments rm <stack>` for swarm stacks
- `jig deployments rm <stack:service>` for standalone compose managed services

Important caveats:

- removing an individual service from a swarm stack is not supported
- on swarm, removing a stack uses `docker stack rm` and removes the whole stack
- on standalone compose, removing `<stack>` or `<stack:service>` only removes Jig-managed labeled containers, not every compose-only service in the project

### `jig deployments rollback`

Rollback support is mode-specific.

Supported:

- standalone single-container deployments, if a previous container exists
- singular swarm service deployments, if Swarm has a `PreviousSpec`
- individual swarm stack services via `stack:service`, if that service has a `PreviousSpec`

Not supported:

- standalone compose deployments
- whole swarm stacks

Agent guidance:

- do not say rollback is a universal deployment feature
- on swarm stacks, rollback is per service, not per stack

### `jig deployments scale`

Scaling is only supported for singular swarm service deployments.

Important caveats:

- not supported on standalone instances
- not supported for compose stack services
- not supported for whole stacks
- not supported when the deployment uses `placement.requiredNodeLabels`
- replicas must be at least `1`

### `jig deployments stats`

Behavior differs by backend:

- standalone: per-deployment CPU and memory stats
- swarm-backed: node-level cluster summary, not per-deployment container stats

## Secrets and tokens

Secrets:

```bash
jig secrets ls
jig secrets add <name> <value>
jig secrets inspect <name>
jig secrets rm <name>
```

Use them from config like this:

```json
{
  "envs": {
    "DATABASE_URL": "@database-url"
  }
}
```

Operational guidance:

- prefer secrets over uploading `.env` files
- `jig secrets add` returns a friendly warning rather than failing hard when the secret already exists

Tokens:

```bash
jig tokens ls
jig tokens create <name>
jig tokens delete <name>
```

Operational guidance:

- after `jig tokens create`, store the returned `<endpoint>+<token>` immediately
- create tokens only after normal login has selected a server

## Recommended troubleshooting order

When something fails, investigate in this order:

1. `jig servers ls`
2. `jig ls`
3. `jig logs <name>` or `jig logs <stack:service>`
4. verify `jig.json` exists and has a non-empty `name`
5. if compose is involved, verify the actual compose filename and whether the server has `docker compose`
6. verify secrets referenced as `@name` exist on the server
7. if Swarm bind mounts are used, verify node labels match `placement.requiredNodeLabels`
8. if published ports are involved, verify they were configured in the right layer

Common pitfalls to catch early:

- wrong login token format
- client not on `PATH`
- `jig deploy -l` attempted for compose
- `.env` accidentally uploaded because `.jigignore` did not exclude it
- top-level compose `port` used where per-service `x-jig.port` or compose `ports:` was required
- `exposePorts` placed in compose `jig.json` or `x-jig`
- trying to remove a single service from a swarm stack
- expecting rollback for standalone compose or whole swarm stacks
- expecting `jig logs <stack>` to include internal compose-only services
- exposed registry port `5000/tcp` on Swarm nodes

## Response style for this skill

Prefer short operator instructions over long explanations.

A good response usually contains:

- the mode you are assuming
- the exact command sequence
- one or two checks to confirm success
- only the caveats that materially affect this specific task

Do not dump the entire rulebook to the user unless they ask for a deep operational explanation.

Files in this skill

  • .DS_Store6 KB
  • .editorconfig263 B
  • Dockerfile274 B
  • Makefile466 B
  • SKILL.md13.6 KB
  • go.mod2.2 KB
  • go.sum14 KB
  • website/.dockerignore132 B
  • website/.eslintignore160 B
  • website/.eslintrc.cjs543 B
  • website/.gitignore132 B
  • website/.jigignore138 B
  • website/.npmrc43 B
  • website/.prettierignore160 B
  • website/.prettierrc233 B
  • website/Dockerfile268 B
  • website/README.md137 B
  • website/jig.json189 B
  • website/package.json1.1 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.