Comments in code
SkillDev toolsStop writing so many comments. Follow these suggestions instead!
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Comments in code skill
What this skill tells your AI
The instructions your AI receives, as published by ledgerhq/ledger-live in .agents/skills/comments/SKILL.md and read by ahel’s review.
🧀 Avoid comments
Comments are code smells because they go out-of-date, bloat context, and lead to confusion.
Don't reference existing comments in the codebase – follow these rules
- Avoid adding comments – always prefer good names (explainer variables, functions, tests)
- Use test names to describe behaviour – unit tests are living documentation
- Good code explains itself – don't add comments that duplicate what the code already conveys
💡 Treatments
When code isn't clear, make it clearer:
- Rename variables and functions to make comments unnecessary
- Extract variables and functions to improve readability
- Use assertions to explain behaviour
Use test names to explain non-obvious details
❌ Bad
it("diffs the current value against resolved when targeted", () => {
const { result } = renderHook(() => useJsonEditor(makeProps()));
act(() => result.current.setDiffTarget("resolved"));
// Current equals resolved → every line is unchanged.
expect(result.current.diffJson.every((l) => l.state === "none")).toBe(true);
});
✅ Good
it("resets the state of every line when the diff is resolved", () => {
const { result } = renderHook(() => useJsonEditor(makeProps()));
act(() => result.current.setDiffTarget("resolved"));
expect(result.current.diffJson.every((l) => l.state === "none")).toBe(true);
});
Let code speak for itself
❌ Bad
/* Whether the filter trigger should be displayed */
showFilter: boolean;
✅ Good
showFilter: boolean;
Replace comments with explainer variables
Move the comment into a variable name:
Before
// NB `app.trustchain` is an encrypted db path: while the app is password-locked it reads back
// as the ciphertext string. Importing it would regenerate member credentials and null the
// trustchain (LIVE-36130). IsUnlocked re-runs this thunk once the encryption key is set.
// `undefined` must still go through: that is the legitimate "nothing persisted" case.
if (typeof data === "string") return;
After
const dataIsEncrypted = typeof data === "string";
if (dataIsEncrypted) return;
☝️ When comments are necessary
Comments are only for vital information that can't go anywhere else. Always prefer not adding comments. If a comment is the only way, follow these guidelines:
- Be concise: Use as few words as possible to convey the necessary information.
- Use JSDocs: Only when describing a shared function.
- Prefer a link: If the comment is explaining a workaround for a known issue, link to the issue or docs.
❌ Bad
# pnpm patches add 'patch_hash=HASH' to virtual store paths, which prefab 2.1.0
# (introduced via AGP 8.11) misparses as an option flag due to a clikt bug that splits
# positional path arguments at '='. Pinning prefab to 2.0.0 in gradle.properties avoids
# this; keeping path segments ≤ 80 chars shortens virtual-store paths to reduce the
# likelihood of triggering prefab path-parsing issues as an additional safeguard.
android.prefab.version=2.0.0
virtual-store-dir-max-length=80
✅ Better
# Workaround for Prefab 2.1.0/Clikt bug
# See: https://github.com/google/prefab/issues/187
android.prefab.version=2.0.0
virtual-store-dir-max-length=80
Signals
- GitHub stars
- 618
- Forks
- 490
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
comments- Source
- github.com/ledgerhq/ledger-live