{"id":903,"date":"2026-03-03T14:05:39","date_gmt":"2026-03-03T06:05:39","guid":{"rendered":"https:\/\/vinta.ws\/code\/?p=903"},"modified":"2026-04-12T05:11:35","modified_gmt":"2026-04-11T21:11:35","slug":"claude-code-useful-plugins-skills-and-mcps","status":"publish","type":"post","link":"https:\/\/vinta.ws\/code\/claude-code-useful-plugins-skills-and-mcps.html","title":{"rendered":"Claude Code: Things I Learned After Using It Every Day"},"content":{"rendered":"<p>I've used Claude Code daily since it came out. Here are the best practices, tools, and configuration patterns I've picked up. Most of this applies to other coding agents (Codex, Gemini CLI) too.<\/p>\n<blockquote>\n<p>TL;DR<br \/>\nMy configs, plugins, and skills for Claude Code:<br \/>\n<a href=\"https:\/\/github.com\/vinta\/hal-9000\">https:\/\/github.com\/vinta\/hal-9000<\/a><\/p>\n<\/blockquote>\n<h2>CLAUDE.md<\/h2>\n<h3>The Global CLAUDE.md<\/h3>\n<p>Your <code>~\/.claude\/CLAUDE.md<\/code> should only contain:<\/p>\n<ul>\n<li>Your preferences and nudges to correct agent behaviors<\/li>\n<li>You probably don't need to tell it YAGNI or KISS. They're already built in<\/li>\n<\/ul>\n<p>Pro tip: before adding something to <code>CLAUDE.md<\/code>, ask it, <strong>&quot;Is this already covered in your system prompt?&quot;<\/strong><\/p>\n<p>Here are some parts of my <code>CLAUDE.md<\/code> I found useful:<\/p>\n<pre class=\"line-numbers\"><code class=\"language-markdown\">&lt;prefer_online_sources&gt;\nYour training data goes stale. Config keys get renamed, APIs get deprecated, CLI flags change between versions. When you guess instead of checking, the user wastes time debugging your confident-but-wrong output. This has happened repeatedly.\n\nLook things up with the <code>find-docs<\/code> skill or <code>WebSearch<\/code> BEFORE writing code or config. This applies even when you feel confident about the answer. Always look up:\n\n- Config file keys, flags, syntax, and environment variables for any tool\n- Library\/framework API calls, module paths, and parameter names\n- CLI flags and subcommands\n- Dependency versions\n- Best practices and recommended patterns\n- Assertions about external tool behavior, even when confident\n\nThe cost of a lookup is seconds. The cost of a wrong config key is a failed run plus a debugging round-trip.\n&lt;\/prefer_online_sources&gt;\n\n&lt;auto_commit if=\"you have completed the user's requested change\"&gt;\nUse the <code>commit<\/code> skill to commit, always passing a brief description of what changed (e.g. <code>\/commit add login endpoint<\/code>). Don't batch unrelated changes into one commit.\n&lt;\/auto_commit&gt;<\/code><\/pre>\n<p>Also see:<\/p>\n<ul>\n<li><a href=\"https:\/\/raw.githubusercontent.com\/vinta\/hal-9000\/refs\/heads\/main\/dotfiles\/.claude\/CLAUDE.md\">GitHub: vinta\/hal-9000 - The user-level CLAUDE.md<\/a><\/li>\n<li><a href=\"https:\/\/www.hlyr.dev\/blog\/stop-claude-from-ignoring-your-claude-md\">Stop Claude from Ignoring Your CLAUDE.md<\/a><\/li>\n<\/ul>\n<h3>The Project CLAUDE.md<\/h3>\n<p>For project-specific instructions, put them in the project-level <code>CLAUDE.md<\/code>.<\/p>\n<p>The highest-signal content in your project <code>CLAUDE.md<\/code> (or any skill) is the <strong>Gotchas<\/strong> section. Build these from the failure points Claude Code actually runs into.<\/p>\n<p>Also see:<\/p>\n<ul>\n<li><a href=\"https:\/\/x.com\/trq212\/status\/2033949937936085378\">Twitter: @trq212 - Lessons from Building Claude Code: How We Use Skills<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/anthropics\/claude-plugins-official\/blob\/main\/plugins\/claude-md-management\/skills\/claude-md-improver\/references\/templates.md\">GitHub: anthropics\/claude-plugins-official - CLAUDE.md templates<\/a><\/li>\n<\/ul>\n<h3>Per File Type Rules<\/h3>\n<p>For language-specific or per-file <a href=\"https:\/\/code.claude.com\/docs\/en\/memory#organize-rules-with-claude\/rules\/\">rules<\/a>, put them in <code>~\/.claude\/rules\/<\/code>, so Claude Code only loads them when editing those file types.<\/p>\n<p>For instance, <code>~\/.claude\/rules\/typescript-javascript.md<\/code>:<\/p>\n<pre class=\"line-numbers\"><code class=\"language-markdown\">---\npaths:\n  - \"**\/*.ts\"\n  - \"**\/*.tsx\"\n  - \"**\/*.js\"\n  - \"**\/*.jsx\"\n  - \"docs\/**\/*.md\"\n---\n\n# TypeScript \/ JavaScript\n\n- Before adding a dependency, search npm or the web for the latest version\n- Pin exact dependency versions in <code>package.json<\/code> \u2014 no <code>^<\/code> or <code>~<\/code> prefixes\n- Use <code>node:<\/code> prefix for Node.js built-in modules (e.g., <code>node:fs<\/code>, <code>node:path<\/code>)\n- Use <code>const<\/code> by default, <code>let<\/code> when reassignment is needed, never <code>var<\/code>\n- Prefer <code>async<\/code>\/<code>await<\/code> over <code>.then()<\/code> chains\n- Use template literals over string concatenation\n- Use optional chaining (<code>?.<\/code>) and nullish coalescing (<code>??<\/code>) over manual checks\n- Never use <code>as any<\/code> or <code>unknown<\/code>. Always write proper types\/interfaces. Only use <code>any<\/code> or <code>unknown<\/code> as a last resort when no typed alternative exists\n- Prefer <code>interface<\/code> over <code>type<\/code> for object shapes (extendable, better error messages)\n- Avoid enums. Use union types (<code>type Status = &#039;active&#039; | &#039;inactive&#039;<\/code>) or <code>as const<\/code> objects\n- Don't prefix interfaces with <code>I<\/code> or type aliases with <code>T<\/code> (e.g., <code>User<\/code> not <code>IUser<\/code>)\n- Mark properties and parameters <code>readonly<\/code> when they should not be mutated\n- Do not add explicit return types. Let TypeScript infer them\n\n&lt;verify_with_browser if=\"you completed a frontend change (UI component, page, client-side behavior)\" only_if=\"playwright-cli skill is installed in project or user scope\"&gt;\nAfter implementing frontend changes, use the <code>playwright-cli<\/code> skill to visually verify the result in a real browser. Check layout, responsiveness, and interactive behavior rather than assuming correctness from code alone.\n&lt;\/verify_with_browser&gt;<\/code><\/pre>\n<p>The full rules I have:<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/vinta\/hal-9000\/tree\/main\/dotfiles\/.claude\/rules\">GitHub: vinta\/hal-9000 - .claude\/rules\/<\/a><\/li>\n<\/ul>\n<h2>Configurations<\/h2>\n<h3>Settings<\/h3>\n<p>There are some useful <a href=\"https:\/\/code.claude.com\/docs\/en\/settings\">configurations<\/a> you could set in your <code>~\/.claude\/settings.json<\/code>:<\/p>\n<pre class=\"line-numbers\"><code class=\"language-json\">{\n  \"env\": {\n    \"CLAUDE_CODE_BASH_MAINTAIN_PROJECT_WORKING_DIR\": \"1\",\n    \"CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING\": \"1\",\n    \"CLAUDE_CODE_EFFORT_LEVEL\": \"max\",\n    \"CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS\": \"1\",\n    \"CLAUDE_CODE_NEW_INIT\": \"1\",\n    \"CLAUDE_CODE_NO_FLICKER\": \"1\",\n    \"ENABLE_CLAUDEAI_MCP_SERVERS\": \"false\",\n    \"USE_BUILTIN_RIPGREP\": \"0\"\n  },\n  \"permissions\": {\n    \"allow\": [\"...\"],\n    \"deny\": [\"...\"],\n    \"ask\": [\"...\"],\n    \"defaultMode\": \"auto\",\n    \"additionalDirectories\": [\n      \"~\/Projects\"\n    ]\n  },\n  \"cleanupPeriodDays\": 365,\n  \"showThinkingSummaries\": true,\n  \"showClearContextOnPlanAccept\": true,\n  \"voiceEnabled\": true\n}<\/code><\/pre>\n<p>Highlights:<\/p>\n<ul>\n<li><code>&quot;CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING&quot;: &quot;1&quot;<\/code>: To mitigate the <a href=\"https:\/\/news.ycombinator.com\/item?id=47660925\">Claude Code Degradation<\/a> issue<\/li>\n<li><code>&quot;CLAUDE_CODE_EFFORT_LEVEL&quot;: &quot;max&quot;<\/code>: Same as above<\/li>\n<li><code>&quot;CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS&quot;: &quot;1&quot;<\/code>: Enable <a href=\"https:\/\/code.claude.com\/docs\/en\/agent-teams\">Agent Team<\/a> feature, a fancy way to consume a huge amount of tokens<\/li>\n<li><code>&quot;permissions.defaultMode&quot;: &quot;auto&quot;<\/code>: We use this to pretend it's safer than <code>--dangerously-skip-permissions<\/code><\/li>\n<li><code>&quot;cleanupPeriodDays&quot;: 365<\/code>: By default, your chat history (location: <code>~\/.claude\/projects\/<\/code>) will be deleted after 30 days. If you want to keep them, set a higher number<\/li>\n<li><code>&quot;voiceEnabled&quot;: true<\/code>: Enable <a href=\"https:\/\/code.claude.com\/docs\/en\/voice-dictation\">Voice Dictation<\/a> feature. Code like a boss!<\/li>\n<\/ul>\n<p>The full settings I use:<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/vinta\/hal-9000\/blob\/main\/dotfiles\/.claude\/settings.json\">GitHub: vinta\/hal-9000 - .claude\/settings.json<\/a><\/li>\n<\/ul>\n<h3>Permissions<\/h3>\n<p>If you're not using a sandbox or devcontainer for Claude Code, you may want to block some <strong>evil<\/strong> commands in your <code>~\/.claude\/settings.json<\/code>:<\/p>\n<pre class=\"line-numbers\"><code class=\"language-json\">{\n  \"permissions\": {\n    \"deny\": [\n      \"Read(~\/.aws\/**)\",\n      \"Read(~\/.config\/**)\",\n      \"Read(~\/.docker\/**)\",\n      \"Read(~\/.dropbox\/**)\",\n      \"Read(~\/.gnupg\/**)\",\n      \"Read(~\/.gsutil\/**)\",\n      \"Read(~\/.kube\/**)\",\n      \"Read(~\/.npmrc)\",\n      \"Read(~\/.orbstack\/**)\",\n      \"Read(~\/.pypirc)\",\n      \"Read(~\/.ssh\/**)\",\n      \"Read(~\/*history*)\",\n      \"Read(~\/**\/*credential*)\",\n      \"Read(~\/Library\/**)\",\n      \"Write(~\/Library\/**)\",\n      \"Edit(~\/Library\/**)\",\n      \"Read(~\/Dropbox\/**)\",\n      \"Write(~\/Dropbox\/**)\",\n      \"Edit(~\/Dropbox\/**)\",\n      \"Read(\/\/etc\/**)\",\n      \"Write(\/\/etc\/**)\",\n      \"Edit(\/\/etc\/**)\",\n      \"Bash(su *)\",\n      \"Bash(sudo *)\",\n      \"Bash(passwd *)\",\n      \"Bash(env *)\",\n      \"Bash(printenv *)\",\n      \"Bash(history *)\",\n      \"Bash(fc *)\",\n      \"Bash(eval *)\",\n      \"Bash(exec *)\",\n      \"Bash(rsync *)\",\n      \"Bash(sftp *)\",\n      \"Bash(telnet *)\",\n      \"Bash(socat *)\",\n      \"Bash(nc *)\",\n      \"Bash(ncat *)\",\n      \"Bash(netcat *)\",\n      \"Bash(nmap *)\",\n      \"Bash(kill *)\",\n      \"Bash(killall *)\",\n      \"Bash(pkill *)\",\n      \"Bash(chmod *)\",\n      \"Bash(chown *)\",\n      \"Bash(chflags *)\",\n      \"Bash(xattr *)\",\n      \"Bash(diskutil *)\",\n      \"Bash(mkfs *)\",\n      \"Bash(security *)\",\n      \"Bash(defaults *)\",\n      \"Bash(launchctl *)\",\n      \"Bash(osascript *)\",\n      \"Bash(dscl *)\",\n      \"Bash(networksetup *)\",\n      \"Bash(scutil *)\",\n      \"Bash(systemsetup *)\",\n      \"Bash(pmset *)\",\n      \"Bash(crontab *)\"\n    ],\n    \"ask\": [\n      \"Bash(curl *)\",\n      \"Bash(wget *)\",\n      \"Bash(open *)\",\n      \"Bash(*install*)\",\n      \"Bash(uv add *)\",\n      \"Bash(bun add *)\",\n      \"Bash(git push *)\",\n    ]\n  },\n  \"hooks\": {\n    \"PreToolUse\": [\n      {\n        \"matcher\": \"Bash\",\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"python3 ~\/.claude\/hooks\/guard-bash-paths.py\"\n          }\n        ]\n      }\n    ]\n  }\n}<\/code><\/pre>\n<p>However, <code>&quot;deny&quot;: [&quot;Read(~\/.aws\/**)&quot;, &quot;Read(~\/.kube\/**)&quot;, ...]<\/code> alone is not enough, since Claude Code can still read sensitive files through the <code>Bash<\/code> tool. You can write a simple hook to intercept <code>Bash<\/code> commands that access blocked files, like this <a href=\"https:\/\/github.com\/vinta\/hal-9000\/blob\/main\/dotfiles\/.claude\/hooks\/guard-bash-paths.py\"><code>guard-bash-paths.py<\/code><\/a> hook.<\/p>\n<p>Though, <strong>Claude Code can still write a one-time script to read sensitive data<\/strong> and bypass all of the above defenses. So the safest approach is using sandbox after all.<\/p>\n<p>Also see:<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/trailofbits\/claude-code-config\">GitHub: trailofbits\/claude-code-config<\/a><\/li>\n<\/ul>\n<h2>Plugins<\/h2>\n<p>Claude Code <a href=\"https:\/\/code.claude.com\/docs\/en\/discover-plugins\">Plugins<\/a> are simply a way to package skills, commands, agents, hooks, and MCP servers. Distributing them as a plugin has the following advantages:<\/p>\n<ul>\n<li>Auto update (versioned releases)<\/li>\n<li>Auto hooks configuration (users don't need to edit their <code>~\/.claude\/settings.json<\/code> manually)<\/li>\n<li>Skills have a <code>\/plugin-name:your-skill-name<\/code> prefix (no more conflicts)<\/li>\n<\/ul>\n<p>To install a plugin, you need to add a marketplace first. A marketplace is usually just a GitHub repo. Think of it as a namespace.<\/p>\n<pre class=\"line-numbers\"><code class=\"language-bash\">claude plugin marketplace add anthropics\/claude-plugins-official\nclaude plugin marketplace add openai\/codex-plugin-cc\nclaude plugin marketplace add slavingia\/skills\nclaude plugin marketplace add trailofbits\/skills\nclaude plugin marketplace add vinta\/hal-9000\n\n# then enter Claude Code to browse plugins\n\/plugin<\/code><\/pre>\n<p>Here are plugins I use:<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/anthropics\/claude-plugins-official\">GitHub: anthropics\/claude-plugins-official<\/a>: The official Claude Code marketplace<\/li>\n<li><a href=\"https:\/\/github.com\/openai\/codex-plugin-cc\">GitHub: openai\/codex-plugin-cc<\/a>: OpenAI Codex's official plugin for Claude Code<\/li>\n<li><a href=\"https:\/\/github.com\/obra\/superpowers\">GitHub: obra\/superpowers<\/a>: The first skills I ever installed, and still find them useful<\/li>\n<li><a href=\"https:\/\/github.com\/slavingia\/skills\">GitHub: slavingia\/skills<\/a>: It's like <a href=\"https:\/\/github.com\/garrytan\/gstack\">gstack<\/a>, but less bullshit<\/li>\n<li><a href=\"https:\/\/github.com\/trailofbits\/skills\">GitHub: trailofbits\/skills<\/a>: I only use the <a href=\"https:\/\/github.com\/trailofbits\/skills\/blob\/main\/plugins\/gh-cli\">gh-cli<\/a> hook though<\/li>\n<li><a href=\"https:\/\/github.com\/vinta\/hal-9000\/tree\/main\/plugins\/hal-skills\">GitHub: vinta\/hal-9000<\/a>: My personal skills<\/li>\n<\/ul>\n<h2>Skills<\/h2>\n<p><a href=\"https:\/\/code.claude.com\/docs\/en\/skills\">Skills<\/a> can contain executable scripts and hooks, not just Markdown. <strong>Use with caution!<\/strong> When in doubt, have your agent review them first.<\/p>\n<p>Here are skills I use, mostly installed per project when needed:<\/p>\n<pre class=\"line-numbers\"><code class=\"language-bash\"># my skills\nnpx skills add https:\/\/github.com\/vinta\/hal-9000 --skill commit magi second-opinions -g\nnpx skills add https:\/\/github.com\/vinta\/dear-ai\n\n# writing skills\nnpx skills add https:\/\/github.com\/softaworks\/agent-toolkit --skill writing-clearly-and-concisely humanizer naming-analyzer\nnpx skills add https:\/\/github.com\/hardikpandya\/stop-slop\nnpx skills add https:\/\/github.com\/shyuan\/writing-humanizer\n\n# doc skills\nnpx skills add https:\/\/github.com\/upstash\/context7 --skill find-docs -g\n\n# backend skills\nnpx skills add https:\/\/github.com\/trailofbits\/skills --skill modern-python\nnpx skills add https:\/\/github.com\/vintasoftware\/django-ai-plugins\nnpx skills add https:\/\/github.com\/supabase\/agent-skills\nnpx skills add https:\/\/github.com\/planetscale\/database-skills\nnpx skills add https:\/\/github.com\/cloudflare\/skills\n\n# frontend skills\nnpx skills add https:\/\/github.com\/vercel-labs\/agent-skills\nnpx skills add https:\/\/github.com\/vercel-labs\/next-skills\n\n# design skills\nnpx skills add https:\/\/github.com\/openai\/skills --skill frontend-skill\nnpx skills add https:\/\/github.com\/pbakaus\/impeccable\nnpx skills add https:\/\/github.com\/nextlevelbuilder\/ui-ux-pro-max-skill\n\n# video skills\nnpx skills add https:\/\/github.com\/remotion-dev\/skills\n\n# browser skills\nnpx skills add https:\/\/github.com\/vercel-labs\/agent-browser\nnpx skills add https:\/\/github.com\/microsoft\/playwright-cli\n\nnpx skills list -g\nnpx skills update -g\nnpx skills remove --all -g<\/code><\/pre>\n<p>Highlights:<\/p>\n<ul>\n<li><code>\/brainstorming<\/code> from <a href=\"https:\/\/github.com\/obra\/superpowers\">superpowers<\/a>: When in doubt, start with this skill<\/li>\n<li><code>\/writing-skills<\/code> from <a href=\"https:\/\/github.com\/obra\/superpowers\">superpowers<\/a>: Use this skill to improve your skills<\/li>\n<li><code>\/skill-creator<\/code> from <a href=\"https:\/\/github.com\/anthropics\/claude-plugins-official\">claude-plugins-official<\/a>: Use this skill to <strong>evaluate<\/strong> your skills<\/li>\n<li><code>\/find-docs<\/code> from <a href=\"https:\/\/github.com\/upstash\/context7\">context7<\/a>: Find the latest documentations<\/li>\n<li><code>\/frontend-design<\/code> from <a href=\"https:\/\/github.com\/pbakaus\/impeccable\">impeccable<\/a>: The better version of the official <code>\/frontend-design<\/code> skill<\/li>\n<li><code>\/simplify<\/code>: Run it often, you will like it<\/li>\n<li><code>\/insights<\/code>: Analyze your Claude Code sessions<\/li>\n<\/ul>\n<p>You can find more skills on <a href=\"https:\/\/skills.sh\/\">skills.sh<\/a>.<\/p>\n<h2>MCP Servers<\/h2>\n<p>You probably don't need any <a href=\"https:\/\/code.claude.com\/docs\/en\/mcp\">MCP servers<\/a> if you can do the same thing with CLI + skills.<\/p>\n<h2>Context7 MCP<\/h2>\n<p>No, just use the <code>ctx7<\/code> CLI with <code>find-docs<\/code> skill instead.<\/p>\n<pre class=\"line-numbers\"><code class=\"language-bash\">npx ctx7 setup<\/code><\/pre>\n<ul>\n<li><a href=\"https:\/\/github.com\/upstash\/context7\">GitHub: upstash\/context7<\/a><\/li>\n<\/ul>\n<h3>Playwright MCP<\/h3>\n<p>No, you should use the <code>playwright-cli<\/code> or <code>agent-browser<\/code> skill instead. Both tools support <strong>headed mode<\/strong> (the opposite of headless), if you'd like to see the browser.<\/p>\n<pre class=\"line-numbers\"><code class=\"language-bash\">npm install -g @playwright\/cli@latest\nnpx skills add https:\/\/github.com\/microsoft\/playwright-cli\n\nnpm install -g agent-browser\nagent-browser install\nnpx skills add https:\/\/github.com\/vercel-labs\/agent-browser<\/code><\/pre>\n<ul>\n<li><a href=\"https:\/\/github.com\/microsoft\/playwright-cli\">GitHub: microsoft\/playwright-cli<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/vercel-labs\/agent-browser\">GitHub: vercel-labs\/agent-browser<\/a><\/li>\n<\/ul>\n<h3>GitHub MCP<\/h3>\n<p>No, you should use the <code>gh<\/code> command instead.<\/p>\n<pre class=\"line-numbers\"><code class=\"language-bash\">brew install gh<\/code><\/pre>\n<p>Trail of Bits' <code>gh-cli<\/code> plugin is also worth a look, though you should check how it uses hooks to intercept GitHub fetch requests. Quite controversial for a security company.<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/trailofbits\/skills\/tree\/main\/plugins\/gh-cli\">GitHub: trailofbits\/skills - gh-cli<\/a><\/li>\n<\/ul>\n<h3>Codex MCP<\/h3>\n<p>Yes, ironically. Other coding agents like Claude Code can use Codex via MCP, which is slightly more stable than directly invoking it with <code>codex exec<\/code> via CLI.<\/p>\n<pre class=\"line-numbers\"><code class=\"language-bash\"># Codex reads your local .codex\/config.toml by default\nclaude mcp add codex --scope user -- codex mcp-server\n\n# You can still override some configs\nclaude mcp add codex --scope user -- codex -m gpt-5.3-codex-spark -c model_reasoning_effort=\"high\" mcp-server<\/code><\/pre>\n<ul>\n<li><a href=\"https:\/\/developers.openai.com\/codex\/cli\/reference\/#codex-mcp-server\">Codex Command Line Options - codex mcp-server<\/a><\/li>\n<\/ul>\n<p>However, since OpenAI releases the official Claude Code plugin: <a href=\"https:\/\/github.com\/openai\/codex-plugin-cc\">codex-plugin-cc<\/a>, you should probably use that instead.<\/p>\n<h2>Some Other Tips<\/h2>\n<h3>Prompt Best Practices<\/h3>\n<ul>\n<li><a href=\"https:\/\/platform.claude.com\/docs\/en\/build-with-claude\/prompt-engineering\/claude-prompting-best-practices\">Claude Prompting Best Practices<\/a><\/li>\n<li><a href=\"https:\/\/developers.openai.com\/cookbook\/examples\/gpt-5\/codex_prompting_guide\">Codex Prompting Guide<\/a><\/li>\n<li><a href=\"https:\/\/ai.google.dev\/gemini-api\/docs\/prompting-strategies\">Gemini Prompting Strategies<\/a><\/li>\n<\/ul>\n<h3>Command Aliases<\/h3>\n<pre class=\"line-numbers\"><code class=\"language-bash\"># in ~\/.zshrc\nalias cc=\"claude --enable-auto-mode --teammate-mode tmux\"\nalias ccc=\"claude --enable-auto-mode --continue --teammate-mode tmux\"\nalias cct='tmux -CC new-session -s \"claude-$(date +%s)\" claude --enable-auto-mode --teammate-mode tmux'\nalias ccy=\"claude --teammate-mode tmux --dangerously-skip-permissions\"\nccp() { claude --no-chrome --no-session-persistence -p \"$*\"; }<\/code><\/pre>\n<p>Use <code>ccp<\/code> for ad-hoc prompts:<\/p>\n<pre class=\"line-numbers\"><code class=\"language-bash\">ccp \"commit\"\nccp \"list all .md in this repo\"<\/code><\/pre>\n<ul>\n<li><a href=\"https:\/\/github.com\/vinta\/hal-9000\/blob\/main\/dotfiles\/.zshrc\">GitHub: vinta\/hal-9000 - .zshrc<\/a><\/li>\n<\/ul>\n<h3>Customize Your Statusline<\/h3>\n<p>Claude Code has a customizable <a href=\"https:\/\/code.claude.com\/docs\/en\/statusline\">statusline<\/a> at the bottom of the terminal. You can run any script that outputs text.<\/p>\n<p>Mine shows the current model, the current working folder, the git branch, and a grammar-corrected version of my last prompt (because my English needs all the help it can get). The grammar correction runs an ad-hoc <code>claude<\/code> command inside the statusline script.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/raw.githubusercontent.com\/vinta\/hal-9000\/main\/assets\/claude-code-statusline-grammar-check.png\" alt=\"Claude Code Statusline with English Grammar Check example\" \/><\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/vinta\/hal-9000\/tree\/main\/plugins\/hal-statusline\">GitHub: vinta\/hal-9000 - statusline<\/a><\/li>\n<\/ul>\n<h3>Run Ad-Hoc Claude Commands Inside Scripts<\/h3>\n<p>You can invoke <code>claude<\/code> as a one-shot CLI tool from hooks, statusline scripts, CI, or anywhere else. The trick is using the right flags to get a clean, isolated call with zero side effects:<\/p>\n<pre class=\"line-numbers\"><code class=\"language-python\">cmd = \"\"\"\n    claude\n    --model haiku\n    --max-turns 1\n    --setting-sources \"\"\n    --tools \"\"\n    --disable-slash-commands\n    --no-session-persistence\n    --no-chrome\n    --print\n\"\"\"\n\nresult = subprocess.run(\n    [*shlex.split(cmd), your_prompt],\n    capture_output=True,\n    text=True,\n    timeout=15,\n    cwd=\"\/tmp\",\n)<\/code><\/pre>\n<p>What each flag does:<\/p>\n<ul>\n<li><code>--setting-sources &quot;&quot;<\/code>: don't load hooks (avoids infinite recursion if called from a hook)<\/li>\n<li><code>--no-session-persistence<\/code> and <code>cwd=&quot;\/tmp&quot;<\/code>: avoid polluting your current context<\/li>\n<li><code>--tools &quot;&quot;<\/code>: no file access, no bash, pure text in\/out<\/li>\n<li><code>--no-chrome<\/code>: skip the Chrome integration<\/li>\n<\/ul>\n<h3>Multi-Model Second Opinions<\/h3>\n<p>You can get independent code reviews or brainstorming input from other model families (Codex, Gemini) without leaving Claude Code. I have two skills for this:<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/vinta\/hal-9000\/tree\/main\/plugins\/hal-skills\/skills\/magi\">magi<\/a>: Evangelion's MAGI system as a brainstorming panel. Three personas (Scientist\/Opus, Mother\/Codex, Woman\/Gemini) deliberate in parallel<\/li>\n<li><a href=\"https:\/\/github.com\/vinta\/hal-9000\/blob\/main\/plugins\/hal-skills\/skills\/second-opinions\/SKILL.md\">second-opinions<\/a>: Asks Codex and\/or Gemini to review code, plans, or docs, then synthesizes their feedback<\/li>\n<\/ul>\n<p>This works because each model family has different training biases. Claude might miss something Codex catches, and vice versa. It's especially useful for architecture decisions and &quot;what should I build next&quot; brainstorming.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I've used Claude Code daily since it came out. These are the best practices, tools, and configuration patterns that I learned. Most of this applies to other coding agents (Codex, Gemini CLI) too.<\/p>\n","protected":false},"author":1,"featured_media":904,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[97],"tags":[127,153,101,154],"class_list":["post-903","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-about-ai","tag-chat-bot","tag-claude-code","tag-cli-tool","tag-coding-agent"],"_links":{"self":[{"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/posts\/903","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/comments?post=903"}],"version-history":[{"count":0,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/posts\/903\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/media\/904"}],"wp:attachment":[{"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/media?parent=903"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/categories?post=903"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/tags?post=903"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}