{"slug": "show-hn-turn-the-prompts-you-keep-retyping-into-slash-commands", "title": "Show HN: Turn the prompts you keep retyping into slash commands", "summary": "A new Agent Skill called faq-shortcuts, published as repo cli-faq-shortcuts with a v1.3.0 release, scans a developer's own prompt history in Claude Code, Codex and Cursor to find repeated requests and converts each into a short slash command such as /sent or /project billing. On one real project the tool's author reports a single ask typed 230 times when grouped by intent, versus 14 times for the most repeated exact request, and the extractor redacts pasted API keys, tokens and passwords to [REDACTED] before the agent reads the list. The extractor is standard-library Python requiring Python 3.9+ and no packages, API keys or network calls, with intent grouping performed by the coding agent itself.", "body_md": "**Stop typing the same long request to your coding agent every day.** This\n[Agent Skill](https://agentskills.io) reads your own history, finds the asks you keep\nrepeating, and turns each one into a short command, like `/sent` or `/project billing`.\nIt works in Claude Code, Codex and Cursor.\n\n- **Built from what you actually typed.** On one real project, a single ask had been\ntyped 230 times in different words. You see the counts and pick which become shortcuts.\n- **Secrets stay out.** API keys, tokens, and passwords you pasted into old prompts are\nreplaced with`[REDACTED]` before your agent reads the list.\n- **Nothing to install but the skill.** The extractor is standard-library Python: no\npackages, API keys, or network calls. Intent grouping happens in your coding agent.\n\n[Watch or download the 24-second video](https://github.com/kishormorol/cli-faq-shortcuts/releases/download/v1.2.0/faq-shortcuts-demo.mp4)\n· [What's new in v1.3.0](https://github.com/kishormorol/cli-faq-shortcuts/releases/tag/v1.3.0)\n\nThe demo illustrates the workflow with synthetic data; it is not a live agent recording.\n\n**1. Install** (macOS / Linux, needs `git` and Python 3.9+; on Windows see [Windows](#windows)):\n\n```\ngit clone https://github.com/kishormorol/cli-faq-shortcuts ~/.agents/skills/faq-shortcuts\nmkdir -p ~/.claude/skills && ln -sfn ~/.agents/skills/faq-shortcuts ~/.claude/skills/faq-shortcuts\n```\n\n**2. Open your project** in Claude Code, Codex or Cursor, in a new session.\n\n**3. Ask** *\"what do I keep asking in this project?\"*, or type `/faq-shortcuts` in Claude Code.\n\nYou'll get a table of your most repeated asks with how often you typed each. Pick the ones you want and they become shortcuts in that project.\n\nThe repo is `cli-faq-shortcuts`; the skill it installs is called **` faq-shortcuts`**.\n\n**If it saves you typing, please ⭐ star the repo.** Stars are how other people find it.\n\n```\n# inside your project, in Claude Code\n/faq-shortcuts                        # find your repeated asks and propose shortcuts\n/faq-shortcuts --since 2026-06-01     # only look at recent history\n/faq-shortcuts --source codex         # only what you asked Codex\n\n# the extractor on its own: no agent, nothing leaves your machine\nE=~/.agents/skills/faq-shortcuts/scripts/extract_asks.py\npython3 \"$E\" .                       # matching prompts, oldest first\npython3 \"$E\" . --since 2026-09-01 | wc -l               # how many since September\npython3 \"$E\" . --format jsonl         # structured records for your own scripts\npython3 \"$E\" . | awk -F'\\t' 'split($3,w,\" \")>=4 {print tolower($3)}' \\\n  | sort | uniq -c | sort -rn | head                     # your most repeated exact requests\n```\n\nThe last one counts exact repeats only, and it undercounts. On one real project, the most\nrepeated exact request appeared 14 times. Grouped by intent, however it was worded, the top\nask had been typed **230 times**. That grouping is the agent's job in `/faq-shortcuts`.\n\n| You kept typing | You type now | \n|---|---|\n| \"how many people signed up this week, not counting test accounts?\" | `/signups` | \n| \"did the newsletter actually go out? did it reach everyone?\" | `/sent` | \n| \"any update on the billing migration? what's blocked?\" | `/project billing` | \n| \"add this CSV of new customers, skip the ones we already have\" | `/import new.csv` | \n\nEach shortcut is a small file in your project, `.claude/skills/<name>/SKILL.md`, for example:\n\n```\n---\nname: sent\ndescription: Check whether a batch email actually reached people. Use for \"did the\n  newsletter go out?\", \"did it reach everyone?\", \"did X get the email?\".\n---\n# Did it go out\n\nReport only. Never re-send from this shortcut.\n\n## Query\nscripts/email-status.js --batch <name>   ← the script your project already has\n\n## Traps\n- A \"delivered\" status to a shared inbox proves nobody read it (happened 3 May).\n\n## Report\nSent / delivered / bounced counts, then the bounced addresses. Then ask.\n```\n\nThe shortcuts point at the scripts and queries **your** project already uses, and they\nrecord the mistakes already made on that path. `/sent` checks the send record, not the\nearlier message where the agent said it sent it. So a shortcut is shorter to type, and it\nverifies the outcome instead of trusting a previous claim. Anything that writes or sends\ndoes a dry run first and waits for your yes, so a typo stops at the preview.\n\n1. **Collect.**`scripts/extract_asks.py` prints every prompt you typed in the project,\nfrom Claude Code and Codex history. It skips subagent turns and scripted runs, because\nyou didn't type those.\n2. **Cluster.** The agent groups prompts by intent, whatever the wording, and counts them.\n3. **Check.** It looks for shortcuts you already have and the tools your project already has.\n4. **Propose.** You get a table of shortcut, the ask it replaces, and how often you asked.\nYou pick.\n5. **Write.** Each chosen shortcut becomes a`SKILL.md` in`.claude/skills/` , linked into`.agents/skills/` so all three agents load it, committed so your team gets it too.\n6. **List.** A table in`CLAUDE.md` /`AGENTS.md` maps each shortcut to the sentence it replaces.\n\nThe quick start above is the whole install. It puts the skill where each agent looks:\n\n| Agent | Reads skills from | \n|---|---|\n| Codex | `~/.agents/skills/` | \n| Claude Code | `~/.claude/skills/` (the link) | \n| Cursor | both | \n\n**Update:** `git -C ~/.agents/skills/faq-shortcuts pull --ff-only`, then start a new agent session.\n\n**Uninstall:** `rm ~/.claude/skills/faq-shortcuts && rm -rf ~/.agents/skills/faq-shortcuts`\n\nIf you only use Claude Code, you can install it as a plugin instead, inside Claude Code:\n\n```\n/plugin marketplace add kishormorol/cli-faq-shortcuts\n/plugin install faq-shortcuts@cli-faq-shortcuts\n```\n\nThe command is then `/faq-shortcuts:faq-shortcuts`, or just ask *\"what do I keep asking\nin this project?\"*. Codex and Cursor don't read Claude Code plugins, so use the quick\nstart for those.\n\nIn PowerShell, with `git` and Python 3.9+ installed. A directory junction links the skill\ninto `~/.claude/skills` and, unlike a symlink, needs no admin rights or Developer Mode:\n\n```\ngit clone https://github.com/kishormorol/cli-faq-shortcuts \"$env:USERPROFILE\\.agents\\skills\\faq-shortcuts\"\nNew-Item -ItemType Directory -Force \"$env:USERPROFILE\\.claude\\skills\" | Out-Null\nNew-Item -ItemType Junction -Path \"$env:USERPROFILE\\.claude\\skills\\faq-shortcuts\" -Target \"$env:USERPROFILE\\.agents\\skills\\faq-shortcuts\"\n```\n\nRun the extractor with `python` (or `py`), not `python3`:\n\n```\npython \"$env:USERPROFILE\\.agents\\skills\\faq-shortcuts\\scripts\\extract_asks.py\" . | Select-Object -First 10\n```\n\n**Update:** `git -C \"$env:USERPROFILE\\.agents\\skills\\faq-shortcuts\" pull --ff-only`, then start a new agent session.\n\n**Uninstall:** remove the junction with `rmdir`, which leaves its target alone, then the clone:\n\n```\ncmd /c rmdir \"$env:USERPROFILE\\.claude\\skills\\faq-shortcuts\"\nRemove-Item -Recurse -Force \"$env:USERPROFILE\\.agents\\skills\\faq-shortcuts\"\n```\n\n| Agent | History | Read? | \n|---|---|---|\n| Claude Code | `~/.claude/projects/<project>/*.jsonl` (the last 30 days) and`~/.claude/history.jsonl` (older prompts) | yes | \n| Codex | `~/.codex/sessions/` (or`$CODEX_HOME` ), matched by the folder each session ran in | yes | \n| Cursor | `Cursor/User/globalStorage/state.vscdb` under`~/Library/Application Support` (macOS),`%APPDATA%` (Windows) or`~/.config` (Linux), matched by the folder each chat ran in | yes, except chats opened without a folder | \n\nTo see what it finds without the agent:\n\n```\npython3 ~/.agents/skills/faq-shortcuts/scripts/extract_asks.py ~/my-project | head\n```\n\nThis prints `date<TAB>source<TAB>prompt`. Add `--source claude`, `--source codex`, or `--source cursor`\nto read one tool only, and `--since 2026-01-01` to skip older prompts.\n\n```\npython scripts/extract_asks.py [project_dir] [--source all|claude|codex|cursor]\n                              [--since YYYY-MM-DD] [--max-len N] [--min-words N]\n                              [--format tsv|jsonl] [--no-redact]\n```\n\n| Option | Default | Behavior | \n|---|---|---|\n| `project_dir` | Current directory | Match the exact project folder recorded in history. | \n| `--source` | `all` | Read one supported tool or all three. | \n| `--since` | No cutoff | Include the given UTC date and later; exclude prompts with unknown dates. | \n| `--max-len` | `400` | Skip prompts longer than this positive character limit, before whitespace cleanup. | \n| `--min-words` | `1` | Skip prompts with fewer words. `3` drops replies like \"ok\", \"yes\" and \"push\"; the skill uses it. | \n| `--no-redact` | off | Print pasted secrets as typed. By default they become `[REDACTED]` . | \n| `--format` | `tsv` | Emit tab-separated lines or one JSON object per line. | \n\nJSONL records have `date`, `source`, and `prompt` fields. Both formats collapse prompt\nwhitespace to single spaces. Dates are `YYYY-MM-DD`, or an empty string when unavailable;\nundated records sort first. Counts and diagnostics go to stderr, keeping stdout usable\nin a pipeline. Exit codes: `0` when a source is available (even if filters match nothing),\n`1` when no source is available, and `2` for invalid arguments.\n\n- This is a view of the history still stored on your machine, not a complete activity log.\n- Prompts longer than 400 characters, injected context, and non-interactive runs are\nfiltered out. Increase `--max-len` if your usual requests are longer.\n- Projects are matched by folder, without recursively including child folders or other worktrees. Moving a project does not move the paths recorded in old history.\n- Cursor's storage format is undocumented and can change. Chats without a recorded workspace or repository cannot be attributed to a project.\n- Malformed records are skipped. An invalid timestamp becomes an unknown date.\n\n| You see | Do this | \n|---|---|\n| The agent doesn't know `/faq-shortcuts` | Start a new session. Skills load when a session starts. Check that `ls ~/.claude/skills/faq-shortcuts/SKILL.md` finds the file. | \n| `checked, nothing for this folder (…)` | Run it from the project folder you actually worked in. History is stored per folder, so a subfolder counts as a different project. | \n| Claude Code asks to allow `python3 …extract_asks.py` | Allow it. The script reads your history under `~/.claude` (and Codex, Cursor) and makes no network calls. In headless runs (`claude -p` ) nobody can answer that prompt, so pass`--add-dir ~/.claude --allowedTools \"Bash(python3:*)\"` . | \n| Very few prompts found | History is read only for the project folder you actually worked in. Cursor chats opened without a folder aren't tied to any project, so they're skipped. | \n| `fatal: destination path … already exists` | It's already installed. Run the update command instead. | \n| No output after `--since` | Check the date and project folder. No matching prompts is a successful empty result; try without the date filter. | \n| `could not read session history` | Check file permissions and try `--source` with another tool. Available sources can still produce results. | \n| Requests you remember are missing | Try `--max-len 2000` ; long prompts are filtered by default. | \n\nIssues and pull requests are welcome. See [CONTRIBUTING.md](https://github.com/kishormorol/cli-faq-shortcuts/blob/main/CONTRIBUTING.md) for local\nchecks and guidance on creating a safe reproduction. Good first contributions:\n\n- **History compatibility fixes** backed by small synthetic fixtures.\n- **Install and troubleshooting improvements** for the tools and platforms you use.\n- **A bug report** with your OS, Python version, command, and sanitized error message.\n\nWindows installation and extraction are supported and covered by CI, alongside Linux\nand macOS. See the [changelog](https://github.com/kishormorol/cli-faq-shortcuts/blob/main/CHANGELOG.md) for unreleased improvements.\n\nEveryone whose pull request is merged appears here:\n\nBuilt and maintained with help from [Claude Code](https://claude.com/claude-code)\nand [OpenAI Codex](https://openai.com/codex/).\n\nThe extractor only reads local files and makes no network calls. Before it prints\nanything, it replaces secrets pasted into prompts with `[REDACTED]`: API keys\n(Anthropic, OpenAI, GitHub, Slack, AWS, Google, Hugging Face, Stripe, Resend, Supabase,\nKaggle), JWTs, bearer tokens, `password=`-style values, passwords in URLs such as\n`postgresql://user:pass@host`, Discord and Slack webhooks, and any other bare token of 30+\nmixed-case letters and digits. Matching is by pattern, so treat it as a safety net, not a\nguarantee. Your prompts can still contain names and emails, so the skill writes the list\nto a scratch folder, never into your repo. Your agent then reads that list the same way it reads any file you show it.\n\nThat agent may send the prompts to its configured model provider. Review your agent's settings before using sensitive history. Do not attach raw history, extractor output, or Cursor databases to public issues. Use invented prompts in bug reproductions and review generated shortcuts before committing them.", "url": "https://wpnews.pro/news/show-hn-turn-the-prompts-you-keep-retyping-into-slash-commands", "canonical_source": "https://github.com/kishormorol/cli-faq-shortcuts", "published_at": "2026-10-29 02:11:52+00:00", "updated_at": "2026-10-29 02:41:48.961534+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "developer-tools", "ai-products"], "entities": ["faq-shortcuts", "cli-faq-shortcuts", "Claude Code", "Codex", "Cursor", "kishormorol"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/show-hn-turn-the-prompts-you-keep-retyping-into-slash-commands", "markdown": "https://wpnews.pro/news/show-hn-turn-the-prompts-you-keep-retyping-into-slash-commands.md", "text": "https://wpnews.pro/news/show-hn-turn-the-prompts-you-keep-retyping-into-slash-commands.txt", "jsonld": "https://wpnews.pro/news/show-hn-turn-the-prompts-you-keep-retyping-into-slash-commands.jsonld"}}