Styles replies and prompts on the desktop: verdict and action boxes, section titles, a prompt bubble

A growing collection of custom Claude Code resources built for real workflows.
Commands (27 total) - Slash commands that expand into structured workflows
Skills (7 total) - Autonomous workflows that research, generate, and self-heal
Agents (3 total) - Specialized subagents for validation and quality
# Add the marketplace
claude plugin marketplace add aren13/ae-cc
# Install the plugin
claude plugin install ae-cc
Start a new Claude Code session to use the commands and skills.
# Clone the repo
git clone https://github.com/aren13/ae-cc.git
cd ae-cc
# Install commands
cp -r commands/* ~/.claude/commands/
# Install skills
cp -r skills/* ~/.claude/skills/
Commands install globally to ~/.claude/commands/. Skills install to ~/.claude/skills/. Project-specific data (prompts, todos) lives in each project's working directory.
Separate analysis from execution. Describe what you want in natural language, Claude generates a rigorous prompt, then runs it in a fresh sub-agent context.
/create-prompt - Generate optimized prompts with XML structure/run-prompt - Execute saved prompts in sub-agent contextsCapture ideas mid-conversation without derailing current work. Resume later with full context intact.
/add-to-todos - Capture tasks with full context/check-todos - Resume work on captured tasksCreate structured handoff documents to continue work in a fresh context. Reference with @./ae-cc/whats-next.md to resume seamlessly.
/whats-next - Create handoff document for fresh contextWrapper commands that invoke the skills below.
/create-agent-skill - Create a new skill/create-meta-prompt - Create staged workflow prompts/create-slash-command - Create a new slash command/create-subagent - Create a new subagent/create-hook - Create a new hookInvoke auditor subagents.
/audit-skill - Audit skill for best practices/audit-slash-command - Audit command for best practices/audit-subagent - Audit subagent for best practices/heal-skill - Fix skills based on execution issuesApply mental frameworks to decisions and problems.
/consider:pareto - Apply 80/20 rule to focus on what matters/consider:first-principles - Break down to fundamentals and rebuild/consider:inversion - Solve backwards (what guarantees failure?)/consider:second-order - Think through consequences of consequences/consider:5-whys - Drill to root cause/consider:occams-razor - Find simplest explanation/consider:one-thing - Identify highest-leverage action/consider:swot - Map strengths, weaknesses, opportunities, threats/consider:eisenhower-matrix - Prioritize by urgent/important/consider:10-10-10 - Evaluate across time horizons/consider:opportunity-cost - Analyze what you give up/consider:via-negativa - Improve by removingSystematic debugging with methodical investigation.
/debug - Apply expert debugging methodology to investigate issuesSpecialized subagents used by the audit commands.
skill-auditor - Expert skill auditor for best practices complianceslash-command-auditor - Expert slash command auditorsubagent-auditor - Expert subagent configuration auditorHierarchical project planning optimized for solo developer + Claude. Create executable plans that Claude runs, not enterprise documentation that sits unused.
PLAN.md IS the prompt - not documentation that gets transformed later. Brief → Roadmap → Research (if needed) → PLAN.md → Execute → SUMMARY.md.
Domain-aware: Optionally loads framework-specific expertise from ~/.claude/skills/expertise/ (e.g., macos-apps, iphone-apps) to make plans concrete instead of generic. Domain expertise skills are created with create-agent-skills - exhaustive knowledge bases (5k-10k+ lines) that make task specifications framework-appropriate.
Quality controls: Research includes verification checklists, blind spots review, critical claims audits, and streaming writes to prevent gaps and token limit failures.
Context management: Auto-handoff at 10% tokens remaining. Git versioning commits outcomes, not process.
Commands: /create-plan (invoke skill), /run-plan <path> (execute PLAN.md with intelligent segmentation)
See create-plans README for full documentation.
Build skills by describing what you want. Asks clarifying questions, researches APIs if needed, and generates properly structured skill files.
Two types of skills:
~/.claude/skills/expertise/ and provide framework-specific context to other skills like create-plansContext-aware: Detects if you're in a skill directory and presents relevant options. Progressive disclosure guides you through complex choices.
When things don't work perfectly, /heal-skill analyzes what went wrong and updates the skill based on what actually worked.
Commands: /create-agent-skill, /heal-skill, /audit-skill
The skill-based evolution of the meta-prompting system. Builds prompts with structured outputs (research.md, plan.md) that subsequent prompts can parse. Adds automatic dependency detection to chain research → plan → implement workflows.
Note: For end-to-end project building, consider create-plans - it's the more structured evolution of this approach with full lifecycle management (brief → roadmap → execution → handoffs). Use create-meta-prompts for abstract workflows and Claude→Claude pipelines. Use create-plans for actually building projects.
Commands: /create-meta-prompt
Build commands that expand into full prompts when invoked. Describe the command you want, get proper YAML configuration with arguments, tool restrictions, and dynamic context loading.
Commands: /create-slash-command, /audit-slash-command
Build specialized Claude instances that run in isolated contexts. Describe the agent's purpose, get optimized system prompts with the right tool access and orchestration patterns.
Commands: /create-subagent, /audit-subagent
Build event-driven automation that triggers on tool calls, session events, or prompt submissions. Describe what you want to automate, get working hook configurations.
Commands: /create-hook
Deep analysis debugging mode for complex issues. Activates methodical investigation protocol with evidence gathering, hypothesis testing, and rigorous verification. Use when standard troubleshooting fails or when issues require systematic root cause analysis.
Commands: /debug
For building projects: Use /create-plan to invoke the create-plans skill. After planning, use /run-plan <path-to-PLAN.md> to execute phases with intelligent segmentation. This provides hierarchical planning (BRIEF.md → ROADMAP.md → phases/PLAN.md), domain-aware task generation, context management with handoffs, and git versioning.
For domain expertise: Use create-agent-skills to create exhaustive knowledge bases in ~/.claude/skills/expertise/. These skills are automatically loaded by create-plans to make task specifications framework-specific instead of generic.
Other tools: The create-meta-prompts skill and /create-prompt + /run-prompt commands are available for custom Claude→Claude pipelines that don't fit the project planning structure.
More resources coming soon.
PS: Original repo and work -> TÂCHES's https://github.com/glittercowboy/taches-cc-resources/ repo. Please use the original repo if you are starting this journey. Community Ports: OpenCode
—Aren
hooks/register.tsx 110 lines1import { atom, memberOf, read, update } from 'claude-code'
2import type { Register } from 'claude-code'
3
4import { collapsePrompt, parseReply, plain } from './parse'
5
6// Muted green read off the person's reference screenshot (approximate).
7const BUBBLE_GREEN = '#3B6637'
8
9// Past this many characters the bubble stops growing and wraps at 70% of the row.
10const BUBBLE_WRAP_AT = 60
11
12// Which long prompts the person opened, one member per transcript row.
13const isPromptOpen = atom({ plugin: 'reply-style', key: 'isPromptOpen' } as const, false)
14
15// The desktop app stamps the person's prompts as `sdk`; the terminal as `composer`.
16const PROMPT_KINDS = new Set(['composer', 'sdk', 'bridge'])
17
18export const register: Register = on => {
19 on('ui.render', { component: 'AssistantMessage' }, ($, e, next) => {
20 if (e.surface !== 'desktop' || e.props.isSummary) {
21 return next(e)
22 }
23
24 const blocks = parseReply(e.props.text)
25 if (!blocks.some(b => b.kind !== 'markdown')) {
26 return next(e)
27 }
28
29 const { Box, Text, Markdown } = $.ui.resolve(e)
30
31 return (
32 <Box flexDirection="column" gap={1}>
33 {blocks.map((b, i) => {
34 switch (b.kind) {
35 case 'verdict':
36 return (
37 <Box key={`b${i}`} borderStyle="bold" borderColor={b.label === 'Decision' ? 'permission' : 'claude'} paddingX={1}>
38 <Text>
39 <Text bold color={b.label === 'Decision' ? 'permission' : 'claude'}>
40 {b.label.toUpperCase()}
41 </Text>
42 {` ${plain(b.text)}`}
43 </Text>
44 </Box>
45 )
46 case 'section':
47 return (
48 <Box key={`b${i}`} flexDirection="column">
49 <Text bold color="claude">
50 {b.label}
51 </Text>
52 {b.body.trim() === '' ? null : <Markdown text={b.body} />}
53 </Box>
54 )
55 case 'action':
56 return (
57 <Box key={`b${i}`} flexDirection="column" borderStyle="bold" borderColor="warning" paddingX={1}>
58 <Text bold color="warning">
59 ACTION NEEDED
60 </Text>
61 {b.body.trim() === '' ? null : <Markdown text={b.body} />}
62 </Box>
63 )
64 case 'markdown':
65 return <Markdown key={`b${i}`} text={b.text} />
66 }
67 })}
68 </Box>
69 )
70 })
71
72 on('ui.render', { component: 'UserMessage' }, async ($, e, next) => {
73 if (e.surface !== 'desktop' || !PROMPT_KINDS.has(e.props.origin.kind)) {
74 return next(e)
75 }
76
77 const { Box, Button, Text } = $.ui.resolve(e)
78 const open = memberOf(isPromptOpen, e)
79 const isOpen = await read($, open)
80 const collapsed = collapsePrompt(e.props.text)
81 const text = collapsed && !isOpen ? collapsed.head : e.props.text
82
83 return (
84 <Box flexDirection="row" justifyContent="flex-end" width="100%">
85 <Box
86 width={e.props.text.length > BUBBLE_WRAP_AT ? '70%' : undefined}
87 flexShrink={1}
88 backgroundColor={BUBBLE_GREEN}
89 borderStyle="round"
90 borderColor={BUBBLE_GREEN}
91 paddingX={2}
92 paddingY={1}
93 >
94 <Box flexDirection="column" gap={1}>
95 <Text color="#FFFFFF">{text}</Text>
96 {collapsed === null ? null : (
97 <Button
98 key="toggle"
99 label={isOpen ? 'Show less' : `Show all (${collapsed.hiddenLines} more lines)`}
100 onPress={() => update($, open, v => !v)}
101 />
102 )}
103 </Box>
104 </Box>
105 </Box>
106 )
107 })
108
109}
110hooks/parse.ts 105 lines1export type Block =
2 | { kind: 'verdict'; label: string; text: string }
3 | { kind: 'section'; label: string; body: string }
4 | { kind: 'action'; body: string }
5 | { kind: 'markdown'; text: string }
6
7const VERDICT = /^\*\*(Verdict|Decision):\*\*\s*/
8const LEAD_IN = /^\*\*([^*\n]{1,40})\*\*\s*$/
9const ACTION = /^\*\*Action needed:\*\*\s*/
10
11// Splits markdown into paragraphs, keeping fenced code (even unclosed while streaming) whole.
12export function paragraphs(text: string): string[] {
13 const out: string[] = []
14 let current: string[] = []
15 let inFence = false
16
17 for (const line of text.split('\n')) {
18 if (/^\s*(```|~~~)/.test(line)) {
19 inFence = !inFence
20 }
21 if (!inFence && line.trim() === '') {
22 if (current.length > 0) {
23 out.push(current.join('\n'))
24 current = []
25 }
26 continue
27 }
28 current.push(line)
29 }
30 if (current.length > 0) {
31 out.push(current.join('\n'))
32 }
33
34 return out
35}
36
37// Strips inline markdown marks for text drawn on a filled background.
38export function plain(text: string): string {
39 return text.replace(/\*\*([^*]+)\*\*/g, '$1').replace(/`([^`]+)`/g, '$1')
40}
41
42// Classifies a reply into styled blocks; plain paragraphs are merged so lists and tables stay intact.
43export function parseReply(text: string): Block[] {
44 const blocks: Block[] = []
45 const paras = paragraphs(text)
46
47 const pushMarkdown = (md: string) => {
48 const last = blocks[blocks.length - 1]
49 if (last?.kind === 'markdown') {
50 last.text += '\n\n' + md
51 } else {
52 blocks.push({ kind: 'markdown', text: md })
53 }
54 }
55
56 for (let i = 0; i < paras.length; i++) {
57 const p = paras[i]!
58
59 if (p.trim() === '---' && ACTION.test(paras[i + 1] ?? '')) {
60 continue
61 }
62 if (ACTION.test(p)) {
63 blocks.push({ kind: 'action', body: [p.replace(ACTION, ''), ...paras.slice(i + 1)].filter(s => s.trim() !== '').join('\n\n') })
64 break
65 }
66
67 const verdict = blocks.length === 0 ? VERDICT.exec(p) : null
68 if (verdict) {
69 blocks.push({ kind: 'verdict', label: verdict[1]!, text: p.slice(verdict[0].length) })
70 continue
71 }
72
73 const [first = '', ...rest] = p.split('\n')
74 const lead = LEAD_IN.exec(first)
75 if (lead) {
76 blocks.push({ kind: 'section', label: lead[1]!, body: rest.join('\n') })
77 continue
78 }
79
80 pushMarkdown(p)
81 }
82
83 return blocks
84}
85
86const PROMPT_MAX_LINES = 8
87const PROMPT_HEAD_LINES = 6
88const PROMPT_HEAD_CHARS = 600
89
90// The head of a long prompt and how many lines it hides, or null when it is short.
91export function collapsePrompt(text: string): { head: string; hiddenLines: number } | null {
92 const lines = text.split('\n')
93 if (lines.length <= PROMPT_MAX_LINES && text.length <= PROMPT_HEAD_CHARS) {
94 return null
95 }
96
97 let head = lines.slice(0, PROMPT_HEAD_LINES).join('\n')
98 if (head.length > PROMPT_HEAD_CHARS) {
99 head = head.slice(0, PROMPT_HEAD_CHARS)
100 }
101 const shownLines = head.split('\n').length
102
103 return { head: head + '…', hiddenLines: Math.max(1, lines.length - shownLines) }
104}
105types/index.d.ts 8 lines1export type PromptOpen = boolean
2
3declare module 'claude-code' {
4 interface PluginState {
5 'reply-style': { isPromptOpen: StateFamily<PromptOpen> }
6 }
7}
8