CtrlK
BlogDocsLog inGet started
Tessl Logo

nitinjain999/platform-skills

Production-grade platform engineering handbook — Kubernetes, Terraform, Flux CD, GitHub Actions, AWS, and more.

64

Quality

80%

Does it follow best practices?

Impact

No eval scenarios have been run

SecuritybySnyk

Advisory

Suggest reviewing before use

Overview
Quality
Evals
Security
Files

setup-agents-build.mdreferences/

generate + upgrade Mode Steps

Mode: generate

Step 1 — Ranked scan (stop when confident)

Read in order. Stop as soon as runtime + framework + deploy target are clear.

head -30 README.md 2>/dev/null
ls -1
# Language/runtime detection — read first match, stop when runtime is clear
cat package.json 2>/dev/null \
  || cat pyproject.toml 2>/dev/null \
  || cat go.mod 2>/dev/null \
  || cat Cargo.toml 2>/dev/null \
  || cat pom.xml 2>/dev/null \
  || cat build.gradle 2>/dev/null \
  || cat build.gradle.kts 2>/dev/null \
  || cat settings.gradle.kts 2>/dev/null \
  || cat Gemfile 2>/dev/null \
  || ls *.csproj 2>/dev/null \
  || cat composer.json 2>/dev/null
{ f=$(ls -t .github/workflows/*.yml 2>/dev/null | head -1); [ -n "$f" ] && head -40 "$f"; }
grep -s 'ENTRYPOINT\|CMD' Dockerfile 2>/dev/null | tail -3
test -f .vscode/extensions.json && cat .vscode/extensions.json
test -f CLAUDE.md && echo "CLAUDE.md present"
test -d .cursor && echo ".cursor/ present"
test -f agents/openai.yaml && echo "agents/openai.yaml present"
ls .github/agents/*.agent.md 2>/dev/null && echo "Copilot agents already set up"
grep -l "## Agent Context" CLAUDE.md 2>/dev/null && echo "Claude Code agent sections in CLAUDE.md"
head -1 AGENTS.md 2>/dev/null

Step 2 — AGENTS.md check

head -1 AGENTS.md 2>/dev/null
  • <!-- generated by platform-skills --> → managed; overwrite freely
  • Anything else / absent → hand-authored; append only, never overwrite existing content

Step 3 — Present findings for correction

Here's what I found — correct anything wrong:

  Runtime:   <detected or "not detected">
  Framework: <detected or "not detected">
  Deploy:    <inferred from workflow or Dockerfile>
  Tests:     <framework> (<CI: yes/no>)
  IaC:       <detected or "none">
  AI tools:  <detected — e.g. Claude Code, Cursor>

Anything wrong?

If no AI tools detected: generate configs for all tools — developer deletes what they don't need.

Step 4 — Interview (minimum questions, not fixed questions)

Ask until you can write agents a developer would trust. Stop when you have enough. Some repos need 2 questions. Some need 10.

Lead with this question first:

Walk me through the last change you shipped. What did that involve?

This reveals: deploy process, review gates, test requirements, environments, approvals, failure modes. One answer replaces a 5-question form. The README tells you what someone wanted the repo to be — this tells you what it actually is.

Follow-up starting points — use as needed, not as a checklist:

  • What does this repo do and who depends on it? (if Q1 was ambiguous about purpose)
  • What would you never want an agent to do here? (off-limits, autonomy ceiling, trust)
  • For deploy/infra agent: can it trigger deployments autonomously or only propose?
  • For reviewer agent: top 3 things your team most commonly gets wrong in PRs?
  • For test-writer agent: coverage target? excluded paths?

If monorepo detected (multiple top-level services or packages):

I see this is a monorepo with multiple services.
Does your team own all of it, or are there areas owned by other teams?
If other teams own areas — which paths, and should agents treat those as off-limits?

Encode team ownership in AGENTS.md off-limits with ownership context, not just paths.

Step 5 — Minimum viability check

If after scan + interview the skill can't populate ≥3 real facts for any agent's ## How to work here section:

I don't have enough signal to write agents with real knowledge of this repo.

Options:
  1. Answer a few more questions so I have enough to write something real
  2. Generate minimal stubs you fill in manually
  3. Skip agents — generate AGENTS.md only as shared context any tool can read

Which would you prefer?

Don't generate shallow agents — they create false confidence.

Step 6 — Decide roster

Use the table in references/setup-agents.md. State roster + reasoning, confirm before generating:

I'll generate: coordinator, app (FastAPI detected), test-writer (pytest, mentioned as painful)
I'm offering:  navigator (helps new team members and code review)
I won't generate: infra (no IaC), platform (CI is support tooling, not the product)
Does this look right? Add navigator?

Step 6b — Model selection

After the roster is confirmed, show the model menu and suggest a model per agent role. The developer should see costs before deciding — not after.

Fetch current pricing before showing this menu — never display stale numbers.

Fetch from the provider's official pricing page at generate time:

  • Anthropic: https://docs.anthropic.com/en/docs/about-claude/models (may redirect to docs.claude.com — follow the redirect)
  • OpenAI: https://openai.com/api/pricing/

If the fetch succeeds, mark figures as "fetched now — verify before billing decisions". Scraped price tables can lag behind actual billing by hours or days when a provider updates their page. Never present a scraped figure as authoritative.

If fetch fails, show model names and tiers only — omit the price column and note that the developer should check current pricing themselves.

This step is skippable. If the developer wants to defer model selection (--no-model-menu or equivalent signal), use the default suggestions from the role table below and move on. Model selection is the one hard network dependency in the hot path — don't block the whole flow on it.

Model menu template (populate from fetch, or omit price column on failure):

Available models (prices per 1M tokens, input → output — fetched now):

  Anthropic  (fetch from https://docs.anthropic.com/en/docs/about-claude/models)
    <opus-latest>     $<in> → $<out>   Most capable — complex reasoning, agentic coding
    <sonnet-latest>   $<in> → $<out>   Best speed/intelligence balance  ✦ recommended default
    <haiku-latest>    $<in> → $<out>   Fastest, lowest cost

  OpenAI  (fetch from https://openai.com/api/pricing/)
    <model>           $<in> → $<out>   <description, context window>

Which model should each agent use?

  coordinator   → <sonnet-latest>   (routing + planning, needs broad judgment)
  app           → <sonnet-latest>   (code tasks, balanced capability/cost)
  infra         → <opus-latest>     (⚠ high blast radius — stronger reasoning pays off here)
  test-writer   → <haiku-latest>    (repetitive generation; speed and cost matter more)
  navigator     → <haiku-latest>    (read-only Q&A; no depth needed)

Accept suggestions? (y / change one / change all)

Populate <opus-latest>, <sonnet-latest>, <haiku-latest> with the current model IDs and prices from the fetch. If Anthropic adds a new tier since this was written, include it — the fetch is authoritative, not this template.

Suggestion rules by role:

RoleSuggested tierReason
infra, deployOpus (most capable)High blast radius — a wrong infra decision costs far more than the token difference
coordinatorSonnet (balanced)Multi-agent routing + planning; needs broad judgment at reasonable cost
app, platform, data-pipeline, mlSonnet (balanced)Code quality and context-aware decisions
test-writer, reviewerHaiku (fast)Repetitive or read-only; fast and cheap is the right trade-off
navigatorHaiku (fast)Read-only Q&A; no autonomous action

On "change one": ask which agent, then ask for the model name. Accept free text — the developer may use a model not in this list (Bedrock cross-region inference, Azure, Vertex, etc.).

Write model: only where the tool supports it in frontmatter:

  • Copilot .agent.md: write model: in YAML frontmatter ✓
  • Codex agents/openai.yaml: write model: under the agent key ✓
  • Cursor .mdc: no model: field — omit it entirely
  • Claude Code CLAUDE.md: no frontmatter — omit it entirely
  • All tools: record per-agent choices in the <!-- setup-agents metadata --> block so upgrade mode can re-surface them

Step 7 — Generate files

Marker syntax is format-dependent — see references/setup-agents-schemas.md → "Managed-file marker" for the per-format rule. Never apply <!-- ... --> to YAML or JSON targets.

Overwrite guard — apply before writing any pre-existing agent file:

managed() { head -1 "$1" 2>/dev/null | grep -q 'generated by platform-skills'; }

For each target file that already exists:

  • managed "$f" → overwrite freely (managed by this tool)
  • ! managed "$f" → skip and warn: "⚠️ $f exists and is hand-authored — skipping. Inspect manually."

This applies to: .github/agents/*.agent.md, .cursor/rules/*.mdc, agents/openai.yaml. It does not apply to CLAUDE.md (always append-only) or .vscode/settings.json / .claude/settings.json (always merge).

See references/setup-agents-prompts.md for 3-section format and navigator pattern. See references/setup-agents-schemas.md for frontmatter per tool and marker syntax. See references/setup-agents-template.md for AGENTS.md full structure.

Generate sub-agents first. Coordinator last (knows every agent's handoffs).

Use asset templates for structural output — do not regenerate them verbatim:

OutputAssetKey tokens
Copilot VS Code .agent.md frontmatterassets/frontmatter/copilot-vscode.tmplDESCRIPTION, MODEL, TOOLS
Copilot cloud .agent.md frontmatterassets/frontmatter/copilot-cloud.tmplDESCRIPTION, MODEL, TOOLS
Cursor .mdc frontmatterassets/frontmatter/cursor.tmplDESCRIPTION, GLOBS, ALWAYS_APPLY
agents/openai.yamlassets/frontmatter/codex.tmplDISPLAY_NAME, SHORT_DESCRIPTION, DEFAULT_PROMPT, AGENT_ENTRIES
CLAUDE.md Agent Context sectionassets/frontmatter/claude-section.tmplAGENT_TABLE_ROWS
Navigator agent bodyassets/agents/navigator.template.mdREPO_NAME, ENTRY_POINTS, etc.
AGENTS.mdassets/AGENTS.md.templateall interview answers
.vscode/mcp.jsonassets/mcp/vscode-settings.json.tmplcopy as-is
.claude/settings.json MCP blockassets/mcp/claude-settings.json.tmplmerge into existing

Render with assets/render.sh — substitute __TOKEN__ placeholders. The model writes only the ## How to work here body for each agent — all structural skeleton comes from the template.

Active staleness guard: Before writing any agent file, verify every path referenced in ## How to work here exists in the current file tree. Fix inline — don't write a dead reference.

Step 8 — Write metadata block to AGENTS.md

At the bottom of AGENTS.md, after all sections:

<!-- setup-agents metadata
generated: YYYY-MM-DD
q1: |
  <verbatim answer to last-change-shipped question>
off-limits: |
  <verbatim answer to never-want-agent-to-do question>
pain-points:
  - "<from interview>"
models:
  coordinator: <model-id chosen by developer>
  app: <model-id chosen by developer>
  infra: <model-id chosen by developer>
-->

Use YAML literal block scalars (|) — free text is safe. Quoted YAML strings break on colons, #, backticks, and embedded quotes. Upgrade mode reads this block to warm the session without a cold start.

Note to implementer: When writing this block, do NOT use inline quoted strings for q1/off-limits answers. Always use | literal blocks. The developer's answer will contain colons, punctuation, and special characters that corrupt inline YAML.

Step 9 — Copy scripts/verify-agents.sh and write .platform-skills/manifest

Do NOT regenerate verify-agents.sh. Copy the canonical static asset:

cp <skill-install-path>/assets/verify-agents.sh scripts/verify-agents.sh
chmod +x scripts/verify-agents.sh

The script reads .platform-skills/manifest to know which checks to run. Write the manifest now, one token per line matching the confirmed output roster:

mkdir -p .platform-skills
cat > .platform-skills/manifest <<'EOF'
# generated by platform-skills setup-agents
<token-per-confirmed-target>
EOF

Valid tokens: copilot-vscode, copilot-cloud, copilot-app, cursor, codex, windsurf, vscode-mcp. See references/setup-agents.md → ".platform-skills/manifest format" for the full reference.

Tell the developer: "Run bash scripts/verify-agents.sh any time. Add it to CI — it exits non-zero on missing references so staleness is caught at PR time."


Mode: upgrade

Step 0 — Guard: no git history

git rev-parse --git-dir &>/dev/null || { echo "Not a git repo — run generate instead."; exit 1; }
git log --oneline -1 &>/dev/null || { echo "No commits yet — run generate instead."; exit 1; }

Step 1 — Check AGENTS.md marker (same as generate)

Step 2 — Read metadata block from last session

sed -n '/<!-- setup-agents metadata/,/-->/p' AGENTS.md 2>/dev/null

Use sed with a delimited range — grep -A20 silently truncates the block once add-mode additions: entries and multi-line q1/off-limits literal blocks push it past 20 lines.

Use interview answers to warm the session:

  • Refer back to pain points: "You mentioned deploy windows were painful last time — still true?"
  • Use off-limits from metadata as a sanity check against what the new scan finds
  • Re-surface saved model choices: "Last time you used claude-opus-4 for infra and claude-haiku-4 for test-writer — keep those?" Allow changing any.

Step 3 — Read manifest and find coordinator

# Read which tool targets exist — consistent with how verify-agents.sh discovers them.
# This tells upgrade which paths to scan without hardcoding assumptions.
MANIFEST_TARGETS=$(grep -vE '^#|^[[:space:]]*$' .platform-skills/manifest 2>/dev/null)

if [ -z "$MANIFEST_TARGETS" ]; then
  echo "ℹ️  .platform-skills/manifest not found — inferring from directory presence"
  # Fallback for repos set up before manifest support
  ls .github/agents/*.agent.md 2>/dev/null && MANIFEST_TARGETS="$MANIFEST_TARGETS copilot-vscode"
  ls .cursor/rules/*.mdc 2>/dev/null       && MANIFEST_TARGETS="$MANIFEST_TARGETS cursor"
  test -f agents/openai.yaml               && MANIFEST_TARGETS="$MANIFEST_TARGETS codex"
fi

# Find coordinator — check all five output targets, not just Copilot/Cursor.
COORD=$(ls .github/agents/coordinator.agent.md \
           .cursor/rules/coordinator.mdc 2>/dev/null | head -1)

# Codex-only repos: openai.yaml holds all agents — read the whole file
[ -z "$COORD" ] && [ -f agents/openai.yaml ] && COORD=agents/openai.yaml

# Claude Code only: Agent Context table in CLAUDE.md
[ -z "$COORD" ] && grep -q "## Agent Context" CLAUDE.md 2>/dev/null && COORD=CLAUDE.md
# git log is primary — more reliable than stat (survives timestamp resets on clone)
AGENT_DATE=$(git log -1 --format=%ai -- "$COORD" 2>/dev/null | cut -d' ' -f1)

# python3 mtime is cross-platform fallback (stat -f is macOS-only, stat -c is Linux-only)
if [ -z "$AGENT_DATE" ] && [ -n "$COORD" ]; then
  AGENT_DATE=$(python3 -c "import os,datetime; \
    print(datetime.datetime.fromtimestamp(os.path.getmtime('$COORD')).strftime('%Y-%m-%d'))" 2>/dev/null)
fi

AGENT_DATE="${AGENT_DATE:-1970-01-01}"

Step 4 — Git diff since last update

CHANGED=$(git log --since="$AGENT_DATE" --name-only --pretty=format: | sort -u | grep -v '^$')
COUNT=$(echo "$CHANGED" | wc -l)

if [ "$COUNT" -gt 50 ]; then
  echo "⚠️  $COUNT files changed since agents were last updated."
  echo "Showing files most likely to affect agents:"
  echo "$CHANGED" | grep -E '^(src|tests|lib|app|.github|terraform|helm|Dockerfile|package\.json|pyproject\.toml|go\.mod)'
else
  echo "$CHANGED"
fi

Present actionable punch list, then ask:

Files changed since agents were last updated:
  src/routers/payments.py   → app agent Knowledge may be stale
  terraform/modules/rds/    → infra agent doesn't cover this new module
  .github/workflows/deploy.yml → deploy process may have changed

Show proposed updates? (y/n/apply-all)

Step 5 — Tool migration check

# Cursor agent files exist but .cursor/ directory is gone?
if ls .cursor/rules/*.mdc 2>/dev/null | grep -q .; then
  test -d .cursor || echo "⚠️  .cursor/rules/*.mdc files exist but .cursor/ is gone — team moved away from Cursor?"
fi
# Copilot agent files exist but no VS Code or Copilot config?
if ls .github/agents/*.agent.md 2>/dev/null | grep -q .; then
  test -f .vscode/extensions.json || echo "ℹ️  Copilot agent files exist but no .vscode/extensions.json detected"
fi

Step 6 — Apply with approval (per item, not all at once)

Present each change individually, not all at once:

Update 1/3: app agent — add new router src/routers/payments.py to ## How to work here
Apply? (y/n/apply-all/skip-all)
  • y → apply, move to next item
  • n → skip this item, explain why it was flagged, move on
  • apply-all → apply all remaining items without further prompts
  • skip-all → stop applying, summarise what was skipped

Do not batch all changes into one write. Some items may be intentionally stale (developer wants to keep old context). Per-item approval is non-negotiable.

BEFORE_AFTER.md

CHANGELOG.md

CODE_OF_CONDUCT.md

COMMANDS.md

CONTRIBUTING.md

EDITOR_INTEGRATIONS.md

GETTING_STARTED.md

HOW_IT_WORKS.md

install.sh

INSTALLATION.md

LAUNCH.md

PROMPTS.md

QUICKSTART.md

README.md

renovate.json

SECURITY.md

SKILL.md

tessl.json

tile.json