Use when adding new error messages to React, or seeing "unknown error code" warnings.
npx skills add zonghui1968/clawd-skills --skill "claude-code-clawdbot"
Install specific skill from multi-skill repository
# Description
Run Claude Code (Anthropic) from this host via the `claude` CLI (Agent SDK) in headless mode (`-p`) for codebase analysis, refactors, test fixing, and structured output. Use when the user asks to use Claude Code, run `claude -p`, use Plan Mode, auto-approve tools with --allowedTools, generate JSON output, or integrate Claude Code into Clawdbot workflows/cron.
# SKILL.md
name: claude-code-clawdbot
description: "Run Claude Code (Anthropic) from this host via the claude CLI (Agent SDK) in headless mode (-p) for codebase analysis, refactors, test fixing, and structured output. Use when the user asks to use Claude Code, run claude -p, use Plan Mode, auto-approve tools with --allowedTools, generate JSON output, or integrate Claude Code into Clawdbot workflows/cron."
Claude Code (Clawdbot)
Use the locally installed Claude Code CLI reliably.
This skill supports two execution styles:
- Headless mode (non-interactive): best for normal prompts and structured output.
- Interactive mode (tmux): required for slash commands like /speckit.* (Spec Kit), which can hang or be killed when run via headless -p.
This skill is for driving the Claude Code CLI, not the Claude API directly.
Quick checks
Verify installation:
claude --version
Run a minimal headless prompt (prints a single response):
./scripts/claude_code_run.py -p "Return only the single word OK."
Core workflow
1) Run a headless prompt in a repo
cd /path/to/repo
/home/ubuntu/clawd/skills/claude-code-clawdbot/scripts/claude_code_run.py \
-p "Summarize this project and point me to the key modules." \
--permission-mode plan
2) Allow tools (auto-approve)
Claude Code supports tool allowlists via --allowedTools.
Example: allow read/edit + bash:
./scripts/claude_code_run.py \
-p "Run the test suite and fix any failures." \
--allowedTools "Bash,Read,Edit"
3) Get structured output
./scripts/claude_code_run.py \
-p "Summarize this repo in 5 bullets." \
--output-format json
4) Add extra system instructions
./scripts/claude_code_run.py \
-p "Review the staged diff for security issues." \
--append-system-prompt "You are a security engineer. Be strict." \
--allowedTools "Bash(git diff *),Bash(git status *),Read"
Notes (important)
- Claude Code sometimes expects a TTY.
- Headless: this wrapper uses
script(1)to force a pseudo-terminal. - Slash commands (e.g.
/speckit.*) are best run in interactive mode; this wrapper can start an interactive Claude Code session in tmux. - Use
--permission-mode planwhen you want read-only planning. - Keep
--allowedToolsnarrow (principle of least privilege), especially in automation.
High‑leverage Claude Code tips (from the official docs)
1) Always give Claude a way to verify (tests/build/screenshots)
Claude performs dramatically better when it can verify its work.
Make verification explicit in the prompt, e.g.:
- “Fix the bug and run tests. Done when npm test passes.”
- “Implement UI change, take a screenshot and compare to this reference.”
2) Explore → Plan → Implement (use Plan Mode)
For multi-step work, start in plan mode to do safe, read-only analysis:
./scripts/claude_code_run.py -p "Analyze and propose a plan" --permission-mode plan
Then switch to execution (acceptEdits) once the plan is approved.
3) Manage context aggressively: /clear and /compact
Long, mixed-topic sessions degrade quality.
- Use /clear between unrelated tasks.
- Use /compact Focus on <X> when nearing limits to preserve the right details.
4) Rewind aggressively: /rewind (checkpoints)
Claude checkpoints before changes.
If an approach is wrong, use /rewind (or Esc Esc) to restore:
- conversation only
- code only
- both
This enables “try something risky → rewind if wrong” loops.
5) Prefer CLAUDE.md for durable rules; keep it short
Best practice is a concise CLAUDE.md (global or per-project) for:
- build/test commands Claude should use
- repo etiquette / style rules that differ from defaults
- non-obvious environment quirks
Overlong CLAUDE.md files get ignored.
6) Permissions: deny > ask > allow (and scope matters)
In .claude/settings.json / ~/.claude/settings.json, rules match in order:
deny first, then ask, then allow.
Use deny rules to block secrets (e.g. .env, secrets/**).
7) Bash env vars don’t persist; use CLAUDE_ENV_FILE for persistence
Each Bash tool call runs in a fresh shell; export FOO=bar won’t persist.
If you need persistent env setup, set (before starting Claude Code):
export CLAUDE_ENV_FILE=/path/to/env-setup.sh
Claude will source it before each Bash command.
8) Hooks beat “please remember” instructions
Use hooks to enforce deterministic actions (format-on-edit, block writes to sensitive dirs, etc.)
when you need guarantees.
9) Use subagents for heavy investigation / independent review
Subagents can read many files without polluting the main context.
Use them for broad codebase research or post-implementation review.
10) Treat Claude as a Unix utility (headless, pipes, structured output)
Examples:
cat build-error.txt | claude -p "Explain root cause"
claude -p "List endpoints" --output-format json
This is ideal for CI and automation.
Interactive mode (tmux)
If your prompt contains lines starting with / (slash commands), the wrapper defaults to auto → interactive.
Example:
./scripts/claude_code_run.py \
--mode auto \
--permission-mode acceptEdits \
--allowedTools "Bash,Read,Edit,Write" \
-p $'/speckit.constitution ...\n/speckit.specify ...\n/speckit.plan ...\n/speckit.tasks\n/speckit.implement'
It will print tmux attach/capture commands so you can monitor progress.
Spec Kit end-to-end workflow (tips that prevent hangs)
When you want Claude Code to drive Spec Kit end-to-end via /speckit.*, do not use headless -p for the whole flow.
Use interactive tmux mode because:
- Spec Kit runs multiple steps (Bash + file writes + git) and may pause for confirmations.
- Headless runs can appear idle and be killed (SIGKILL) by supervisors.
Prerequisites (important)
1) Initialize Spec Kit (once per repo)
specify init . --ai claude
2) Ensure the folder is a real git repo (Spec Kit uses git branches/scripts):
git init
git add -A
git commit -m "chore: init"
3) Recommended: set an origin remote (can be a local bare repo) so git fetch --all --prune won’t behave oddly:
git init --bare ../origin.git
git remote add origin ../origin.git
git push -u origin main || git push -u origin master
4) Give Claude Code enough tool permissions for the workflow:
- Spec creation/tasks/implement need file writes, so include Write.
- Implementation often needs Bash.
Recommended:
--permission-mode acceptEdits --allowedTools "Bash,Read,Edit,Write"
Run the full Spec Kit pipeline
./scripts/claude_code_run.py \
--mode interactive \
--tmux-session cc-speckit \
--permission-mode acceptEdits \
--allowedTools "Bash,Read,Edit,Write" \
-p $'/speckit.constitution Create project principles for quality, accessibility, and security.\n/speckit.specify <your feature description>\n/speckit.plan I am building with <your stack/constraints>\n/speckit.tasks\n/speckit.implement'
Monitoring / interacting
The wrapper prints commands like:
- tmux ... attach -t <session> to watch in real time
- tmux ... capture-pane ... to snapshot output
If Claude Code asks a question mid-run (e.g., “Proceed?”), attach and answer.
Operational gotchas (learned in practice)
1) Vite + ngrok: "Blocked request. This host (...) is not allowed"
If you expose a Vite dev server through ngrok, Vite will block unknown Host headers unless configured.
- Vite 7 expects
server.allowedHoststo betrueorstring[]. - ✅ Allow all hosts (quick):
ts server: { host: true, allowedHosts: true } - ✅ Allow just your ngrok host (safer):
ts server: { host: true, allowedHosts: ['xxxx.ngrok-free.app'] } - ❌ Do not set
allowedHosts: 'all'(won't work in Vite 7).
After changing vite.config.*, restart the dev server.
2) Don’t accidentally let your shell eat your prompt
When you drive tmux via a shell command (e.g. tmux send-keys ...), avoid unescaped backticks and shell substitutions in the text you pass.
They can be interpreted by your shell before the text even reaches Claude Code.
Practical rule:
- Prefer sending prompts from a file, or ensure the wrapper/script quotes prompt text safely.
3) Long-running dev servers should run in a persistent session
In automation environments, backgrounded vite / ngrok processes can get SIGKILL.
Prefer running them in a managed background session (Clawdbot exec background) or tmux, and explicitly stop them when done.
OpenSpec workflow (opsx)
OpenSpec is another spec-driven workflow (like Spec Kit) powered by slash commands (e.g. /opsx:*).
In practice it has the same reliability constraints:
- Prefer interactive tmux mode for /opsx:* commands (avoid headless -p for the whole flow).
Setup (per machine)
Install CLI:
npm install -g @fission-ai/openspec@latest
Setup (per project)
Initialize OpenSpec with tool selection (required):
openspec init --tools claude
Tip: disable telemetry if desired:
export OPENSPEC_TELEMETRY=0
Recommended end-to-end command sequence
Inside Claude Code (interactive):
1) /opsx:onboard
2) /opsx:new <change-name>
3) /opsx:ff (fast-forward: generates proposal/design/specs/tasks)
4) /opsx:apply (implements tasks)
5) /opsx:archive (optional: archive finished change)
If the UI prompts you for project type/stack, answer explicitly (e.g. “Web app (HTML/JS) with localStorage”).
Bundled script
scripts/claude_code_run.py: wrapper that runs the localclaudebinary with a pseudo-terminal and forwards flags.
React + TypeScript 项目开发实战经验
这些经验来自于实际开发中遇到的问题和解决方案,可作为快速参考。
1. 常见 React Hooks 导入问题
问题症状:
- 页面完全空白
- 浏览器控制台报错:ReferenceError: useState is not defined
- Vite HMR 无法正常更新
根本原因:
使用了 React hooks(如 useState, useEffect, useReducer)但忘记从 react 导入。
快速修复:
// ❌ 错误
import { useEffect } from 'react';
function App() {
const [state, setState] = useState(null); // ReferenceError
// ...
}
// ✅ 正确
import { useEffect, useState } from 'react';
function App() {
const [state, setState] = useState(null); // 正常工作
// ...
}
预防措施:
1. 使用 TypeScript 时,类型检查会提示未定义的变量
2. 配置 ESLint 规则检测未导入的 hooks
3. 使用 IDE 的自动导入功能
2. Vite 开发服务器常见问题
问题:Vite HMR 不生效
症状:修改代码后浏览器没有自动更新,需要手动刷新。
解决方案:
1. 检查 vite.config.ts 配置是否正确
2. 确保没有禁用 HMR
3. 检查浏览器控制台是否有 WebSocket 连接错误
4. 尝试重启开发服务器
问题:Vite + ngrok "Blocked request" 错误
症状:
Blocked request. This host (xxxx.ngrok-free.app) is not allowed
解决方案(Vite 7+):
// vite.config.ts
export default defineConfig({
server: {
host: true, // 监听所有网络接口
allowedHosts: true, // 允许所有主机(快速方案)
// 或更安全的方式:
// allowedHosts: ['xxxx.ngrok-free.app']
}
})
注意:
- ❌ allowedHosts: 'all' 在 Vite 7 中不起作用
- ✅ 使用 true 或字符串数组
问题:开发服务器端口被占用
症状:
Error: Port 3000 is already in use
解决方案:
# 方案 1: 使用其他端口
npm run dev -- --port 3001
# 方案 2: 杀死占用端口的进程
# Windows
netstat -ano | findstr :3000
taskkill /PID <进程ID> /F
# macOS/Linux
lsof -ti:3000 | xargs kill -9
3. React 项目状态管理最佳实践
简单状态:使用 useState
function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
复杂状态:使用 useReducer
适用于有多个相关操作的状态管理。
type Action =
| { type: 'ADD_ITEM'; payload: Item }
| { type: 'REMOVE_ITEM'; payload: string }
| { type: 'UPDATE_ITEM'; payload: { id: string; item: Partial<Item> } };
function reducer(state: State, action: Action): State {
switch (action.type) {
case 'ADD_ITEM':
return { ...state, items: [...state.items, action.payload] };
case 'REMOVE_ITEM':
return { ...state, items: state.items.filter(i => i.id !== action.payload) };
case 'UPDATE_ITEM':
return {
...state,
items: state.items.map(i =>
i.id === action.payload.id ? { ...i, ...action.payload.item } : i
),
};
default:
return state;
}
}
function App() {
const [state, dispatch] = useReducer(reducer, initialState);
// ...
}
何时使用 useReducer:
- 状态逻辑复杂,有多个子值
- 下一个状态依赖于前一个状态
- 需要为复杂状态编写可测试的 reducer 函数
4. API 集成最佳实践
使用免费 API 代替需要 Key 的服务
案例:私人日记项目的天气集成
原始方案(OpenWeatherMap):
- ❌ 需要用户手动输入 API Key
- ❌ 有请求限制
- ❌ 可能需要付费
优化方案(Open-Meteo):
- ✅ 完全免费
- ✅ 不需要 API Key
- ✅ 无请求限制
- ✅ 支持全球位置
// 使用 Open-Meteo 获取天气
async function getWeather(lat: string, lon: string) {
const response = await fetch(
`https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lon}¤t_weather=true`
);
const data = await response.json();
return data.current_weather;
}
推荐免费 API:
- 天气:Open-Meteo, wttr.in
- 图片:Unsplash, Pexels
- 地图:Leaflet + OpenStreetMap
- 文本:本地 LLM(Ollama)
API 缓存策略
减少 API 调用,提升性能:
const CACHE_DURATION = 60 * 60 * 1000; // 1 小时
export async function getWeatherWithCache(date: string) {
const cacheKey = `weather_${date}`;
const cached = localStorage.getItem(cacheKey);
if (cached) {
const { data, timestamp } = JSON.parse(cached);
if (Date.now() - timestamp < CACHE_DURATION) {
return data; // 返回缓存数据
}
}
const data = await fetchWeatherFromAPI();
localStorage.setItem(cacheKey, JSON.stringify({
data,
timestamp: Date.now(),
}));
return data;
}
5. LocalStorage 使用注意事项
数据容量限制
LocalStorage 通常限制在 5-10MB。
最佳实践:
1. 压缩大型数据(JSON + gzip)
2. 分片存储(多个键)
3. 使用 IndexedDB 存储大量数据
// 检查容量
function checkStorageSpace() {
const test = 'x'.repeat(1024 * 1024); // 1MB
try {
localStorage.setItem('test', test);
localStorage.removeItem('test');
return true;
} catch (e) {
console.error('Storage limit exceeded');
return false;
}
}
数据序列化
LocalStorage 只能存储字符串:
// ✅ 正确:存储前序列化,读取后解析
const entries = [{ id: 1, title: 'Test' }];
localStorage.setItem('entries', JSON.stringify(entries));
const loaded = JSON.parse(localStorage.getItem('entries') || '[]');
// ❌ 错误:直接存储对象
localStorage.setItem('entries', entries); // 存储为 "[object Object]"
错误处理
LocalStorage 可能被禁用(隐私模式):
function safeSetItem(key: string, value: string) {
try {
localStorage.setItem(key, value);
return true;
} catch (e) {
console.error('LocalStorage access failed:', e);
alert('无法保存数据,请检查浏览器设置');
return false;
}
}
6. Tailwind CSS 响应式设计
移动优先策略
<div className="
// 手机(默认)
p-4 text-sm
// 平板(≥768px)
md:p-6 md:text-base
// 桌面(≥1024px)
lg:p-8 lg:text-lg
">
响应式内容
</div>
深色模式
配置(tailwind.config.js):
module.exports = {
darkMode: 'class', // 使用 class 策略
// ...
};
使用:
function App() {
const [darkMode, setDarkMode] = useState(false);
useEffect(() => {
if (darkMode) {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
}, [darkMode]);
return (
<div className={darkMode ? 'dark bg-gray-900 text-white' : 'bg-white text-gray-900'}>
<button onClick={() => setDarkMode(!darkMode)}>
{darkMode ? '🌙' : '☀️'}
</button>
</div>
);
}
7. TypeScript 类型定义最佳实践
定义清晰的接口
// ✅ 好:明确的类型定义
interface DiaryEntry {
id: string;
date: string; // ISO 格式 YYYY-MM-DD
content: string;
mood?: 'happy' | 'neutral' | 'sad' | 'excited' | 'thoughtful';
tags: string[];
isMemory: boolean;
weather?: WeatherData;
createdAt: string; // ISO timestamp
updatedAt: string;
}
interface WeatherData {
temp: number;
description: string;
icon: string;
humidity: number;
windSpeed: number;
}
类型守卫
function isDiaryEntry(obj: unknown): obj is DiaryEntry {
return (
typeof obj === 'object' &&
obj !== null &&
'id' in obj &&
'content' in obj &&
'date' in obj
);
}
8. 项目初始化检查清单
使用 Claude Code + Spec Kit 开发 React 项目时,确保:
文件结构
project/
├── src/
│ ├── components/ # 可复用组件
│ ├── services/ # 外部服务(API)
│ ├── utils/ # 工具函数
│ ├── types/ # TypeScript 类型
│ ├── App.tsx # 主应用
│ ├── main.tsx # 入口
│ └── index.css # 全局样式
├── package.json
├── tsconfig.json
├── vite.config.ts
└── tailwind.config.js
依赖检查
{
"dependencies": {
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
"devDependencies": {
"@types/react": "^18.0.0",
"@types/react-dom": "^18.0.0",
"@vitejs/plugin-react": "^4.0.0",
"typescript": "^5.0.0",
"vite": "^5.0.0",
"tailwindcss": "^3.0.0",
"postcss": "^8.0.0",
"autoprefixer": "^10.0.0"
}
}
配置检查
tsconfig.json:
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }]
}
vite.config.ts:
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
server: {
host: true,
port: 3000,
allowedHosts: true,
},
});
9. 实战案例:私人日记项目
使用 Spec Kit + Claude Code 完整工作流
步骤 1:初始化项目
cd /path/to/project
specify init . --ai claude
git init
git add -A
git commit -m "chore: init"
步骤 2:运行 Spec Kit
./scripts/claude_code_run.py \
--mode interactive \
--tmux-session diary-speckit \
--permission-mode acceptEdits \
--allowedTools "Bash,Read,Edit,Write" \
-p $'/speckit.constitution ...\n/speckit.specify ...\n/speckit.plan ...\n/speckit.tasks\n/speckit.implement'
步骤 3:常见问题修复
问题 1:React hooks 未导入
症状:页面空白,控制台报错
修复:
// 在 App.tsx 顶部添加
import { useEffect, useReducer, useState } from 'react';
问题 2:天气 API 需要 Key
症状:需要用户手动配置才能使用
优化:改用 Open-Meteo 免费服务
// 原来:需要 API Key
const response = await fetch(
`https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${apiKey}`
);
// 优化后:不需要 Key
const response = await fetch(
`https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lon}¤t_weather=true`
);
问题 3:类型定义不完整
症状:TypeScript 报错缺少属性
修复:
// 更新类型定义,移除不再需要的字段
export interface DiaryState {
entries: DiaryEntry[];
selectedDate: string;
searchQuery: string;
showMemoriesOnly: boolean;
darkMode: boolean;
// 移除 weatherApiKey
}
项目运行检查
# 1. 安装依赖
npm install
# 2. 启动开发服务器
npm run dev
# 3. 访问 http://localhost:3000
# 4. 检查控制台是否有错误
# 5. 测试功能
# - 创建日记
# - 查看天气
# - 切换深色模式
# - 搜索功能
10. 调试技巧
浏览器开发者工具
控制台错误:
- 按 F12 打开开发者工具
- 查看 Console 标签页的红色错误
- 常见错误:
- ReferenceError: 变量未定义
- TypeError: 类型错误(如 .map 用于非数组)
- SyntaxError: 语法错误
网络请求:
- Network 标签页查看 API 请求
- 检查状态码(200, 404, 500)
- 查看 Response 数据格式
React DevTools:
- 安装 React Developer Tools 浏览器扩展
- 查看组件树和状态
- 调试 props 和 hooks
Vite 日志
# 启动时检查警告
npm run dev
# 常见警告:
# - "! Some chunks are larger than 500kB"
# 解决:代码分割(lazy loading)
# - "Circular dependency"
# 解决:重构代码结构
TypeScript 类型检查
# 运行类型检查
npx tsc --noEmit
# 修复所有类型错误后再提交
11. Git 工作流
提交前检查
# 1. 查看修改
git status
# 2. 检查差异
git diff
# 3. 运行测试
npm test
# 4. 类型检查
npx tsc --noEmit
# 5. 提交
git add .
git commit -m "feat: add feature description"
提交消息规范(Conventional Commits)
feat: add weather widget with Open-Meteo API
fix: resolve useState import error
docs: update README with setup instructions
style: format code with Prettier
refactor: simplify reducer logic
test: add unit tests for storage utils
chore: update dependencies
总结
这些实战经验涵盖了:
- ✅ React 常见问题(hooks 导入、状态管理)
- ✅ Vite 配置(HMR、ngrok 兼容)
- ✅ API 集成(免费服务、缓存策略)
- ✅ LocalStorage 最佳实践(容量限制、错误处理)
- ✅ TypeScript 类型定义
- ✅ 响应式设计和深色模式
- ✅ 完整项目开发流程(Spec Kit + Claude Code)
- ✅ 调试技巧和 Git 工作流
在开发 React + TypeScript 项目时,参考这些经验可以快速定位和解决问题。
# Supported AI Coding Agents
This skill is compatible with the SKILL.md standard and works with all major AI coding agents:
Learn more about the SKILL.md standard and how to use these skills with your preferred AI coding agent.