# Okteto Onboarding

> |

- **Type:** Skill
- **Install:** `agentstack add skill-okteto-okteto-agent-skills-okteto-onboarding`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [okteto](https://agentstack.voostack.com/s/okteto)
- **Installs:** 0
- **Category:** [Cloud & Infrastructure](https://agentstack.voostack.com/c/cloud-infrastructure)
- **Latest version:** 0.1.0
- **License:** Apache-2.0
- **Upstream author:** [okteto](https://github.com/okteto)
- **Source:** https://github.com/okteto/okteto-agent-skills/tree/main/plugins/okteto/skills/okteto-onboarding

## Install

```sh
agentstack add skill-okteto-okteto-agent-skills-okteto-onboarding
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Okteto Onboarding Skill

## 1. Activation

This skill activates when **all** of the following are true:
- The project has **no** `okteto.yaml` or `okteto.yml` at the repo root
- The user is asking about Okteto, dev environments, or onboarding (e.g., "how do I get this onto Okteto", "set this repo up for Okteto", "create an Okteto manifest")

**Do NOT activate if:**
- An `okteto.yaml` or `okteto.yml` already exists at the repo root — that is the existing `okteto` skill's domain. Defer to it.
- The user is asking how to *use* Okteto with an existing manifest. Defer to the existing `okteto` skill.

**Pre-flight check.** Before starting Phase 1, run:

```bash
ls okteto.yaml okteto.yml 2>/dev/null
```

If anything is returned, stop and tell the user:
> "I see `okteto.yaml` already exists. The `okteto-onboarding` skill is for repos *without* a manifest. For working with the existing manifest, use the `okteto` skill or run `/dev-setup`."

**Two operating modes:** collaborative (default — user is in the loop) and autonomous (no human; opens a PR). See Section 7. Most of the workflow is mode-agnostic; only Phase 6 and the resolution of "ask the user" branches differ.

## 2. Phase 1 — Discover

Build an internal model of the repo: services, their build contexts, ports, dev commands, and any existing deploy artifacts. Read signals in priority order. **Do not write the manifest yet.**

### 2.1 Signal priority

1. **`docker-compose.yml` / `compose.yaml`** — the richest signal for services and dev, and a valid `deploy:` source on its own. If present, it is the primary blueprint for `build:` and `dev:`, and Okteto can deploy it directly via `deploy: compose:` (Section 4.1) — no chart or k8s manifests required. See the mapping table below.
2. **Existing Helm chart** — any `Chart.yaml` under `chart/`, `charts/`, `helm/`, or `deploy/`. If found, `deploy:` will be a `helm upgrade --install` command. **Do not generate or modify the chart.**
3. **Existing k8s manifests** — `.yaml` files with `kind:` headers under `k8s/`, `manifests/`, `deploy/` — but **excluding any `templates/` subdirectory** (those belong to a Helm chart and are not directly applyable). If found, `deploy:` will be `kubectl apply -f ...`. **Do not author these manifests.**
4. **Per-service Dockerfiles** — for repos without compose, each top-level `Dockerfile` is a candidate service. Service name comes from the parent directory.
5. **Language manifests** — `package.json`, `go.mod`, `pom.xml`, `pyproject.toml`, `Gemfile`, `Cargo.toml`. Used to pick the dev image and infer the dev command. When this is the only signal (no Dockerfile, no compose), name the service after the project's `name` field (e.g., `pyproject.toml`'s `[project] name`, `package.json`'s `name`) or, failing that, the repo directory.
6. **Procfile / Makefile** — secondary signals when language manifests are ambiguous.

**These signals are complementary, not exclusive.** A repo can carry more than one. Common combinations:

- **Compose only** — compose drives `build:`, `dev:`, *and* `deploy:` (via `deploy: compose:`). Enough to reach Level 2 with no chart or k8s manifests.
- **Chart or k8s only** — the artifact drives `deploy:`; derive `dev:` from the deployed workload names (Phase 3, bullet 4).
- **Compose *and* a chart/k8s** — the deploy source is ambiguous. Compose files are often the dev path and charts the prod path, but not always. **Do not assume the chart wins `deploy:`.** Ask the user which should drive it — compose, the chart/manifests, or both combined (Section 2.5).

Apply each signal to its own section of the manifest rather than treating priority order as a winner-takes-all.

**Don't stop at the root compose file.** Real projects routinely ship several: a base or production compose (often at the repo root, using published `image:`s) plus one or more development composes under `docker/`, `dev/`, or named `*.dev.yml` / `compose.dev.yml`. Glob for `**/docker-compose*.y*ml` and `**/compose*.y*ml` (skip `node_modules`, vendor, and build dirs) — not just `./docker-compose.yml`. The split usually maps cleanly:

- The **dev** compose — the one that **builds from source** (`build:` with `context:`/`target:`, plus source bind mounts) — drives `build:` and `dev:`.
- A **base / production / `*.preview*`** compose can drive `deploy:`.

When more than one compose file exists, **list them and ask** which describes development and which is the deploy source (Section 2.5). **Do not assume the root file is the dev blueprint** — a root compose built entirely from published images is a *run/deploy* file, and developing against a published image is meaningless.

**Follow `include:` and resolve anchors.** A compose file may pull in others via `include:` (or the older `extends:`) — read those too, or you'll miss services. Parse the *resolved* YAML, not raw lines: dev composes commonly rely on anchors and `x-` extension fields (`build: *some-anchor`, `` | `build.` (when there's a `build:` block) and `dev.` |
| `build.context`, `build.dockerfile` | `build..context`, `build..dockerfile` |
| `image` (no `build`) | `dev..image` directly — **do not** add a `build.` entry for pre-built images |
| `ports` (Level 1) | `dev..forward` — preserves the user's local-port intent |
| `ports` (Level 2+) | exposed via the `deploy:` source (compose `deploy:`, Helm, or k8s); also keep `dev..forward` for active dev sessions |
| `command` | starting point for `dev..command` |
| `volumes` (host bind mounts only) | `dev..sync` candidates |
| `depends_on` | ordering hint for the deploy step |
| `environment` | `dev..environment` |

Ignore compose-only concepts that don't translate (`networks`, `restart`, named volumes, `extends`).

**Backing services vs. dev targets.** A compose service that uses a published `image:` with no `build:` and no source in the repo (databases, caches, object stores, mail catchers, message brokers — `postgres`, `redis`, `minio`, `nats`, `mailpit`, and the like) is *infrastructure*: include it in the `deploy:` stack, but it rarely belongs in `dev:`. Reserve `dev:` for the services you actually edit — the ones that build from source in the repo. **Don't create a `dev:` entry for every compose service by default**; a repo with ten compose services often has only one or two real dev targets.

### 2.3 Dev-image picks by language manifest

Pick the image **family** from the language manifest, and the **tag from the version the repo declares** — do not hard-code a version. Reading the declared version keeps the pick current instead of freezing a minor that goes stale.

| Language manifest | Image family | Where to read the version |
|---|---|---|
| `package.json` | `okteto/node` | `engines.node` |
| `go.mod` | `okteto/golang` | the `go 1.x` line |
| `pom.xml` / `build.gradle*` | `okteto/maven` or `okteto/gradle` | `maven.compiler.release` / `sourceCompatibility`, or the wrapper version |
| `pyproject.toml` / `requirements.txt` | `okteto/python` | `requires-python` or `.python-version` |
| `Gemfile` | `okteto/ruby` | `.ruby-version` or the `ruby` directive |
| `Cargo.toml` | `okteto/rust` | `rust-version` (MSRV), if set |

Tag the image with the declared version, e.g. `okteto/golang:1.23` when `go.mod` says `go 1.23`. **State the source in an inline comment** (`# go.mod declares Go 1.23`).

**When the repo declares no version**, do not invent a specific minor — it will be wrong as often as right. In collaborative mode, ask the user which version they target. In autonomous mode, pin to the family's current stable major and flag it in the PR as a decision to confirm (`# go.mod has no version line — defaulting to a recent stable; confirm`).

### 2.4 Dev-command picks

| Signal | Dev command default |
|---|---|
| `package.json` with `scripts.dev` | `npm run dev` |
| `package.json` with `scripts.start` (no dev) | `npm start` |
| `go.mod` | `bash` (Go projects usually want a shell to `go run` manually) |
| `pom.xml` with `spring-boot-maven-plugin` | `mvn spring-boot:run` |
| `pyproject.toml` with FastAPI/Flask | `bash` (varies too much to default) |
| Procfile with a `web:` line | the value of `web:` |
| compose `entrypoint`/`command` is `sleep infinity` or `tail -f /dev/null` | `bash` — this is a **dev-container placeholder** (the container stays alive so you exec in), not a real command. Don't copy it into `dev..command`; it's exactly the pattern Okteto's `dev:` replaces. |
| None of the above | `bash` |

### 2.5 When discovery is ambiguous

If discovery leaves real ambiguity, **ask one targeted question at a time** rather than guessing. Examples:

- "I see Dockerfiles in `api/` and `web/` but no compose file. Should both be services?"
- "I found a Helm chart at `chart/` and another at `infra/helm/`. Which one is the canonical deploy?"
- "This repo has both a `docker-compose.yml` and a Helm chart. Which should drive `deploy:` — the compose file, the chart, or both? (Compose is often the dev path and the chart the prod path, but I don't want to assume.)"
- "I see several compose files — `docker-compose.yml` at the root and `docker/docker-compose.dev.yml`. Which one describes how you *develop* (builds from source), and which should I use to *deploy* the stack?"
- "Your `package.json` doesn't have a `scripts.dev` — what command starts your dev server?"

Do **not** ask the user about everything. Only ask when a guess would be likely wrong. Trust the signals.

**In autonomous mode, do not ask.** Pick the most conservative interpretation, proceed, and note the ambiguity in the PR description (Section 7.2 covers this).

### 2.6 Output of Phase 1

Internally, you should now have a model like:

```
Services: [api, web, worker]
api:    Dockerfile @ ./api,    port 8080, dev cmd `bash`,        dev image `okteto/golang:1.22`
web:    Dockerfile @ ./web,    port 3000, dev cmd `npm run dev`, dev image `okteto/node:20`
worker: Dockerfile @ ./worker, no port,   dev cmd `bash`,        dev image `okteto/python:3.12`
Deploy: helm chart at ./chart
Tests: detected `go test ./...` in api, `npm test` in web
```

Show this summary to the user before moving to Phase 2.

## 3. Phase 2 — Negotiate scope

Before drafting, frame the choice and pick a level on the adaptive ladder.

### 3.1 The framing block (always show this to the user)

> *In Okteto, `deploy:` describes how to **provision** the environment — from a Docker Compose file, a Helm chart, or k8s manifests. `dev:` describes how to **live-edit** a running service — file sync, the dev image, the startup command. You can use Okteto with just `dev:` if you already have a way to deploy your stack, or have Okteto handle both.*

This same framing goes at the top of the generated `okteto.yaml` as a header comment.

### 3.2 The adaptive ladder

| Level | What it produces | Requires |
|---|---|---|
| **1 — dev-only** | `dev:` section only. User runs their own deploy externally. | Nothing extra. |
| **2 — deploy + dev** | `build:` + `deploy:` + `dev:`. `okteto deploy` brings up the stack. | A Helm chart, k8s manifests, **or a Docker Compose file** in the repo. |
| **3 — full lifecycle** | Adds `test:` containers wired to existing test commands. | Level 2 prereqs PLUS detected tests. |

### 3.3 Recommendation logic

Recommend a level based on what Phase 1 found:

A **deploy source** is a Helm chart, k8s manifests, or a deployable Docker Compose file.

- A deploy source found AND tests detected → recommend **Level 3**
- A deploy source found, no tests → recommend **Level 2**
- No deploy source at all (no chart, no k8s manifests, no compose) → recommend **Level 1** (and explain why higher levels are unavailable)

When more than one deploy source exists (e.g. compose *and* a chart), confirm which one drives `deploy:` (Section 2.5) before drafting — don't default to the chart.

Then ask the user (collaborative mode) or accept the recommendation (autonomous mode):

> "Based on what I found, I'd recommend Level [N]. Want to go with that, pick a different level, or have me explain the trade-offs?"

### 3.4 Locking the level

Once chosen, the level is **locked for the rest of the session.** Do not negotiate level mid-flight. If the draft turns out to need a different level (e.g., the chart is broken), surface that as a Phase 5 failure and re-enter Phase 2 cleanly.

## 4. Phases 3–4 — Draft and refine

### 4.1 Draft (Phase 3)

Write `okteto.yaml` to the repo root. The user must see the **actual file**, not just a summary.

**Required content of every draft:**

1. **Header comment block** — the framing from Section 3.1, plus a note that the file was generated by `okteto-onboarding` and the user is expected to edit it. Include the chosen scope level and a one-line rationale.
2. **`build:` section** (Level 2+) — one entry per service with `context` and `dockerfile`. Skip pre-built images here (they go directly under `dev..image`).
3. **`deploy:` section** (Level 2+) — points at the chosen deploy source:
   - **Compose:** `deploy: { compose: docker-compose.yml }` (optionally a `services:` subset). The simplest path when the repo has no chart or manifests.
   - **Helm:** a `helm upgrade --install` command, passing built images via `--set ...=${OKTETO_BUILD__IMAGE}` (see "Wiring built images" below).
   - **k8s manifests:** a `kubectl apply -f ...` command.

   See the schema examples below.
4. **`dev:` section** (always) — one entry per service the user wants in dev mode, with `image`, `command`, and `sync`. The **key name** must match the workload Okteto will deploy:
   - **Compose repo:** the compose service name (mapping table, Section 2.2).
   - **Helm/k8s repo (no compose):** the name of the Kubernetes workload the chart/manifests create — the `Deployment`/`StatefulSet` `metadata.name` (render the chart or read the manifest to find it). A `dev:` key matching no deployed workload won't attach.

   The `image`, `command`, and `sync` come from the Dockerfile + language manifest (Sections 2.3–2.4) regardless of repo shape.
5. **`test:` section** (Level 3) — one entry per detected test command. See the schema example below.

**Sync-path defaults:**
- **Single-service repo** (one Dockerfile or one language manifest at the root): `.:/usr/src/app` is a reasonable default. If the Dockerfile sets `WORKDIR`, use that path on the right side instead of `/usr/src/app`.
- **Multi-service repo** (per-service Dockerfiles or compose with multiple services): scope each service's sync to its own subdirectory, e.g., `./api:/usr/src/app`. Syncing the whole repo into every container is almost always wrong.

**Inline comments are required on every non-obvious choice** (image picks, command picks, sync paths, `forward:` ports). Image and command picks are non-obvious by default — comment them.

**Wiring built images into `deploy:` and `dev:`.** Images defined under `build:` are pushed to the Okteto Registry and exposed to the rest of the manifest as environment variables:

- `OKTETO_BUILD__IMAGE` — full image reference (the one you almost always want)
- `OKTETO_BUILD__REGISTRY`, `_REPOSITORY`, `_SHA` — the parts, if you need them

`` is the `build:` key uppercased, with `-` replaced by `_` (so `build.web-api` → `OKTETO_BUILD_WEB_API_IMAGE`). Use these so the deployed workload runs the freshly built image instead of a stale or hard-coded one:

- **Helm:** `--set api.image=${OKTETO_BUILD_API_IMAGE}`
- **k8s manifests:** substitute the value (e.g. `envsubst`) before `kubectl apply`, or template the image field.
- **Compose:** the `build:` section already overrides the matching compose `image:` by service name — no `--set` needed.
- **`dev:`:** set `dev..image: ${OKTETO_BUILD__IMAGE}` when the user wants to develop against the built application image rather than a generic toolchain image (Section 2.3).

**Example: Level 2/3 fragment (build + deploy + dev + test)**

```yaml
build:
  api:
    context: ./api
    dockerfile: Dockerfile  # using the existing Dockerfile

deploy:
  - name: Deploy chart
    command: helm upg

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [okteto](https://github.com/okteto)
- **Source:** [okteto/okteto-agent-skills](https://github.com/okteto/okteto-agent-skills)
- **License:** Apache-2.0

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-okteto-okteto-agent-skills-okteto-onboarding
- Seller: https://agentstack.voostack.com/s/okteto
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
