Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
"$schema": "https://anthropic.com/claude-code/marketplace.schema.json",
"name": "adhd",
"description": "ADHD-friendly answers, tweet-sized. Short, straightforward, every character counts.",
"description": "ADHD-friendly answers, tweet-sized. Fixes verbose output: short, concise, every character counts.",
"owner": {
"name": "Kisu"
},
"plugins": [
{
"name": "adhd",
"description": "Tweet-sized, ADHD-friendly answers for Claude Code: action first, numbered steps, no filler.",
"description": "Tweet-sized, ADHD-friendly output style for Claude Code: turns verbose answers into short ones — action first, numbered steps, no filler.",
"source": "./",
"category": "productivity"
}
Expand Down
4 changes: 3 additions & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{
"name": "adhd",
"description": "ADHD-friendly answers, tweet-sized: action first, numbered steps, one topic per answer, state restated every turn, no filler."
"description": "Turns verbose answers into tweet-sized ones. ADHD-friendly output style: short, concise answers — action first, numbered steps, one topic per answer, state restated every turn, no filler.",
"repository": "https://github.com/jjdmev2/adhd",
"homepage": "https://github.com/jjdmev2/adhd"
}
29 changes: 29 additions & 0 deletions .github/ISSUE_TEMPLATE/rule-broken.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: The skill broke a rule
description: An answer didn't follow one of the 10 rules
labels: [rule-broken]
body:
- type: input
id: rule
attributes:
label: Which rule broke? (1–10)
placeholder: "10 — it opened with 'Great question!'"
validations:
required: true
- type: textarea
id: prompt
attributes:
label: The prompt you sent
validations:
required: true
- type: textarea
id: got
attributes:
label: The answer you got
validations:
required: true
- type: textarea
id: wanted
attributes:
label: The answer you wanted
validations:
required: false
14 changes: 14 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: CI
on:
push:
branches: [main]
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: node --test
72 changes: 65 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,36 +10,58 @@ This skill makes every Claude Code answer read like a tweet on X: action first,

## English

Real outputs. Same prompt — *"My Node app crashes on startup with 'Error: Missing API_KEY'. What's going on?"* — same model, skill off vs on:

<table>
<tr>
<td width="50%">

**Before**
**Before — 1,379 chars, ~60s read**

> Great question! Let me think about this. Looking at your setup, the application fails on startup because the settings file is missing a required value, specifically the API key, which the client library needs before it can initialize. One approach would be to add it to your environment file. Hope this helps!
> That error means your code reads `process.env.API_KEY` (or similar) at startup and throws when it's `undefined` — the environment variable isn't set wherever you're running the app.
>
> Common causes and fixes:
>
> 1. **No `.env` file / not loaded** — if you're using a package like `dotenv`, make sure a `.env` file exists in your project root…
>
> *…and three more numbered causes.*

</td>
<td width="50%">

**After**
**After — 292 chars, ~12s read**

> Missing `API_KEY` in `.env`. Add it, restart.
> `API_KEY` env var isn't set. Fix:
>
> 🧵 next: `.env` isn't in `.gitignore`. Fix that too?
> 1. Find where it's read: `grep -rn API_KEY --include=*.js .`
> 2. Add it to `.env` (or your shell env): `API_KEY=your_key_here`
> 3. If using `.env`, confirm `dotenv` (or similar) is loaded before that check runs
>
> Want me to grep your repo for where it's read?

</td>
</tr>
</table>

### Install — 30 seconds

Any agent (Claude Code, Cursor, Codex, Cline, Windsurf, ~50 more):

```bash
npx skills add jjdmev2/adhd
```

Or as a Claude Code plugin — adds the `/adhd` command and an on/off switch:

```bash
git clone https://github.com/jjdmev2/adhd ./adhd
claude plugin marketplace add ./adhd
claude plugin install adhd@adhd
```

Then type `/adhd` in Claude Code. Done.
Pick one path, not both. Claude.ai web: **Settings → Capabilities → Skills** → upload [`skills/adhd/SKILL.md`](./skills/adhd/SKILL.md).

Wary of prompt plugins? This one is a single markdown file — read [SKILL.md](./skills/adhd/SKILL.md) before installing. No code, no dependencies.

### The rules

Expand All @@ -51,27 +73,54 @@ Then type `/adhd` in Claude Code. Done.

Five more (drama-free errors, real time estimates, no "Hope this helps!") in [SKILL.md](./skills/adhd/SKILL.md).

### Why not just tell it "be brief"?

| | |
|---|---|
| "Be brief" in a prompt | Decays — three turns later the paragraphs are back. |
| A concise output mode | Shortens the same structure. |
| adhd | Restructures: action first, numbered steps, state every turn. |

Concise mode shortens the answer. adhd rebuilds it for a brain that reads timelines, not documents.

### Off / update / tune

- Off: `claude plugin disable adhd`
- Update: `cd ./adhd && git pull`
- Tune: edit [SKILL.md](./skills/adhd/SKILL.md), re-run `/adhd`

Turn it off for: deep-dive learning, postmortems, anything where you want every caveat.
Test: if you'd *read* the five paragraphs, disable it. If you'd skim them, keep it on.

Got a real before/after? [Post it](https://github.com/jjdmev2/adhd/issues) — best pairs get quoted above, credited.

---

## Español

Tu IA escribe cinco párrafos. Tú lees cero. Este skill hace que cada respuesta se lea como un tweet en X: acción primero, cada carácter cuenta.

Salida real (tabla arriba): misma pregunta, mismo modelo — 1.379 caracteres sin el skill, 292 con él.

### Instalar — 30 segundos

Cualquier agente (Claude Code, Cursor, Codex, Cline, Windsurf, ~50 más):

```bash
npx skills add jjdmev2/adhd
```

O como plugin de Claude Code — agrega el comando `/adhd` y un interruptor de encendido/apagado:

```bash
git clone https://github.com/jjdmev2/adhd ./adhd
claude plugin marketplace add ./adhd
claude plugin install adhd@adhd
```

Escribe `/adhd` en Claude Code. Listo.
Elige un camino, no ambos. Claude.ai web: **Settings → Capabilities → Skills** → sube [`skills/adhd/SKILL.md`](./skills/adhd/SKILL.md).

¿Desconfías de los plugins de prompts? Este es un solo archivo markdown — lee [SKILL.md](./skills/adhd/SKILL.md) antes de instalar. Sin código, sin dependencias.

### Las reglas

Expand All @@ -83,12 +132,21 @@ Escribe `/adhd` en Claude Code. Listo.

Cinco más en [SKILL.md](./skills/adhd/SKILL.md) (en inglés — el skill le habla al modelo).

### ¿Por qué no basta con "sé breve"?

"Sé breve" en un prompt decae: tres turnos después vuelven los párrafos. Un modo conciso acorta la misma estructura. adhd la reconstruye: acción primero, pasos numerados, estado en cada turno.

### Apagar / actualizar / ajustar

- Apagar: `claude plugin disable adhd`
- Actualizar: `cd ./adhd && git pull`
- Ajustar: edita [SKILL.md](./skills/adhd/SKILL.md), vuelve a correr `/adhd`

Apágalo para: aprendizaje a fondo, postmortems, cualquier cosa donde quieras cada detalle.
Prueba: si *leerías* los cinco párrafos, apágalo. Si los saltearías, déjalo encendido.

¿Tienes un antes/después real? [Publícalo](https://github.com/jjdmev2/adhd/issues) — los mejores se citan arriba, con crédito.

---

Inspired by [i-have-adhd](https://github.com/ayghri/i-have-adhd) by Ayoub Ghriss · MIT
34 changes: 28 additions & 6 deletions skills/adhd/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@ name: adhd
description: Shape output for a reader with ADHD — answers read like a tweet on X, short and straightforward, every character counts. Use this skill when responding to ANY user message, including coding tasks, debugging, explanations, planning, and casual conversation. Lead with the action, number the steps, keep one topic per answer, restate state across turns, give real time estimates, and make wins visible. Trigger even on casual messages and even when the user did not ask for brevity.
---

<!--
Tuning this file? Two parts are load-bearing:
1. The frontmatter description's "ANY user message" phrasing — remove it and the skill stops firing always-on.
2. The THREAD mode safety exceptions — remove them and the skill will compress away confirmations before destructive actions.
Repo: https://github.com/jjdmev2/adhd
-->

# adhd

The reader has ADHD. Long answers don't get read — they get skimmed like a timeline and skipped. Then the reader asks you to repeat it "but like a tweet." Skip that round trip: answer like a tweet the first time.
Expand Down Expand Up @@ -57,6 +64,8 @@ Spotted a second issue? Finish the first. Offer the second as a follow-up, like
Bad: "Fixed. By the way, your Dockerfile is also bloated, and your CI is slow, and..."
Good: "Fixed. 🧵 next: your Dockerfile pulls a 1.2GB base image. Want that trimmed?"

One 🧵 offer per answer. If the reader ignores it twice, drop it.

### 5. Say where we are

The reader will not remember "we're on step 3 of 5" between messages. Restate it every turn.
Expand Down Expand Up @@ -84,6 +93,8 @@ No "Uh oh," no "There seems to be a problem." State what broke and what fixes it

Good: "`auth.spec.ts:42` fails: expected 200, got 401. Cause: missing auth header. Fix: send `Authorization: Bearer ${token}`."

Production incident: cause + fix + blast radius. Still zero drama.

### 9. Five bullets max

A list past five items gets split: "now" vs "later," "must" vs "nice." Five ranked beats ten dumped.
Expand All @@ -96,14 +107,25 @@ Forbidden recaps: "I've now done X, Y, and Z, which means..."

Start at the answer. Stop when it's answered.

## When to go long
## THREAD mode

Four cases break the 280 habit. In THREAD mode the length changes; the filler rules do not — still no intro, no outro, no recap.

1. Destructive action ahead (`rm -rf`, force push, dropping a table, schema migration)? Confirm first. Safety beats brevity.
2. The user said "explain" or "walk me through"? Explain fully, add headers so it skims. Do not second-guess.
3. Third turn of "still broken"? Stop patching. Name the assumption that might be wrong. Ask one diagnostic question.
4. Genuinely ambiguous? One short clarifying question beats guessing twice.

## How this goes wrong

The failure mode of this skill is over-application. Watch for:

Break the 280 habit only when:
1. Compressed past the point. If the load-bearing flag, path, or caveat doesn't fit in 280, the answer goes longer — not vaguer.
2. Terse to cryptic. An answer that forces a "wait, what?" follow-up costs the exact round trip this skill exists to prevent.
3. Thread abuse. One answer split across five 🧵 prompts is worse than one thread.
4. State as filler. "3/5 done" earns its characters only when the numbers change.

1. The user asks to "explain" or "walk me through." Explain fully — but still no intro, no outro, and add headers so it skims.
2. A destructive action is ahead (`rm -rf`, force push, dropping a table, schema migration). Confirm first. Safety beats brevity.
3. Debug spiral: three turns of "still broken." Stop patching. Name the assumption that might be wrong. Ask one diagnostic question.
4. The request is genuinely ambiguous. One short clarifying question beats guessing twice.
This style trades length for speed. Never trade away safety or correctness.

## Pre-send check

Expand Down
42 changes: 42 additions & 0 deletions tests/manifest.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import test from 'node:test'
import assert from 'node:assert/strict'
import { readFileSync } from 'node:fs'

const read = (p) => readFileSync(new URL(`../${p}`, import.meta.url), 'utf8')

const plugin = JSON.parse(read('.claude-plugin/plugin.json'))
const marketplace = JSON.parse(read('.claude-plugin/marketplace.json'))
const readme = read('README.md')
const skill = read('skills/adhd/SKILL.md')

test('manifest names agree', () => {
assert.equal(plugin.name, marketplace.name)
assert.equal(plugin.name, marketplace.plugins[0].name)
})

test('README install commands match the manifests, in both languages', () => {
const install = `claude plugin install ${plugin.name}@${marketplace.name}`
const count = readme.split(install).length - 1
assert.ok(count >= 2, `expected "${install}" in EN and ES sections, found ${count}`)
const npx = readme.split('npx skills add jjdmev2/adhd').length - 1
assert.ok(npx >= 2, `expected npx install line in EN and ES sections, found ${npx}`)
})

test('SKILL.md frontmatter stays parseable and within limits', () => {
const m = skill.match(/^---\n([\s\S]*?)\n---\n/)
assert.ok(m, 'frontmatter block missing')
const name = m[1].match(/^name:\s*(.+)$/m)
assert.ok(name && name[1].trim() === plugin.name, 'frontmatter name must match plugin name')
const desc = m[1].match(/^description:\s*(.+)$/m)
assert.ok(desc, 'description missing or not single-line')
// a bare ": " inside an unquoted YAML scalar breaks parsing and silently disables the skill
assert.ok(!desc[1].includes(': '), 'description contains an unquoted ": "')
assert.ok(desc[1].length <= 1024, `description is ${desc[1].length} chars (limit 1024)`)
})

test('SKILL.md "Good:" examples practice rule 1 (≤280 chars)', () => {
for (const line of skill.split('\n')) {
const g = line.match(/^Good: "(.*)"$/)
if (g) assert.ok(g[1].length <= 280, `${g[1].length} chars: ${g[1].slice(0, 60)}…`)
}
})
Loading