mirror of
https://github.com/penpot/penpot.git
synced 2026-09-24 04:46:14 +00:00
* ♻️ Keep agent content on standard paths, drop client shims Agent guidance stays where the ecosystem reads it: AGENTS.md at the root and the skills in .agents/skills. Codex scans .agents/skills and follows symlinks, opencode lists it among its discovery locations, and Cursor, Zed, Warp, Cline and Amp use the same project path. Claude Code reads neither, so it needed CLAUDE.md and .claude/skills. Committing those two paths is not a neutral default. Both are gitignored, git treats ignored files as expendable, and a checkout that needs the path deletes whatever a contributor keeps there without a warning. Neither sparse-checkout nor skip-worktree offers a way out, because both make the next pull abort. The two links are now created by the contributor, once per clone, and documented in .agents/README.md. AGENTS.local.md and .agents/local/ give every client one personal layer that composes on top of the shared one, instead of one file per client inside the repository. sync-workspace seeds the two links for ws1 and above, the way it already seeds the gitignored config.js, so the devenv workflow does not change. AI-assisted-by: claude-opus-5 Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro> * ♻️ Lean on Claude Code reading AGENTS.md, drop the pointer Claude Code 2.1.277 reads AGENTS.md through the built-in agents-md plugin, whose default mode loads it in a project that has no instruction file of its own. Deleting the committed CLAUDE.md is what turns that on here, so the pointer a Claude user had to create is no longer part of the setup, and only the .claude/skills link remains: the plugin covers instruction files, and skills still load from that path alone. The instruction that replaces the pointer is a removal. A CLAUDE.md, .claude/CLAUDE.md or CLAUDE.local.md anywhere from the root down to the working directory hands the project back to CLAUDE.md and hides this repository's AGENTS.md, while .claude/rules/*.md and the person's own ~/.claude/CLAUDE.md do not count and stay usable for personal steering. CLAUDE.local.md joins the ignore list, and a hard rule in AGENTS.md forbids all three. The docs name the version, say the fallback has not reached Bedrock, Vertex or Foundry, and say the stable auto-update channel runs about a week behind the default one, so the symlink is documented as the stopgap for those cases and as something to drop afterwards. sync-workspace seeds the skills link alone for the same reason. AI-assisted-by: claude-opus-5 Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro> * 📎 Remove skills directory mention on AGENTS.md Signed-off-by: Andrey Antukh <niwi@niwi.nz> --------- Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro> Co-authored-by: Andrey Antukh <niwi@niwi.nz>
530 lines
23 KiB
Markdown
530 lines
23 KiB
Markdown
# Agentic development with opencode inside devenv
|
|
|
|
This doc shows how to run AI-assisted development for Penpot inside the
|
|
devenv with [opencode](https://opencode.ai). It covers the setup once,
|
|
then points to the skills that drive daily work.
|
|
|
|
Full reference lives in the technical guide:
|
|
|
|
- [Dev environment](../docs/technical-guide/developer/devenv.md)
|
|
|
|
This file does not repeat those guides. It gives the short path and
|
|
leaves room for notes we add step by step.
|
|
|
|
## TL;DR
|
|
|
|
```bash
|
|
./manage.sh pull-devenv
|
|
./manage.sh run-devenv --ws 0 --attach
|
|
```
|
|
|
|
Then open a shell in the container tmux session, run `opencode` inside
|
|
~/penpot directory.
|
|
|
|
## 1. Introduction
|
|
|
|
The LLM client — opencode, Claude Code, or Codex — runs in a shell
|
|
inside the plain devenv container, with the repo mounted and the
|
|
skills in this folder driving the work. One client session per
|
|
workspace (`ws0` is the live repo, `ws1+` are sibling clones).
|
|
|
|
This doc is written around opencode, but Claude Code runs the same
|
|
way inside devenv and follows exactly the same flows. This is not
|
|
the "agentic devenv" (`--agentic`) from the technical guide, which
|
|
runs the client outside devenv and wires it in over MCP — here the
|
|
client lives inside the sandboxed devenv docker.
|
|
|
|
The content lives at the paths the ecosystem agreed on: `AGENTS.md` at the
|
|
repository root and the skills in this folder, `.agents/skills/`. Codex,
|
|
opencode, Cursor, Zed, Amp, omp and pi read both without any setup.
|
|
|
|
Claude Code reads `AGENTS.md` from 2.1.277, through the built-in
|
|
`agents-md` plugin, but only in a project that has no instruction file of
|
|
its own. A `CLAUDE.md`, `.claude/CLAUDE.md` or `CLAUDE.local.md` anywhere
|
|
from the repository root down to your working directory hands the whole
|
|
project back to `CLAUDE.md`, and this file's guidance stops arriving. Keep
|
|
none of them here. Personal steering goes in `AGENTS.local.md`, or in
|
|
`.claude/rules/*.md` and `~/.claude/CLAUDE.md`, which the plugin does not
|
|
count and which therefore leave the project guidance in place.
|
|
|
|
Skills are untouched by that plugin and still load from `.claude/skills`
|
|
alone, which is not committed, so link it once per clone:
|
|
|
|
```bash
|
|
mkdir -p .claude && ln -s ../.agents/skills .claude/skills
|
|
# or, with Node:
|
|
npx skills add ./.agents/skills --agent claude-code
|
|
```
|
|
|
|
Below 2.1.277, and on Bedrock, Vertex and Foundry where the fallback has
|
|
not arrived, add `ln -s AGENTS.md CLAUDE.md` and drop it once your client
|
|
has the feature. The auto-update channel decides when that is: `latest`,
|
|
the default, has it; `stable` runs about a week behind; Homebrew and the
|
|
Linux packages update by hand. Personal skills go in
|
|
`.agents/local/skills/<name>/`.
|
|
|
|
Every one of those paths is gitignored, so your own files keep working and
|
|
no checkout overwrites them. Inside the devenv, `ws0` sees the links from
|
|
the live checkout, and `ws1` and above are seeded on their first sync.
|
|
|
|
Unlike the agentic devenv, running the client inside the devenv
|
|
docker gives it full access to the live environment: every
|
|
dependency already resolved by the image, so the agent can write
|
|
and run tests directly, query the running PostgreSQL, and reach
|
|
the backend and frontend through nREPL — no proxies, no round
|
|
trips outside the container.
|
|
|
|
And if you later want vision, it is one MCP entry away — a
|
|
headless Playwright server in your `opencode.json`:
|
|
|
|
```json
|
|
{
|
|
"$schema": "https://opencode.ai/config.json",
|
|
"mcp": {
|
|
"playwright": {
|
|
"type": "local",
|
|
"command": ["npx", "-y", "@playwright/mcp", "--headless"],
|
|
"enabled": true,
|
|
"env": {}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## 2. Quickstart: bring up devenv and run opencode inside
|
|
|
|
Pull once, then bring up the workspace you want (add `--ws 1`,
|
|
`--ws 2`, … for more):
|
|
|
|
```bash
|
|
./manage.sh pull-devenv
|
|
./manage.sh run-devenv --ws 0 --attach # ws0 (the live repo)
|
|
```
|
|
|
|
This attaches to the container tmux session. Open a new shell there
|
|
(`Ctrl+b c`), `cd` to the repo, and run opencode directly:
|
|
|
|
```bash
|
|
cd penpot;
|
|
opencode
|
|
```
|
|
|
|
One session drives exactly one workspace — for N parallel workspaces,
|
|
open one container shell and one opencode session per workspace.
|
|
|
|
Stop with `./manage.sh stop-devenv [--ws N | --all]`. Shared infra
|
|
stops when the last workspace stops.
|
|
|
|
|
|
## 3. Connecting providers
|
|
|
|
### Starting point: Zen free models, no login needed
|
|
|
|
The easiest way to try the setup is Zen's free models — they need no
|
|
login and no key. Just run opencode, pick a free model, and work.
|
|
|
|
That said, creating a Zen account and connecting with your API key is
|
|
still worth it from day one: it unlocks the full model list, spend
|
|
limits, auto-reload, and the Go-overflow fallback below. Connect
|
|
through the TUI:
|
|
|
|
- Run `/connect`, pick a provider, paste the key.
|
|
- Run `/models` to see what that provider offers.
|
|
|
|
### OpenCode Go (subscription, best value for daily use)
|
|
|
|
$10/month subscription with generous included usage — up to $60/month
|
|
of model consumption at published per-token rates, depending on the
|
|
model. Best value if you work mostly with open coding models
|
|
(GLM, Kimi, Qwen, DeepSeek, MiniMax, LongCat…).
|
|
|
|
The strong part: when you hit a model's monthly limit, Go can fall
|
|
back to your Zen balance instead of blocking (enable *Use balance* in
|
|
the console). So the setup many of us use is Go + Zen credit on top —
|
|
subscription first, pay-as-you-go overflow after.
|
|
|
|
### OpenCode Zen (pay per use)
|
|
|
|
Zen is the opencode team's gateway: curated models tested for coding
|
|
agents, fair prices, no markups, stable latency. You top up credit
|
|
and pay per request, with monthly spend limits and auto-reload.
|
|
|
|
Free usage is generous: the free models carry limits good enough for
|
|
real work, not just a quick taste. Worth knowing: brand-new,
|
|
unannounced models often show up on Zen first with a very generous
|
|
free quota so people try them — e.g. `0x Alpha`, which later turned
|
|
out to be GLM-5.3-Flash. Keep an eye on the free list; the newest
|
|
entry is often the best deal.
|
|
|
|
Two reasons to have a Zen account even with Go:
|
|
|
|
- It absorbs Go overflow (see above).
|
|
- Its free models let you try the whole setup before paying.
|
|
|
|
### OpenRouter (widest catalog)
|
|
|
|
If you already have an account, connect it: the widest model range in
|
|
one place. Trade-off is latency and occasional instability versus Zen,
|
|
which is tuned for coding agents.
|
|
|
|
Beyond code: OpenRouter also serves image, video, and audio models.
|
|
opencode itself cannot call those directly — it is built for code —
|
|
but a cheap model can quickly build you a small tool or script that
|
|
talks to them through the OpenRouter API. So if you also generate
|
|
content other than code and text, having OpenRouter connected is
|
|
worth it: the agent wires the plumbing for you.
|
|
|
|
### OpenAI (subscription or API key)
|
|
|
|
If you have an OpenAI subscription or API access, connect it — it
|
|
works very well as a daily driver alongside (or instead of) Go/Zen.
|
|
|
|
### Suggested combos
|
|
|
|
| Profile | Connect |
|
|
|---|---|
|
|
| Try it out | Nothing (Zen free models, no login) |
|
|
| Try it out, properly | Zen account + API key (free models + limits) |
|
|
| Daily use, best value | Go + Zen credit (overflow) |
|
|
| Widest model choice | Add OpenRouter |
|
|
| Already pay OpenAI | Add OpenAI account |
|
|
|
|
## 4. Recommended models
|
|
|
|
Personal picks from Andrey, current as of September 2026. Models come
|
|
and go, so treat this as a snapshot — the shape (one cheap solver,
|
|
one reviewer/planner, one explorer) matters more than the names.
|
|
|
|
| Model | Role | How often |
|
|
|---|---|---|
|
|
| Muse Spark 1.3 (`high`) | Main solver: plan, review, develop. Sharp and cheap — covers ~70% of coding tasks. | Daily |
|
|
| GLM-5.3-Flash | Reasoning all-rounder, now mostly code/plan reviewer and planner. | Daily |
|
|
| DeepSeek V4.1 Flash (`high`) | Explorer: code and idea exploration, sometimes development. Especially good at small bash/node utilities for repo chores and changelog updates. | Daily |
|
|
| LongCat 2.0 | Backup solver, occasional stand-in for Muse Spark 1.3. | Weekly |
|
|
| GPT-5.6 Luna | Alternative to DeepSeek Flash; pricier, unclear the extra cost pays off. | Rarely |
|
|
| Qwen3.8 Flash | As strong as the top three; used in rotation to avoid hammering one model. Less Go subsidy than the top picks, so mostly in overflow mode. | Overflow |
|
|
| MiMo-V2.5-Pro | Former main model; slightly pricier now next to Muse Spark / GLM-Flash / LongCat, and less Go subsidy — used in overflow. | Overflow |
|
|
| Kimi K3 | Heavy reasoning for hard reviews and plans. Expensive, ~1% of tasks. | Rarely |
|
|
| GLM-5.3 | Same slot as Kimi K3: hard reviews and plans only. | Rarely |
|
|
|
|
**TL;DR:** the first three (Muse Spark 1.3, GLM-5.3-Flash, DeepSeek
|
|
V4.1 Flash) are a good starting point.
|
|
|
|
## 5. Customizing your `opencode.json`
|
|
|
|
opencode merges config in this order (later wins):
|
|
|
|
1. Global: `~/.config/opencode/opencode.json` (on host, or the dir
|
|
mounted with `--opencode-config-dir` inside devenv —
|
|
see §9 Advanced usage).
|
|
2. Project: `opencode.json` at the repo root (gitignored on purpose —
|
|
use it to override the global entries for one workspace).
|
|
|
|
Below is a full working example of my personal config at the date of
|
|
writing this. It is only an example: define whatever subagents you
|
|
need, with whatever models you like or work with.
|
|
|
|
Copy it to `opencode.json` on the root of the repo:
|
|
|
|
```json
|
|
{
|
|
"$schema": "https://opencode.ai/config.json",
|
|
"disabled_providers": ["amazon-bedrock"],
|
|
"subagent_depth": 2,
|
|
"agent": {
|
|
"compaction": {
|
|
"model": "opencode-go/deepseek-flash",
|
|
"variant": "high"
|
|
},
|
|
"title": {
|
|
"model": "opencode-go/deepseek-flash",
|
|
"variant": "low"
|
|
},
|
|
"explore": {
|
|
"model": "opencode-go/deepseek-flash",
|
|
"variant": "high"
|
|
},
|
|
"build": {
|
|
"prompt": "{file:.agents/prompts/engineer-agent-prompt.md}",
|
|
"permission": {
|
|
"external_directory": {
|
|
"/tmp/**": "allow"
|
|
}
|
|
}
|
|
},
|
|
"general": {
|
|
"prompt": "{file:.agents/prompts/engineer-agent-prompt.md}",
|
|
"permission": {
|
|
"external_directory": {
|
|
"/tmp/**": "allow"
|
|
}
|
|
}
|
|
},
|
|
"engineer-glm": {
|
|
"mode": "subagent",
|
|
"model": "opencode-go/glm-5.3-flash",
|
|
"variant": "high",
|
|
"prompt": "{file:.agents/prompts/engineer-agent-prompt.md}",
|
|
"permission": {
|
|
"*": "allow",
|
|
"task": {
|
|
"*": "allow"
|
|
}
|
|
}
|
|
},
|
|
"engineer-kimi": {
|
|
"mode": "subagent",
|
|
"model": "opencode/kimi-k3",
|
|
"variant": "high",
|
|
"prompt": "{file:.agents/prompts/engineer-agent-prompt.md}",
|
|
"permission": {
|
|
"*": "allow",
|
|
"task": {
|
|
"*": "allow"
|
|
}
|
|
}
|
|
},
|
|
|
|
"engineer-qwen": {
|
|
"mode": "subagent",
|
|
"model": "opencode-go/qwen3.7-plus",
|
|
"variant": "high",
|
|
"prompt": "{file:.agents/prompts/engineer-agent-prompt.md}",
|
|
"permission": {
|
|
"*": "allow",
|
|
"task": {
|
|
"*": "allow"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
What the blocks mean:
|
|
|
|
- `compaction` / `title` / `explore`: cheap background agents. Keep
|
|
them on a fast model; `title` uses the `low` variant on purpose.
|
|
- `build` / `general`: the main agents. They load the shared prompt
|
|
`{file:.agents/prompts/engineer-agent-prompt.md}` and may only touch
|
|
`/tmp/**` outside the repo without asking for explicit permision.
|
|
- `engineer-*`: one subagent per model family, all with the same
|
|
prompt and full permissions (`"*": "allow"`). They purpose are
|
|
specially for delegate work to them because are defined to be used
|
|
only as subagents.
|
|
- `disabled_providers` / `subagent_depth`: global guards. Keep
|
|
`"$schema"` — opencode refuses to start if any field is wrong.
|
|
|
|
How the `engineer-*` subagents are actually used — delegating work to
|
|
them to keep the main context clean — is covered in §6 Common agentic
|
|
flows.
|
|
|
|
Note this is opencode-only: other clients have their own way of
|
|
defining subagents or helpers — or none at all.
|
|
|
|
## 6. Common agentic flows
|
|
|
|
Work happens two ways: directly in your session, or delegated to a
|
|
subagent. Besides the `engineer-*` subagents from §5 there is a
|
|
builtin `general` subagent. Delegating planning and review to a
|
|
subagent starts a fresh, clean context with a clean prompt instead
|
|
of growing the main session — the main lever for keeping context
|
|
small. To delegate without switching models, delegate to `general`.
|
|
|
|
### Issue / error report flow
|
|
|
|
1. **Frame the problem.** Enter Plan mode (TAB in opencode) and paste the
|
|
report with your intent: "investigate this and find the possible cause",
|
|
"investigate and tell me where this points", or "does this still apply?".
|
|
Explore until you and the agent roughly agree on the problem.
|
|
2. **Write the plan.** Run `/make-a-plan` — it executes in Build mode.
|
|
If you need to step in and answer something yourself, press TAB to
|
|
leave Build mode. Use Plan mode only when you want a hard guarantee
|
|
that the agent modifies no file under any circumstance. If you
|
|
explored with a weaker model but want a stronger one to write the
|
|
plan, switch models first or delegate:
|
|
`/make-a-plan delegate to @engineer-glm`.
|
|
3. **Iterate on the plan.** The plan is saved to `.agents/plans/`, so you
|
|
never depend on LLM memory: read the file directly, or run `/review-plan`
|
|
for a second opinion (delegation works here too). Complex plans deserve a
|
|
review; simple ones can skip it.
|
|
4. **Execute.** Run `/implement-plan`. It first prints the full picture —
|
|
whether it will create an issue and a branch, the execution style, and a
|
|
task checklist — and waits for your go-ahead. Say "step by step" to stop
|
|
after each task (one commit per task) so you can verify as it goes;
|
|
the default runs all tasks with one final commit.
|
|
5. **Land the work.** When it finishes, either push yourself and run
|
|
`/create-pr`, or loop `/review-code` → `/make-a-plan` →
|
|
`/implement-plan` until the findings are addressed, then push and
|
|
`/create-pr`. Nothing pushes for you — you always push from your shell.
|
|
|
|
> Note: `/implement-plan` checks the current branch. On a base branch
|
|
> (`main`, `develop`, `staging`) it creates a GitHub issue and a branch
|
|
> `issue-NNNN`; on an existing feature branch it continues there and
|
|
> creates nothing. The pre-run summary tells you which applies. Read the
|
|
> skill at `.agents/skills/implement-plan/SKILL.md` — it is
|
|
> self-explanatory.
|
|
|
|
### Big feature with multiple plans
|
|
|
|
When the work is too large for a single plan, tell `/make-a-plan`
|
|
up front: produce a high-level roadmap where each task will get its
|
|
own execution plan, and the roadmap doubles as the progress tracker.
|
|
|
|
From there the flow mirrors the issue flow above, one level down:
|
|
take each roadmap task in turn, write its own plan (`/make-a-plan`,
|
|
delegating when it helps), review it when the task is complex
|
|
(`/review-plan`), implement it (`/implement-plan`), and mark progress
|
|
on the roadmap as you land each piece.
|
|
|
|
### Plan file naming (base + derivatives)
|
|
|
|
Base plans live in `.agents/plans/` as `YYYY-MM-DD-<slug>.md`.
|
|
Derived plans reuse the parent basename verbatim and append one
|
|
suffix per level with `--`, with no new date — the parent prefix
|
|
keeps everything adjacent in `ls`:
|
|
|
|
- Review followup on implemented work:
|
|
`2026-09-14-paste-before-init-crash.md` →
|
|
`2026-09-14-paste-before-init-crash--review-01.md`
|
|
- Roadmap sub-plan (task number from the roadmap):
|
|
`2026-09-20-upload-pipeline-roadmap.md` →
|
|
`2026-09-20-upload-pipeline-roadmap--task-01-chunk-upload.md`
|
|
- Chained: `...--task-02-gc--review-01.md`
|
|
|
|
While a plan is still unimplemented, `/make-a-plan` revises it in
|
|
place. Once implemented and reviewed, it writes a new followup file.
|
|
Full rules live in the `planner` skill.
|
|
|
|
### Plan status lifecycle
|
|
|
|
Every plan carries `Status: draft | reviewed | done` plus an
|
|
append-only `Review Log` (UTC ISO 8601, one line per entry):
|
|
|
|
- `draft` — fresh from `/make-a-plan`.
|
|
- `reviewed` — review feedback incorporated. `/review-plan` stays
|
|
read-only; only your explicit "apply" makes `/make-a-plan` apply
|
|
the changes, flip the status, and log one line.
|
|
- `done` — `/implement-plan` closes it on completion, logging the
|
|
issue URL when one exists (never commit hashes).
|
|
|
|
A plan approved with no changes goes `draft` → `done` directly.
|
|
|
|
## 7. Connecting `gh` CLI with a token
|
|
|
|
The `create-issue` and `create-pr` flows need an authenticated `gh`
|
|
so they can run on their own. Create a fine-grained token with the
|
|
minimum scopes:
|
|
|
|
1. GitHub → Settings → Developer settings → Personal access tokens →
|
|
Fine-grained tokens → Generate new token.
|
|
2. Under Organization permissions, grant access to **Projects**.
|
|
3. Under Repository permissions, grant at least **Issues** and
|
|
**Pull requests**.
|
|
|
|
Then authenticate the CLI and follow the prompts:
|
|
|
|
```bash
|
|
gh auth login
|
|
```
|
|
|
|
Verify with `gh auth status` (token lives in
|
|
`~/.config/gh/hosts.yml`). You still push from your own shell — the
|
|
agents only read and open issues and PRs.
|
|
|
|
## 8. Troubleshooting / FAQ
|
|
|
|
> TBD — filled in step by step as issues come up.
|
|
|
|
## 9. Advanced usage
|
|
|
|
### Personal agents and prompts without committing them here
|
|
|
|
Bind-mount a host dir over the container's `~/.config/opencode`:
|
|
|
|
```bash
|
|
./manage.sh run-devenv --ws 0 --opencode-config-dir ../penpot-opencode
|
|
```
|
|
|
|
It applies at container creation, so changing it needs a stop + rerun
|
|
of that instance.
|
|
|
|
## Summary of available skills
|
|
|
|
### How the skills are organized
|
|
|
|
**Flows** are the six skills you invoke by name. Each one covers one step
|
|
in the life of a change: plan it, review the plan, implement it, review
|
|
the code, open the pull request.
|
|
|
|
**References** hold the quality standards. A flow's reviewer loads them;
|
|
you rarely touch them directly.
|
|
|
|
**Procedures** define how one concrete step is done — a plan document, an
|
|
issue, a commit. Flows call them, but they also work on their own.
|
|
|
|
**Utilities** are small helpers for everyday work: search, file lookup,
|
|
JSON, REPL access, and so on.
|
|
|
|
### Flows
|
|
|
|
| Skill | What it does | When you would say |
|
|
|---|---|---|
|
|
| [`make-a-plan`](skills/make-a-plan/SKILL.md) | Researches the task, writes an implementation plan, asks you the open questions in plain language, and saves the plan to `.agents/plans/`. | "make a plan for the token refresh bug" |
|
|
| [`review-plan`](skills/review-plan/SKILL.md) | Evaluates a plan before anyone writes code: completeness, ordering, risks. Approves it or asks for changes. | "review this plan before we start" |
|
|
| [`implement-plan`](skills/implement-plan/SKILL.md) | Shows you the full flow first — the issue and branch it will create (or the branch it continues on), the execution style, and the task checklist — and, after your go-ahead, executes a ready plan. Default: every task, one commit. On request ("step by step"): one task, one commit, your confirmation between tasks. On request ("direct"): no issue and no branch, commits on the current branch. | "implement the plan" · "step by step, one commit per task" · "direct, no branch" |
|
|
| [`review-code`](skills/review-code/SKILL.md) | Reviews a diff, branch, or PR and returns findings ranked by impact. | "review my changes before I push" |
|
|
| [`create-pr`](skills/create-pr/SKILL.md) | Opens a pull request for the current branch — with checks on base branch, commits, issue, and push state — or updates an existing PR's title and description. | "open a PR for this branch" |
|
|
| [`resolve-git-conflicts`](skills/resolve-git-conflicts/SKILL.md) | Untangles merge or rebase conflicts: explains both sides, proposes a resolution, applies it after you approve. Never runs `git rebase --continue`. | "resolve these conflicts" |
|
|
|
|
### References
|
|
|
|
| Skill | What it holds |
|
|
|---|---|
|
|
| [`plan-review-criteria`](skills/plan-review-criteria/SKILL.md) | The plan review rubric: six axes, severity levels, approval standard, output format. The `review-plan` reviewer loads it. |
|
|
| [`code-review-criteria`](skills/code-review-criteria/SKILL.md) | The code review rubric: five axes, core principles (DRY, KISS, YAGNI), severity format, verdict. The `review-code` reviewer loads it. |
|
|
|
|
### Procedures
|
|
|
|
| Skill | What it does |
|
|
|---|---|
|
|
| [`planner`](skills/planner/SKILL.md) | The spec of a good plan: context, architecture decisions, tasks with acceptance criteria, checkpoints. Used by `make-a-plan`. |
|
|
| [`create-issue`](skills/create-issue/SKILL.md) | Creates a GitHub issue that follows Penpot conventions. Used by `implement-plan`; also works on its own. |
|
|
| [`create-commit`](skills/create-commit/SKILL.md) | Makes a commit the Penpot way: emoji subject, clear body, `AI-assisted-by` trailer. Used by `implement-plan`; also works alone when you say "commit this". |
|
|
|
|
### Utilities
|
|
|
|
| Skill | What it does |
|
|
|---|---|
|
|
| [`bat-cat`](skills/bat-cat/SKILL.md) | Read files in the terminal with syntax highlighting and line numbers. |
|
|
| [`fd-find`](skills/fd-find/SKILL.md) | Find files by name or pattern, respecting `.gitignore`. |
|
|
| [`ripgrep`](skills/ripgrep/SKILL.md) | Fast content search with regular expressions. |
|
|
| [`jq-json-processor`](skills/jq-json-processor/SKILL.md) | Slice, filter, and reshape JSON output. |
|
|
| [`nrepl-eval`](skills/nrepl-eval/SKILL.md) | Run Clojure or ClojureScript code in the live REPL sessions (backend and frontend). |
|
|
| [`taiga`](skills/taiga/SKILL.md) | Look up Penpot issues, user stories, and tasks in Taiga. |
|
|
| [`testing`](skills/testing/SKILL.md) | The repo's testing rules and TDD workflow, loaded before writing tests. |
|
|
| [`local-ci`](skills/local-ci/SKILL.md) | Run CI-style lint, test, and format checks for the modules you touched with `scripts/ci`, and read the logs when they fail. |
|
|
| [`security-and-hardening`](skills/security-and-hardening/SKILL.md) | Security checks for code that handles user input, auth, or external services. |
|
|
| [`ste`](skills/ste/SKILL.md) | Rewrites prose in Simplified Technical English. Loads only when you name it. |
|
|
| [`refine-prompt`](skills/refine-prompt/SKILL.md) | Rewrites a rough prompt into a clearer one. Never runs the prompt. |
|
|
| [`update-changelog`](skills/update-changelog/SKILL.md) | Regenerates `CHANGES.md` from a GitHub milestone. |
|
|
|
|
### A typical round
|
|
|
|
1. `/make-a-plan` — you get a plan and a saved file in `.agents/plans/`.
|
|
2. `/review-plan` — a second opinion; approve or request changes.
|
|
3. `/implement-plan` — the code gets written and committed. Starting from a base branch, it also opens the GitHub issue and the `issue-NNNN` branch; the plans that follow continue on that same branch.
|
|
4. `/review-code` — a reviewer checks the commit.
|
|
5. `/create-pr` — the branch goes up as a pull request.
|
|
|
|
Every step also works on its own, and you can always say what you want
|
|
in plain words — the agents pick the right skill from what you say.
|
|
|
|
### Adding or changing a skill
|
|
|
|
Create a folder here with a `SKILL.md` inside. The file needs `name` and
|
|
`description` in its frontmatter, and a clear "When to use" section so
|
|
agents know when to reach for it. Keep one job per skill, and keep the
|
|
two families apart: flows are named with a verb first; reference skills
|
|
end in `-criteria`.
|