Skip to content

Skills

The last chapter taught OpenCode to spread work out — the built-in subagents and your own pushing noisy scans into isolated context and fanning audits across workers. This chapter teaches it something narrower and stickier: a procedure you run over and over, written down once so OpenCode runs it itself the moment the situation calls for it. It’s the next step up from rules. Rules are the standing facts about feedmill — timestamps are stored UTC, the dedupe key is canonical-URL-plus-title. A Skill is a routine — a named, multi-step thing the agent does, not just knows.

A Skill is a directory with a SKILL.md file in it. The frontmatter says when to use it; the body says what to do. OpenCode keeps every Skill’s name and description in view and exposes them through a built-in skill tool — when your request matches one, the agent calls that tool to pull in the full body and follows it, no procedure re-pasted. And this is where OpenCode’s openness shows up again: it doesn’t read skills only from its own .opencode/skills/ — it also reads the Claude Code (.claude/skills/) and Codex (.agents/skills/) paths, walking up from your cwd until it reaches the git worktree. A skill you wrote for another tool already works here, unchanged. Skills are documented on the OpenCode Skills page; this chapter walks the whole arc on one concrete procedure.

Those three are the project-scoped sources; OpenCode also picks up global skills from the home-directory equivalents — ~/.config/opencode/skills/, ~/.claude/skills/, and ~/.agents/skills/ — so a skill you keep machine-wide is available in every repo too. This chapter stays project-local, but it’s worth knowing the project dirs aren’t the only source.

You’re still living in feedmill. It pulls dozens of feeds — RSS, Atom, a couple of awkward JSON-feed variants — and the set keeps growing, because the whole point of a self-hosted aggregator is that you decide what goes in it. Every time you add one, you do the same dance:

  • sniff the format — fetch a sample of the feed and work out whether it’s RSS, Atom, or one of the JSON shapes, and where it tucks the fields that matter
  • write a parser adapter that maps that feed’s quirks onto feedmill’s internal item struct — the id, the title, the published timestamp, the link
  • register the adapter so the sync server actually reaches for it when it sees that source
  • add a fixture test — drop the sample in testdata/, assert the adapter produces the items you expect, so the next refactor can’t silently break this source

The steps never change; only the feed does. And so far you’ve walked OpenCode through all four by hand for each new source — “okay, this one’s an Atom feed, the timestamp is in <updated> not <published>, register it in the adapter map, and yes write the fixture test too.” That re-narrating is the waste. We’ll write the procedure down once, as a Skill, and let OpenCode recognize “this is a new feed source to onboard” and run the whole thing itself.

Across the next three lessons:

  • Package the add-a-feed procedure — the directory, the SKILL.md, the frontmatter and body — and build the onboard-a-feed routine end to end so OpenCode’s skill tool can fire it on recognition.
  • Reuse skills across tools — because OpenCode reads .claude/skills/ and .agents/skills/ directly, a skill folder authored for Claude Code or Codex already loads here. You’ll drop one in and watch it work without a rewrite, and see which frontmatter keys travel and which get ignored.
  • Control which agents can run a skill — the permission.skill setting, globally and per-agent, plus turning the skill tool off entirely for an agent. So your read-only plan agent can’t fire a skill that writes parser code.

By the end, onboarding a feed is something OpenCode owns. You stop narrating the field-mapping, the fixture test stops being a thing you can forget, and the same skill folder works whether you’re driving OpenCode, Claude Code, or Codex on this repo.

Start by packaging the add-a-feed procedure.