Agent skill
LC Add
solved → filed
Solving the problem is the interesting half. The other half is filing it: the real
slug off the problem page, the layout every neighbouring file already uses, a smoke
test against the docstring's own examples, and a README row that lines up with the
table it was inserted into. /lc-add does that half, in one pass, the
same way every time.
1 slug weekly_517/ws.txt โ count-integers-appearing-in-a-single-block
the method is countSpecialIntegers. That is not the slug.
2 neighbour read Hash_table/count-special-triplets.py, matched its shape
3 write leetcode_python/Hash_table/count-integers-โฆ-single-block.py
V0 ยท IDEA : HASH MAP {val : [idx_1, idx_2, ...]}
time = O(n), space = O(n)
4 variant + V0-1, keeps only (first, last, cnt) โ O(distinct) space
5 test [1,1,2,2,3]โ3 [1,2,1]โ1 [5]โ1 []โ0 V0 and V0-1 agree
6 readme row inserted after LC 4007 โ README.md:494
7 assumed Easy, inferred from its position in weekly 517. Correct me.
A real run, in the order it always happens: find the slug, copy a neighbour, write, test, file, then say what was guessed.
Why a skill and not a habit
Three ways filing a solution goes wrong
None of these are hypothetical โ each one has actually landed in this repo, and each one is invisible in a diff. They are why the recipe is written down once instead of remembered differently every time.
LC 4038's method is countSpecialIntegers. Its problem is Count Integers Appearing in a Single Block. A file named after the method is a file nobody finds.
Cost: a wrong file name and a dead README link.
Every file in a pattern directory has the same shape โ docstring, V0, IDEA, complexity, class. A file that invents its own is the one that breaks a later sweep over the tree.
Fix: read a neighbour before writing.
The file name has dashes, so it is not importable โ which makes it just slightly too annoying to test, which is how untested code gets committed and a README row lands with the wrong columns.
Rule: untested is unfinished.
One pass, no branches
Seven steps, in order
The steps never reorder and none of them is optional. Pick one to see what it does and the rule that step exists to enforce.
What lands in the tree
The house layout
Two artefacts, every time: one Python file and one README row. Both are shown here as they were actually written for LC 4038 โ the run the skill's own worked example describes.
""" <- docstring first, before any import
4038. Count Integers Appearing in a Single Block
Easy <- number, exact title, difficulty
An integer x is called special if all occurrences of x in nums
appear in a single contiguous block.
Example 1:
Input: nums = [1,1,2,2,3]
Output: 3
...
"""
# V0 <- the canonical solution
# IDEA : HASH MAP {val : [idx_1, idx_2, ....]}
#
# collect every index a value lands on, then a value is special
# ONLY if its indices are consecutive.
#
# the cheap way to test "consecutive" is NOT to walk the list, but
# to compare the span against the count:
#
# last_idx - first_idx + 1 == number_of_occurrences
#
# e.g. nums = [1,2,1] -> idx of 1 = [0,2] -> 2 - 0 + 1 = 3 != 2
#
# time = O(n), space = O(n) <- last comment before the code
from collections import defaultdict
class Solution(object): <- Python 2 style, like the whole tree
def countSpecialIntegers(self, nums):
"""
:type nums: List[int] <- kept: these get pasted back into LC
:rtype: int
"""
# edge
if not nums:
return 0
my_map = defaultdict(list)
for i in range(len(nums)):
my_map[nums[i]].append(i)
cnt = 0
for k in my_map:
indices = my_map[k]
# NOTE !!! span == count <=> indices are consecutive
if indices[-1] - indices[0] + 1 == len(indices):
cnt += 1
return cnt
# NOTE !!! marks the one line a reader would get wrong. Once per file โ
five of them mark nothing.
Inserted into the pattern's own table, in ascending LC-number order:
| 4038 | [Count Integers Appearing in a Single Block](https://leetcode.com/problems/count-integers-appearing-in-a-single-block/) | [Python](./leetcode_python/Hash_table/count-integers-appearing-in-a-single-block.py) | _O(n)_ | _O(n)_ | Easy | **hash table**, hashmap, `span == cnt` trick, first/last idx, LC weekly | AGAIN(1) |
| Column | Where it comes from |
|---|---|
| Title | The problem page โ never the method name. |
| Python / Java | The file just written. A Java link joins the same cell only if that file exists โ checked, not assumed. |
| O(t) / O(s) | The time = / space = line on V0, so the row and the file cannot disagree. |
| Tags | Pattern in bold first, then the trick worth grepping for later, then LC weekly, then company tags in backticks if known. |
| Status | AGAIN(1) on a first pass. A status you have already set is never downgraded. |
The same problem earned a second block, because it is a genuinely different space bound โ not a different spelling of the same loop:
# V0-1
# IDEA : ONE PASS, KEEP ONLY (first_idx, last_idx, count)
#
# same "span == count" check as V0, but there is no need to KEEP
# every index : first, last and the count are all the check reads
#
# -> still O(n) space, but O(distinct) instead of O(n) list cells
#
# time = O(n), space = O(k), k = number of distinct values
class Solution2(object): <- so the file still imports
def countSpecialIntegers(self, nums):
info = {}
for i, v in enumerate(nums):
if v not in info:
info[v] = [i, i, 1]
else:
info[v][1] = i
info[v][2] += 1
return sum(1 for first, last, cnt in info.values()
if last - first + 1 == cnt)
Both variants get the same smoke test and the results have to agree. A variant that
disagrees with V0 is a bug found before the commit rather than after.
Arguments are inferred, not interrogated
How to call it
The slash form and plain English do the same thing. Paste a draft under the command
and it becomes V0; leave it out and the draft is usually already in the
contest scratch file, which is step 1's job to find.
/lc-add 4038 Hash_table # + paste your draft under it
/lc-add 239 Sliding_Window
add LC 4038 to leetcode_python/Hash_table/
file yesterday's contest Q1
add this solution and update the README
| Left out | What happens |
|---|---|
| Pattern dir | Inferred from the technique the solution actually uses โ not from the problem's LeetCode tags. |
| Language | Taken from wherever the draft came from. Python by default. |
| Difficulty | Read off the problem page, or inferred from the contest position (Q1 Easy, then Medium, Medium/Hard, Hard) โ and flagged as an inference in the report. |
| LC number | The one thing it will ask for. Everything else keys off it. |
End to end
A worked run
/lc-add 4038 Hash_table with a draft pasted under it โ the run the hero
terminal is showing, step by step and with what each one actually produced.
| Step | What it produced |
|---|---|
| 1 slug | weekly_517/ws.txt → count-integers-appearing-in-a-single-block; first of 4038/4039/4040/4041, so Easy |
| 2 neighbour | read count-special-triplets.py from the same directory |
| 3 write | wrote the file; the IDEA explains why last - first + 1 == count is the contiguity test |
| 4 variant | added V0-1 keeping only first/last/cnt โ justified: O(distinct) space, not O(n) cells |
| 5 test | [1,1,2,2,3]→3, [1,2,1]→1, [5]→1, [1,2,1,3,3,2]→1, []→0 โ both variants agreeing |
| 6 readme | row inserted after LC 4007, the last row of the hash-table table |
| 7 report | flagged: difficulty inferred from contest position, examples written from the rule |
The file it produced is in the tree: count-integers-appearing-in-a-single-block.py.
The guardrails
What it will not do
A filing tool that quietly does more than filing is one you have to review line by line, which defeats the point of having it.
- Rewrite your approach into its own.A pasted draft gets its bugs fixed and keeps its idea. The bug you hit is the thing worth seeing fixed.
- Hand back untested code.The docstring's own examples plus the edges run before anything is reported done.
- Touch
data/progress.txt.The practice log is your own record and gets its own commit โ it is also the single source for the review plan, so nothing else writes to it. - Downgrade a status you set.
AGAIN(1)is for a first pass. AnOKyou earned staysOK. - Commit or push unless asked.It writes files and stops. The commit is yours to shape.
One markdown file, no dependencies
Install
SKILL.md is the whole recipe โ nothing to build and no network calls, so
the same source runs on any agent that takes a system prompt. Pick yours.
Drop the skill directory into your user-level skills folder and it loads in every repo:
git clone --depth 1 https://github.com/yennanliu/CS_basics.git /tmp/cs_basics
mkdir -p ~/.claude/skills
cp -r /tmp/cs_basics/.claude/skills/lc-add ~/.claude/skills/
Already installed inside this repo at .claude/skills/lc-add/, so a clone
of CS_basics needs no setup at all. Claude Code matches it on the description, or you
can call /lc-add by name โ the directory name is the command.
Zip the directory, then Customize → Skills → + → + Create skill → Upload a skill:
cd .claude/skills && zip -r lc-add.zip lc-add
Leave the YAML frontmatter in SKILL.md intact. description is
what Claude matches your request against when deciding to load the skill on its own;
name is the display label, and the directory name is what supplies the
slash command.
Codex reads AGENTS.md at the repo root automatically. Point it at the skill:
## Filing a LeetCode solution
When asked to add an LC problem to the repo, to file a problem just
solved, or to wire an existing solution file into README, follow
`.claude/skills/lc-add/SKILL.md`.
A pointer, not a copy โ one source of truth means a fix reaches every agent at once.
Same shape in GEMINI.md, or point at it for a single session:
gemini -p "Follow the recipe in .claude/skills/lc-add/SKILL.md. \
File LC 4038 into leetcode_python/Hash_table/ โ draft in @draft.py"
Paste SKILL.md in as the system prompt. It is self-contained and has no
references/ to carry. For Cursor or Windsurf, put the Codex pointer above
into a rule file (.cursor/rules/lc-add.mdc or the editor's equivalent).
curl -sL https://raw.githubusercontent.com/yennanliu/CS_basics/master/.claude/skills/lc-add/SKILL.md
One caveat away from this repo: steps 2 and 6 read a neighbouring solution file and an
existing README table. Point it at whatever plays those roles in your own tree, or it
falls back to the layout documented in SKILL.md.
Under the hood
What is inside
One file. The steps live there and nowhere else โ this page describes them, but
SKILL.md is what actually runs, so the two cannot drift into two recipes.
- SKILL.md The whole recipe โ the five prime directives, the seven steps with their commands, the file layout, the README row shape, the do-not list, and the LC 4038 worked example.
Gated in CI by check_skills.py โ frontmatter every host can parse, the directory name pinned to the command name, and whether the links on this page still resolve.
The rest of the loop
Where it fits
/lc-add is the step right after you solve something โ it turns a scratch
draft into a file the rest of the site can see. From there the
explorer indexes it, the
review plan schedules it once you log the attempt,
suggest review decides when it is owed another look,
and LC Coach is the one to ask whether the solution you just
filed would actually have passed.