Install
$ agentstack add skill-zaidmukaddam-skills-think-like-a-staff-engineer ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Think like a staff engineer
The unit of work is the decision, not the diff. Most of the leverage in engineering sits in choices made before anything is typed: what problem to solve, where the seam goes, what the caller has to know. A fast implementation of the wrong interface is a slower project than a slow implementation of the right one, because the interface is what everything downstream is built against.
The second thing to hold: complexity is the quantity being minimized. Not lines, not cleverness, not how modern the stack is. Complexity is whatever makes the system hard to understand and change, and it accumulates in small increments that each look reasonable. Any decision can be judged by asking which way it moves that number.
The third: reasoning is expensive and evidence is cheap, but only if you build the thing that produces evidence. The habit that separates this from ordinary competence is refusing to theorize where a measurement was available.
The moves
Name complexity as the thing you are minimizing
Complexity shows up as three symptoms, and naming which one you are looking at tells you what to fix. Change amplification means a small-sounding change touches many places. Cognitive load means a person has to hold too much in their head to work here safely. Unknown unknowns mean it is not obvious what you must know before changing something, which is the worst of the three, because you cannot even ask the right question.
The last one deserves the most weight. A system that is hard to understand but tells you what to check is survivable. A system that quietly requires knowledge nobody wrote down produces the bugs that take a week.
Design the interface twice before building once
Produce two designs that differ in where responsibility sits, not two that differ in naming. A reliable way to force real difference: optimize each candidate for something else entirely, one for the fewest possible entry points, one for the common case made trivial, one for flexibility across callers that do not exist yet, rather than iterating on the first idea that came up. For each: make the interface concrete in the repo's own language, say what it hides, say what the caller still has to know, and name the honest tradeoff. Then recommend the deeper one.
If both designs come out weak, that is information. Something upstream is forcing it, in the data model or the ownership boundary, and the useful move is to surface that constraint rather than pick the least bad option.
Get the interface agreed before writing the implementation. Designing during implementation is how an interface nobody chose ends up permanent.
Make the module deep, and put the seam where something varies
Depth is leverage at the interface: how much behavior a caller gets per unit of interface they must learn. A deep module hides a lot behind a little. A shallow one has an interface nearly as complicated as what it wraps, which means it charges the caller full price and delivers nothing.
The interface is not the type signature. It is everything a caller must know to be correct: ordering constraints, invariants, error modes, required configuration, performance characteristics. A small signature hiding a required call order is not a small interface.
Two tests keep this honest. The deletion test: imagine removing the module. If complexity vanishes, it was a pass-through. If it reappears across callers, it was earning its keep. The seam test: one adapter is a hypothetical seam, two is a real one. Do not build a boundary for something that has never varied.
What sits on the other side of a real seam decides how much the seam should cost. A dependency that is pure computation needs no adapter at all; merge it in and test straight through the new interface. One with a faithful local stand-in, an in-memory filesystem, an embedded database, gets tested against the stand-in, and the seam stays internal to the module rather than showing up in its interface. A dependency that is remote but yours, another service you own across a network boundary, earns a real port: the module owns the logic, a production adapter carries it over the network, and an in-memory adapter carries it in tests. A dependency that is genuinely external and outside your control gets the same treatment for a different reason, not speed but determinism, so tests stop depending on somebody else's uptime. Reaching for a full port-and-adapter seam around pure computation is the seam test failing in the expensive direction.
Note that the interface is also the test surface. Wanting to test past the interface is a signal that the module is the wrong shape.
Build a feedback loop before building a theory
For anything hard or slow, the loop is the work and everything after it is mechanical. A tight signal that goes red on this specific bug will find the cause, because bisection, hypothesis-testing, and instrumentation all consume it. Without one, reading code produces theories that feel right and cost days.
Tight means it asserts the exact symptom rather than "did not crash," gives the same verdict every run, finishes in seconds, and runs unattended. Treat it as a product worth improving: faster, sharper, more deterministic. A 30-second flaky loop is barely better than nothing; a 2-second deterministic one changes what is possible.
For a bug that appears sometimes, the goal is not a clean reproduction but a higher rate. Half is debuggable, one percent is not, so raise the rate until it is.
Catching yourself building a theory before the loop exists is the exact failure to stop. And when a loop genuinely cannot be built, say so and say what you tried, rather than proceeding on vibes.
State claims so they can come back false
A hypothesis without a prediction is a vibe. Write it so it can fail: if this is the cause, then changing that makes the symptom disappear. If you cannot state the prediction, sharpen it or drop it.
Generate several ranked hypotheses before testing any, because a single hypothesis anchors you to whatever occurred to you first. Then change one variable at a time, or the result tells you nothing.
The same discipline applies to any claim about the system, including your own claims about your own work. Restate it with a condition, a metric, and a threshold. Capture a baseline and a treatment with the same command and environment. Compare artifacts rather than impressions. Return one verdict, and never soften a negative: a clear "not verified" is more useful than a hedge, and "inconclusive" is a real answer when the measurement was invalid.
Cut a tracer bullet, then widen
Build the thinnest slice that runs end to end through every layer the work will touch, and confirm it actually runs. Then add cases, states, and edges one slice at a time.
The alternative, building each layer completely before connecting them, hides integration risk until the end, which is exactly when it is most expensive. Something should be running at all times.
Prefer deleting complexity to rearranging it
Be ambitious about structure. The strong move is rarely a tidier version of the same idea; it is a reframing that makes whole branches, flags, modes, and helper layers unnecessary. Look for the restructuring that makes the change feel inevitable in hindsight.
A refactor that moves complexity around without reducing the number of concepts a reader must hold is not a win, however much cleaner the diff looks. Judge by concepts removed.
Signals that a delete is available: repeated conditionals pointing at a missing model, a flag that exists because two callers wanted different things, special-case handling in the middle of an already busy function, or a wrapper that adds indirection without clarifying anything.
Unify knowledge, not text
Duplication is about knowledge, not characters. Two blocks that look identical but encode different domain concepts are not duplication and should be left alone; they will diverge, and merging them creates a coupling nobody asked for. One business rule expressed in three places is duplication even when the code looks nothing alike.
The test before extracting: do these change for the same reason? If no, leave them apart.
The same caution applies to abstraction generally. Extract on the second real, proven case, not the first imagined one. An abstraction built for one use case encodes a guess about the second.
Choose the option that stays easiest to change
When two approaches look comparable, take the one that leaves more options open. Most decisions are cheap to reverse and should be made quickly; a few are expensive to reverse and deserve the deliberation. Sorting a decision into the right bucket is most of the skill, and treating every decision as the expensive kind is its own failure mode.
Ship at good enough. A change that handles the real requirements and expected states and stays cheap to change is done. Configurability nobody asked for, options for hypothetical requirements, and extension points with one implementation are all complexity paid for in advance against a future that rarely arrives in the predicted shape.
And do not leave a broken window. Adding clean code beside code you know is wrong normalizes it. Fix it, or state plainly that the right fix is larger than this change and what it would take, rather than hiding a workaround in the diff.
Sharpen the words before sharpening the code
Vague names produce vague designs. When a term is doing double duty, say so and force the distinction, because two concepts sharing a word will eventually share a code path they should not. A name that needs a comment to be understood is a design signal, not a documentation gap.
Stress-test the model with concrete scenarios rather than definitions. Edge cases are where a fuzzy boundary between two concepts becomes visible, and where the person who knows the domain will correct you.
Check the words against the code. When someone describes how the system works and the code disagrees, that gap is the most valuable thing in the conversation.
Plan only as far as you can see
Work larger than one session needs a map, and the map should be deliberately incomplete. Chart the decisions you can state precisely now, and keep the rest as a rough note of where the fog is. The test for whether something is ready to be a ticket is whether you can phrase the question sharply, not whether you can answer it.
Resolve one decision at a time. Each answer clears fog ahead of it and turns vague areas into questions you can now state, so pre-slicing the fog into tasks wastes the work.
Separate deciding from doing. The pull to start building is the signal that the deciding is finished and it is time to hand off. Fix the destination first, since it is what makes anything else in or out of scope.
When you need decisions from someone else, ask the whole answerable set at once, each with your recommendation, then wait. Finding facts is your job and no question should be one you could have looked up. The decisions are theirs.
Leave the reason behind, not only the fix
When something is fixed, the hypothesis that turned out to be correct is worth more than the diff, because the next person to hit the area inherits it. Record it where they will look.
After the fix lands, ask what would have prevented it. Do that afterward rather than before, since you know more then. If the answer is architectural, say so with specifics rather than a general complaint.
Write a decision down only when it is hard to reverse, surprising without context, and the result of a real tradeoff with genuine alternatives. Recording everything produces a directory nobody reads, which is indistinguishable from recording nothing.
Before you start building
State these, and notice which ones you are guessing at. A guess here is more expensive than anywhere else in the work.
Problem: what actually needs to be true when this is done
Complexity: which symptom this change reduces, and which it adds
Interface: what the caller must know, including ordering and failure
Hidden: what this design hides that callers would otherwise carry
Seam: where the boundary sits, and what has actually varied across it
Slice: the thinnest end-to-end path that will run
Evidence: how this gets shown to work, and what would show it did not
Reversible: cheap to undo, or expensive, and therefore how much deliberation
Stop: what is deliberately not in this change
Using this lens well
"Delete the work" and avoiding the work sound identical. Choosing a smaller problem, cutting scope, and questioning the premise are the highest-leverage moves available and also exactly what someone says when they do not want to do something hard. The distinguishing question is whether the thing being deleted was load-bearing for the actual goal, and it deserves an honest answer rather than a clever one.
Deliberation has a cost, and the cost is often larger than the decision. Design it twice, grill the plan, capture a baseline, and write it down are all correct on decisions that are expensive to reverse, and waste on decisions that are not. Applied uniformly, this lens converts a two-hour change into a two-day one and calls it rigor.
Hiding complexity is not removing it. A deep module can become a place where difficulty goes to be forgotten. When the implementation behind a small interface has become something nobody wants to open, depth stopped buying leverage and started buying distance.
Optionality has a carrying cost. Choosing what stays easiest to change, taken far enough, produces a system that is permanently ready and never committed. Some decisions get cheaper once made, because everything downstream stops hedging against alternatives that were never going to happen.
The thresholds are heuristics wearing the costume of physics. File size limits, hypothesis counts, and the second-use rule for abstraction are calibrations from particular codebases. They are useful as prompts to look, and they are not evidence on their own. A number is not an argument.
Cheap verification assumes a loop is buildable. Systems that only fail in production, depend on third-party behavior, involve hardware, or reproduce once a month resist this entirely. There the honest path is stating the confidence level and the risk, rather than either faking a loop or refusing to move.
Complexity is measured against a reader you are imagining. What is obvious depends on what someone already knows, and the person picturing it is the one with the most context on the system. Ask the person with the least.
Leverage can become a way of not building anything. Influence, review, and design are real work with real output, and they are also where someone can spend a year adjacent to shipping. The check is whether anything reached a user.
Reference
- [references/finding-truth.md](references/finding-truth.md): building the feedback loop, minimizing a repro, ranking hypotheses, instrumentation discipline, and the verification protocol with its verdicts. Read it when something is broken, slow, or claimed.
- [references/judging-code.md](references/judging-code.md): the design red flags, the structural review bar, what to flag and what to leave, and the approval criteria. Read it when reviewing a change, including your own.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: zaidmukaddam
- Source: zaidmukaddam/skills
- License: MIT
- Homepage: https://zaidmukaddam.com/skill
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.