Writing an agent skill
Source: Dev.to
The DRY principle
The DRY (Don’t Repeat Yourself) principle has been around for ages.
If you copy‑and‑paste code in multiple places and a bug appears, you’ll have to fix the bug everywhere. The more duplications you have, the higher the chance you’ll miss one when fixing.
DRY in the context of coding assistants
When using a coding assistant, DRY means something different:
- You don’t need to ask the assistant to analyze your project on every session.
- You don’t have to repeat your language’s coding conventions each time.
- You don’t need to remind the assistant that your project favors immutability.
When a new developer joins a good project, they are told the project’s features, architecture, and conventions. In great projects, those conventions are formalized in written form and sometimes kept up‑to‑date. Your coding assistant is a team member like any other: it requires written documentation.
Both coding assistants I use allow the use of such instructions (I assume all do). For example, GitHub Copilot automatically reads the .github/instructions.md file.
Keeping instruction files small
If the assistant reads the instructions automatically and they are too broad, you’ll pollute the context with irrelevant data.
Conclusion: keep the file relatively small and focus on general information.
Sizing advice
| Source | Recommendation |
|---|---|
docs.factory.ai | 700 lines is too long |
My advice: start small, increment when needed, analyze results, and refactor when the file grows too large.
Tokens are the real resource
Today, the critical resources aren’t CPU, RAM, or storage, but tokens. Tokens are finite and expensive. I predict developers will soon be measured on token usage: the better developer will be the one who uses the fewest tokens to achieve similar results.
Most agents load a default instructions file:
- GitHub Copilot →
AGENTS.md - Claude →
CLAUDE.md
The smaller the file, the fewer tokens are spent in the context.
A good context contains all the necessary tokens, but not more—that’s where skills come into play.
Agent Skills
Agent Skills are folders of instructions, scripts, and resources that agents can discover and use to work more accurately and efficiently.
Skills differ from AGENTS.md in that they aren’t loaded automatically, so they don’t bloat the context. Depending on the coding assistant, a skill may be discovered and loaded automatically, or not.
Invoking a skill
- By default, both you and Claude can invoke any skill.
- Type
/skill-nameto invoke it directly. - Claude can load a skill automatically when it’s relevant to the conversation.
How Claude knows when to invoke a skill
Claude transforms the front‑matter of every SKILL.md file into a tool definition. Below is the front‑matter of the Kotlin skill I created:
---
name: kotlin
description: |
Use this skill when working with Kotlin code in any capacity:
- Reading, writing, editing, or reviewing Kotlin files (*.kt, *.kts)
- Running Gradle tasks for Kotlin modules
- Writing or debugging Kotlin/JS code that targets Node.js
- Working with external JavaScript libraries from Kotlin
- Writing tests for Kotlin code (@Test, @BeforeTest, @AfterTest)
- Setting up dependency injection or mocking in Kotlin
- Dealing with multiplatform Kotlin projects (common, jsMain, jsTest, jvmMain)
- Troubleshooting Kotlin compilation or runtime errors
- Any task involving Kotlin/JS modules targeting Node.js
This skill provides Kotlin/JS technical knowledge (especially JS interop gotchas)
and coding‑style preferences beyond the official conventions.
---
The above gives Claude the information it needs to decide when to load the tool. Obviously, the skill is about Kotlin and Kotlin/JS.
Content of a skill
Follow the same rules as regular AGENTS.md files:
- You can reference other documents (textual or otherwise) that are local to the skill folder or accessible online.
- I have copied the entire Kotlin coding conventions into a dedicated file.
SKILL.mdsummarizes the main items and links to the conventions. - The full conventions are cached locally in this skill directory at
kotlin-coding-conventions.md.
Key reminders (Kotlin)
- Prefer
valovervar– immutability first - Use immutable collection interfaces (
List,Set,Map, notMutableList, etc.) - Use
itfor short lambdas; use named parameters for nested/complex ones - Prefer expression forms of
if,when,tryover statement forms - Prefer functional style (
filter,map) over imperative loops
1. External Interfaces vs. Kotlin Classes
Problem: Kotlin classes have methods on their prototype. External interfaces expect methods directly on the object. You cannot use unsafeCast to convert between them.
// ❌ WRONG: This will fail at runtime
class MockSql {
fun unsafe(query: String) = /* … */
}
val sql: Sql = mockSql.unsafeCast() // Throws: sql.unsafe is not a function
// ✅ CORRECT: Use an extension function to build a plain JS object
fun MockSql.toExternal(): Sql {
val obj = Any().asDynamic()
val mock = this
obj.unsafe = { query: String -> mock.unsafe(query) }
obj.end = { mock.end() }
return obj.unsafeCast()
}
// Then use it:
val sql: Sql = mockSql.toExternal()
Bottom line
Skills are great for avoiding the repetition of the same instructions over and over. The main difference between skills and instructions is that skills don’t bloat the context when they’re not needed. Use them wisely, keep your instruction files small, and watch your token usage shrink.
To go further
Agent Skills
- Extend Claude with skills
- Methodical Development Skill
- Awesome Skills
Originally published at A Java Geek on March 15th, 2026.