Introducing jonbaldie/skills

27th August, 2026


A few weeks ago, I ran out of Claude usage halfway through a change. The code was still sitting safely in the project, but much of the useful context was trapped inside the old conversation.

What was the agent trying to achieve? Which files mattered? What had it already ruled out? Starting again would mean repeating work I had already paid for.

That frustration eventually became one of the first workflows in jonbaldie/skills, my collection of practical skills for coding agents.

If you have not used agent skills before, the idea is simple. A skill is a reusable set of instructions that teaches a coding agent how to complete one particular job. It can include scripts and reference material as well as plain English guidance. Instead of explaining the same process in every new conversation, I can invoke a named skill and have the agent follow the whole workflow from beginning to end.

Continuing Interrupted Work

The first problem I wanted to solve was straightforward: how can a new coding-agent session continue the work of an old one without making me write a detailed handover?

resume-from-agent searches the session histories of supported coding agents, extracts a short brief, and checks it against the files and Git state in the live project. It then continues the work immediately. That last part matters. The transcript might claim that a file changed or a test failed, but the current project is always the source of truth.

Not every interruption happens inside a conversation. Sometimes the unfinished work is sitting in a draft pull request, alongside review comments, failing checks, and a branch left by an earlier agent or teammate. resume-from-pr gathers that context, checks out the actual work, and continues from the next useful action. The pull request becomes a practical handover instead of somewhere unfinished work goes to die.

Finishing the Work

Another problem I ran into was that coding agents sometimes stopped a little earlier than I expected. They would write the code, run a few tests, and tell me that the change was finished.

But what about the pull request? Had every check passed? Had it been merged into the right branch? Was the linked issue actually closed? These might sound like small details, but they are still part of finishing a real project.

I added three skills for the different ways this problem tends to appear:

  • For a whole specification, ship-spec works through its child issues one at a time. Each change gets its own branch, and must reach the target branch before the agent moves on.
  • For one finished branch, ship-pr creates or reuses its pull request, waits for the required checks, merges it, closes linked issues, and verifies the result.
  • For work from a fork, promote-fork-pr-upstream separates the intended changes from any fork-only history and turns them into one clean pull request for the upstream project.

They all follow the same basic principle: the work is not finished until it has reached the place it was supposed to go.

Proving That the Code Works

While working on my own GitHub projects, I became interested in a harder question: how can I tell whether agent-written code actually works?

A passing test suite is reassuring, but it can also create false confidence. Some tests only check values created by fixtures, mocks, or test helpers, without observing anything produced by the real system. Even good tests only cover the examples we thought to write. What happens to the cases we never considered?

The idea behind deintrovert-tests was inspired by unclebob/deintroverter4clj. An introverted test can pass without its assertion coming from the behaviour of the system it claims to test. For example, it might assert a literal value or some data created by its own fixture. The test is green, but it has not told us very much about the application.

deintrovert-tests applies that question across a test suite. It follows each asserted value backwards and checks whether it came from production code, the surrounding test machinery, or the test itself. It is not intended to become another automatic CI gate. Instead, it shows an engineer which tests deserve a closer look and where the evidence behind them stops.

That leaves the second problem: how do we find a bug that nobody thought to write a test for?

finding-bugs starts with a user-facing part of the project and asks what rules should always remain true. It then applies coverage-guided, property-based testing to generate and mutate inputs, run them through the real application, and explore paths that ordinary examples might miss. Depending on the project, it can also use static analysis, runtime checks, or generated sequences of user actions.

Finding a suspicious result is not enough. The skill must reproduce the failure, reduce it to the smallest useful example, and explain it in the language of the project. This matters because a bug report is only useful when another engineer can reliably see the same thing.

This approach has already paid off in my personal projects. Fuzzing MyREST found malformed filters, unusual text values, collisions in embedded result keys, and invalid Accept quality values that its existing tests had missed. I fixed them together in pull request 101, which came directly from those fuzz findings.

I used a similar approach while hardening my database project’s write-ahead log, the record used to rebuild stored data after a restart. Rejected statements could leave records that would return on replay, valid control bytes could be split apart, and primary-key updates could target the wrong row. Pull request 176 fixed those problems and added new regression tests and fuzz targets.

Finding Performance Problems

I have also been using coding agents to inspect the performance of my GitHub projects. In simple terms, this means finding parts of the code that take too long, use too much memory, or become dramatically slower as the amount of data grows.

That last problem is often described using Big-O notation. Big-O does not tell us exactly how many milliseconds some code will take. It describes how the amount of work grows as the input gets larger.

For example, imagine some code that checks every row in a database once. If the number of rows doubles, the work will roughly double too. That is known as linear, or O(n), growth. If the code compares every row with every other row, doubling the number of rows can quadruple the work. That is O(n²). The difference might be invisible with ten rows and rather more noticeable with ten million.

Measuring performance sounds straightforward: run the code before and after a change, then compare the numbers, right? Unfortunately, one fast result can be misleading. The test might use unrealistically small inputs, measure the wrong part of the application, or improve a situation that real users rarely encounter.

seeking-performance asks the agent to read the relevant code first and follow real user actions through it. It looks for loops, database queries, input and output, memory use, and work that gets repeated unnecessarily. It then ranks the most important problems and gathers repeatable measurements where possible. The skill produces a report before changing anything, which gives me a chance to review the evidence and choose what is worth improving.

There was a more dramatic example in Mutago, my mutation-testing tool for Go. Mutation testing deliberately changes small parts of a program and runs the tests to see whether they notice. One change might turn true into false, remove a statement, or alter a return value. If the tests still pass, Mutago has probably found something they do not properly check.

The important detail is that it does this many times. A project might produce hundreds or thousands of possible mutations, with tests running for each one. An unnecessary piece of work that costs one second is annoying when it happens once. When it happens once for every package or every mutation, that cost is multiplied across the whole run.

This is what made pull request 54 so effective. Mutago was fully loading the code of every dependency when it only needed that detail for the project being tested. Once that work was removed, the median time for a full-project dry run fell from 8.94 seconds to 2.18 seconds. In the time it previously took to run once, it could now run just over four times. That became release v2.8.6.

Two nearby changes removed work that was repeated even more often. Pull request 52 reused a test run that Mutago had already performed instead of running it again for every package. Pull request 45 stopped it from running the tests for mutations on lines that the tests never reached. Those became v2.8.5 and v2.8.3.

Taken together, these changes remove wasted work at several levels of the same process. The project loads faster, each package avoids an extra test run, and uncovered mutations never start their tests at all. As the number of dependencies, packages, and possible mutations grows, those savings are repeated across the whole run. That is where the multiplicative speed-up comes from.

Why Use Skills?

Why did I put these workflows into skills instead of simply asking an agent to do the work each time?

At first, that is exactly what I did. I explained how I wanted a pull request handled, which checks should run, and what I considered finished. For another task, I explained how I wanted performance measured or a test suite inspected.

I soon found myself repeating the same instructions. I would also occasionally leave out an important detail. The agent might stop after creating a pull request, compare an old transcript without checking the current files, or report a performance improvement without enough evidence behind it.

A skill gives me somewhere to keep those instructions. When using one on a real project exposes a missing step, I can update it. The next time I use the skill, I do not have to remember that lesson all over again.

Trying the Skills

The collection is available at github.com/jonbaldie/skills. The installer supports Codex, Claude Code, OpenCode, Pi, and Cursor. You can install the skills for one project or make them available globally.

Some of the workflows build on skills from mattpocock/skills. The installer can add those prerequisites at the same time. If you would rather not run the installation commands yourself, the README also includes a short instruction that you can paste into your coding agent.

I expect the collection to keep changing as I use it. Each skill began with a problem I encountered while working on a real project. When another project exposes something the workflow does not handle properly, I will change it again.


Please check out The 24 Laws of Storytelling, my book that explores the principles that make some books and movies great and explains why others fail. By reading my book, you’ll gain the same strategies used by master storytellers such as Stephen King, Christopher Nolan, Fyodor Dostoyevsky, and many more. Pick up your copy today.