Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 72 additions & 81 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,104 +1,95 @@
# OpenCode Instructions

## Worktrees
## Environment

- Always perform repository code and configuration changes in a Git worktree, never in the canonical checkout.
- Use the shared workspace-root directory `/data/workspace/.worktrees/<repository>/<task>`; do not create repository-local `.worktrees` folders.
- Before editing, inspect the canonical checkout and create a task branch with `git worktree add`. Move the OpenCode session to the worktree and run edits, tests, commits, and pushes there.
- Keep uncommitted user changes untouched. Do not delete worktrees with uncommitted work or remove another session's worktree.
- For research-only tasks, reading the canonical checkout is fine. For non-Git directories, ask before initializing a repository.
- Use the shared workspace-root directory `/data/workspace/.worktrees/<repository>/<task>`, not a repository-local `.worktrees` folder. It overrides a skill's default worktree location.
- Create the task branch with `git worktree add`, move the session into the worktree, and run edits, tests, commits, and pushes there. Leave uncommitted user changes and other sessions' worktrees alone.
- Reading the canonical checkout is fine for research. Ask before initializing a repository in a non-Git directory.
- Never delete, move, or reset `/data/.config` or `/data/.local`. They hold the OpenCode database, logs, credentials, and OpenChamber settings for every session.
- Load skills with the native `skill` tool and delegate with native `subagent` tools. Do not use Orchestra.

## Workflow

- Use Superpowers skills through the native `skill` tool for planning, test-driven development, debugging, verification, and review when applicable. Use native `subagent` tools when those skills call for delegation; do not use Orchestra.
- The shared worktree location above overrides a skill's default worktree location. Preserve the Git and pull request rules below when following skills.
- Execute well-specified work directly. Reserve subagents for genuinely parallel or exploratory work, and tell each one to commit and push as it goes and to keep scratch files outside the repository.
- Once the user has made a decision, act on it. Do not reopen it or add verification loops they did not ask for.
- Stop everything you started (dev servers, containers, background processes, temp files) before finishing.
- Use Superpowers skills when they apply, and keep the Git and pull request rules below while following them.
- Execute well-specified work directly. Use subagents only for parallel or exploratory work, and tell each one to push as it goes, keep scratch files outside the repository, and keep its prose short.
- Once the user decides, act on it without pausing for confirmation, reopening the decision, or adding verification loops they did not ask for.
- Fix an obvious visible bug straight away. Skip git history forensics.
- To audit noise (alerts, failing jobs), tally the actual signal in the inbox, channel, or logs before sweeping repositories.
- During an incident, do only the task the user named and report blockers in one line.
- Stop everything you started (servers, containers, background processes, temp files) before finishing.

## Scope

- A narrowly scoped request defines the diff. Mention adjacent improvements in chat instead of committing them.
- When something broken turns up mid-task, fix it in a PR rather than filing a ticket for it.
- Never delete or weaken tests to make CI green. Ask first.
- Do not build machinery for edge cases a bot reviewer raises unless the user wanted that capability. Say it is out of scope.
- Prefer adding a function over changing an existing function's signature.
- When a producer omits a value the contract requires, fix the producer instead of loosening the contract.
- Do not ship dependency overrides (`pnpm.overrides`, `resolutions`, patches, vendoring) as a workaround. Find the upstream fix or report that the upgrade is blocked.
- If the user said "don't commit" or "edits only", that holds for follow-up changes until they say otherwise.
- Work in a named repository ends when its change is merged and its CI is green. Do not fan out into downstream repositories unasked.
- A narrow request defines the diff. Mention extras in chat, and stop at the named repository once its change merges with green CI.
- Give a deliverable exactly the fields the user named. Caveats go in chat.
- Fix what breaks mid-task in a PR instead of filing tickets, and add related work to the existing ticket.
- Never delete or weaken tests to pass CI without asking.
- Skip edge cases a bot reviewer raises unless the user wants that capability.
- Add a function rather than change an existing signature.
- When a producer omits a required value, fix the producer, not the contract.
- No dependency overrides (`pnpm.overrides`, `resolutions`, patches, vendoring) as workarounds. Find the upstream fix or report the upgrade blocked.
- "Don't commit" or "edits only" holds for follow-ups until the user lifts it.
- Never overwrite a PR body, issue, or comment a human wrote unless they give the new text. Comment instead.

## Verification

- Run a command that reads the state before claiming it: PR merged, file tracked, field present, deploy live. An empty result means "cannot see", not "does not exist".
- If an error or pending run would confirm the work, go and look. Do not end with an offer to check.
- Validate approaches that touch external systems against current primary docs, not memory, and cite the URLs.
- Prefer CI for full test suites. Push and read the checks. Run locally only to iterate on one failing test or lint error, and never quote a local pass once CI has run.
- When a repository ships a production-like local setup (Docker, Compose, a run script), test with it rather than a quick substitute.
- Pin third-party GitHub Actions by commit SHA after checking `gh api repos/<owner>/<repo>/releases/latest`.
- When changing CI, trace which tool reads which variable. A secret existing in the repository does not mean the failing step uses it.

## Git Rules

- **NEVER force-push** (`git push --force`, `git push -f`, `--force-with-lease`, etc.) under any circumstances.
- Never amend or rebase a commit that has been pushed. Make follow-up commits.
- **Incremental commits:** Commit changes incrementally and granularly with clear, descriptive commit messages matching conventional commit conventions. When importing existing or untracked state into a repository, commit the baseline state first before making improvements so the user can review the diff.
- Stage explicit paths. Never `git add -A` or `git add .` while another agent or process shares the checkout.
- Gate every commit and push on the branch name, for example `[ "$(git branch --show-current)" = "<branch>" ] && git commit ...`, then confirm the push with `git rev-parse HEAD origin/<branch>`.
- The user pushes commits to open PR branches. Fetch before pushing. If a push is rejected, pull (a merge commit is fine) and push again.
- Use one branch per task, even across phases. Branch independent PRs off `main` instead of stacking them.
- Pass `--repo owner/name` to `gh pr` commands instead of relying on the working directory.
- Never run `gh pr merge --auto`. Without branch protection it merges immediately instead of waiting for CI.
- After a squash merge, confirm late commits landed with `git merge-base --is-ancestor <sha> origin/main`, and re-land anything missing in a small follow-up PR.
- Commits under the user's account are often an earlier agent's work. Do not cite authorship metadata as evidence of who designed something.

## Programming languages

- TypeScript, Shell, and Go are the only permitted programming languages in the user's repositories without explicit user approval. Do not introduce Python code, dependencies, or artifacts. Existing declarative configuration and third-party services are not permission to add another programming language.
- Run a command that reads the state before claiming it (merged, tracked, deployed). Empty output means "cannot see", not "absent".
- Derive inventories and numbers from the code with `file:line`, not from tickets or old surveys.
- Before blaming the environment, test it against a known-good control.
- If an error or pending run would confirm the work, look at it instead of offering to.
- Check approaches against current primary docs and cite the URLs.
- Let CI run full suites and regenerate docs. Locally, run only the one failing test or lint, and never quote a local pass once CI has run.
- Test with the repository's production-like setup (Docker, Compose, a run script) when it has one.
- Pin third-party GitHub Actions to the commit SHA of `releases/latest`.
- When changing CI, trace which tool reads which variable.

## Git

- **Never force-push** (`--force`, `-f`, `--force-with-lease`), and never amend or rebase a pushed commit.
- Commit small and often with Conventional Commit messages. When importing existing state, commit it as-is first so the user can review the diff.
- Stage explicit paths. Never `git add -A` or `git add .`.
- Gate every commit and push on the branch, as in `[ "$(git branch --show-current)" = "<branch>" ] && git commit ...`, then confirm with `git rev-parse HEAD origin/<branch>`.
- The user pushes to open PR branches. Fetch before pushing, and if a push is rejected, pull (a merge commit is fine) and retry.
- One branch per task. Branch independent PRs off `main`, and stack only when asked, with `gh stack`.
- Pass `--repo owner/name` to `gh pr`. Never run `gh pr merge --auto`, which merges without waiting for CI.
- After a squash merge, check late commits landed with `git merge-base --is-ancestor <sha> origin/main`, and re-land missing ones in a follow-up PR.
- Commits under the user's account are often an agent's work, so authorship metadata proves nothing about who designed something.
- Report git outcomes, not each step.

## Code

- Default to no comments. Add one line for a non-obvious why, two only when the second adds a real constraint. Rationale belongs in the commit message.
- Never restate the code, narrate history, or put ticket IDs or current infrastructure state in comments.
- Config files (YAML, Dockerfiles, workflows) get no explanatory comments.
- Every exported Go identifier gets exactly one doc comment that starts with its name.
- Never swallow errors. Return, log, or show every one, and in retry loops surface the last error on timeout.
- Prefer the standard library and well-known packages over hand-rolled utilities.
- Use clearly fictional names (Ada Lovelace, alice, bob) in tests, fixtures, and docs, never real people.
- Use `Taskfile.yml` (go-task v3) for build automation in personal projects, not Makefiles.
- Edit YAML with `yq` and format it with `yq -iP .`, since plain `-i` corrupts folded block scalars. Put YAML comments on their own line.
- Pipe JSON with `printf '%s' "$json"`, never `echo`, which expands `\n` in zsh.
- In Go repositories that depend on `gutil`, use it for logging, JSON responses, and ETags. Use chi for routing and GORM with `AutoMigrate` for Postgres. Load the `go-repo` skill for repository plumbing.
- `golangci-lint` caps output at 50 issues per linter. Pass `--max-issues-per-linter=0 --max-same-issues=0` for true counts.
- Measure Go coverage with the toolchain from `go.mod` (`GOTOOLCHAIN=go1.x.y`), since totals differ between Go versions.
- Regenerate lock files with their tool (`tofu init -upgrade`, `pnpm install`). Never hand-edit them.
- In Terraform, module constants go in `locals.tf`, not in variables with defaults.
- Personal repositories use TypeScript, Shell, and Go. Ask before adding any other language, Python included.
- Default to no comments. Write one line for a non-obvious why. Never restate code, narrate history, or mention tickets or current infrastructure state. Config files get no comments.
- Never swallow errors. In retry loops, surface the last error on timeout.
- Prefer the standard library and well-known packages over hand-rolled code. Judge approaches on substance, since import and lockfile churn cost nothing.
- Use fictional names (Ada Lovelace, alice, bob) in tests, fixtures, and docs.
- Personal projects use `Taskfile.yml`, not Makefiles.
- Edit YAML with `yq` and format with `yq -iP .`, because plain `-i` corrupts folded scalars. YAML comments go on their own line.
- Pipe JSON with `printf '%s'`, never `echo`, which expands `\n` in zsh.
- Regenerate lock files with their tool, never by hand, and keep `yarn upgrade` and `pnpm update` out of CI.
- In Terraform, put module constants in `locals.tf`, not defaulted variables. Pin modules `~> X.Y.Z` and providers `~> X.Y`.
- Load the `go-repo` skill before writing Go.

## Writing

- Brevity matters most. Cut every sentence that does no work, and cut before publishing, not after.
- ASCII only. No em dashes.
- Never hard-wrap Markdown or prompts. One paragraph or bullet per line.
- Link to sources instead of paraphrasing them.
- READMEs lead with install and usage. Check every factual claim in docs against what was measured.
- Return requested documents in the reply, not in a new file, unless the user names a path.
- When the work depends on something unknown, look it up, then ask the user directly before continuing. Never bury a decision in a trailing caveat or a PR body.

## Pull request workflow

- Open draft pull requests early, then commit and push small, verified changes frequently instead of waiting for the whole task to finish.
- Open a pull request by default for repository code or configuration changes after verification passes; do not stop at uncommitted local edits unless the user explicitly asks otherwise.
- Load the `commit-push-pr` skill when committing, pushing, or opening a pull request.

## Pull request descriptions

- Before creating or editing a PR, read and follow its repository's PR template. Check the repository owner's `.github` repository for an inherited template when there is no repository-local template. Never assume no local file means no template exists.
- Use exactly the template's sections and keep each concise. Do not add Summary, Validation, Test Plan, Deployment, or other assistant-generated sections. Put essential rollout caveats under the risks section and leave detailed setup instructions in repository documentation.
- Keep bodies to six lines of content or fewer, excluding template headers. Write for the reviewer: no narrative of the work, no bugs found along the way, no test-plan checklist.
- Never add AI attribution to a PR body. `Co-Authored-By` trailers in commits are fine.
- Use Conventional Commit PR titles with lowercase subjects. PRs are squash-merged.
- Pick the type honestly: `fix` for repairs, `chore`, `docs`, `ci`, or `build` for plumbing, and `feat` only for a new user-facing capability. Avoid `refactor`. The title drives semantic-version bumps.
- Brevity matters most. Cut before publishing, not after.
- ASCII only, no em dashes. Never hard-wrap Markdown or prompts, even inside a wrapped file.
- Link sources instead of paraphrasing them.
- READMEs lead with install and usage. Check each factual claim against what was measured.
- Return requested documents in the reply unless the user names a path.
- Status updates and summaries get about ten short bullets, nested for detail, with no bold lead-ins or tables. Fence text meant for pasting in a `markdown` block.
- When the work depends on an unknown, look it up, then ask the user directly in one batched question. Never bury a decision in a caveat or PR body.

## Pull requests

- Open a draft PR early and push small commits often, unfinished work included, noting WIP in the message. Do not stop at uncommitted edits unless told to.
- Load the `commit-push-pr` skill to commit, push, or open a PR.
- Follow the repository's PR template, or the owner's `.github` template when the repository has none. With neither, write a short summary and a few bullets.
- Use only the template's sections. Tick its fixed checklist items without adding new ones, and write "No Risks Found" rather than dropping a risks section.
- Six lines of content at most, excluding headers, covering what the PR does, what to look at, and risks or deferred work. Write for the reviewer, with no narrative, no bugs found along the way, and no test plan. Link detail that already lives in a README or the commit message.
- No AI attribution in PR bodies. `Co-Authored-By` trailers in commits are fine.
- Titles are lowercase Conventional Commits, and the squash-merged title drives the version bump. Use `fix` for repairs, `chore`, `docs`, `ci`, or `build` for plumbing (`chore(deps)` for dependencies), and `feat` only for a new user-facing capability. Never `refactor`. Mark breaking changes with `!` before the colon.

## Personal sites

Expand Down
6 changes: 5 additions & 1 deletion skills/go-repo/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
---
name: go-repo
description: Conventions for creating or maintaining the user's Go repositories, covering scaffolding, lint configuration, CI workflows, versioning, and goreleaser releases. Use when creating a Go repository or changing its lint, CI, or release plumbing.
description: Conventions for the user's Go repositories, covering code, libraries, scaffolding, lint, CI, versioning, and goreleaser releases. Use before writing Go in the user's repositories or changing their plumbing.
---

- Every exported identifier gets exactly one doc comment that starts with its name.
- In repositories that depend on `gutil`, use it for logging, JSON responses, and ETags. Use chi for routing and GORM with `AutoMigrate` for Postgres.
- Create repositories from the owner's `go-template` GitHub template rather than copying an older repository.
- Actions are disabled on the template itself. Confirm a new repository has them enabled with `gh api repos/<owner>/<repo>/actions/permissions`.
- Use the module path the owner's other repositories use. Libraries start at `v1.0.0`.
- Keep lint configuration in a committed `.golangci.yml`, never as `-E` flags in a workflow, so local runs and CI enforce the same set.
- golangci-lint caps output at 50 issues per linter. Pass `--max-issues-per-linter=0 --max-same-issues=0` for true counts.
- If golangci-lint refuses to load because it was built with an older Go than `go.mod`, rebuild it with the current toolchain at CI's version (`go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@<version>`). Never skip lint because of it.
- Measure coverage with the toolchain from `go.mod` (`GOTOOLCHAIN=go1.x.y`), since totals differ between Go versions.
- `.yamllint` disables `document-start` and `line-length` and sets `truthy: check-keys: false`.
- The yaml-json auto-format step uses `file_pattern: '. :!.github/workflows/*'`. A literal `*.json` makes `git add` exit 128 in a repository without JSON.
- Releases use goreleaser, tagged by `PaulHatch/semantic-version`. Wrap `major_pattern` and `minor_pattern` in `/ /` so scoped titles such as `feat(api):` count.
Expand Down
Loading