Token导航 LogoToken导航

Agent Skill · 开发

spoosh-react(spoosh React 开发)

用于辅助前端页面、组件、样式和交互逻辑的开发与维护。它适合让 Agent 生成或审查 React、Next.js、Vue、Tailwind、CSS 等相关代码,整理组件结构,或定位布局和性能问题。使用时需要结合项目现有设计系统、路由和构建方式,避免只生成孤立片段;涉及页面改动时,应配合本地预览和构建检查确认视觉效果。

spoosh-react 是开发类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为需要联网;许可证信息还不明确,第三方扫描已通过,按安装量在开发类的 21,746 个 Skill 里排第 18,535。

总安装 329周安装 14GitHub Stars 公开资料未说明下载 115核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:spoosh-react(spoosh React 开发)
来源仓库:https://github.com/spooshdev/skills
仓库路径:skills/spoosh-react
安装命令:
npx skills add https://github.com/spooshdev/skills --skill spoosh-react
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/spooshdev/skills --skill spoosh-react

这个 Skill 是做什么的

开发类 Skill 面向写代码、改代码和排查问题,一般会读写仓库文件,部分还会执行构建或测试命令。

spoosh-react 用于辅助 React、Next.js 等前端框架的开发与维护,支持组件和样式生成。适用于页面布局、交互逻辑和性能问题排查等场景。通过 npx skills add 命令从 GitHub 仓库安装并调用。需结合项目现有设计系统和构建方式使用,避免生成孤立片段。

涉及页面改动时应配合本地预览确认视觉效果。

来源仓库内路径:skills/spoosh-react

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/spooshdev/skills --skill spoosh-react;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要需要联网,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

spoosh-react 怎么安装?

在终端执行 npx skills add https://github.com/spooshdev/skills --skill spoosh-react。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

spoosh-react 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

spoosh-react 需要什么权限?

权限级别是需要联网。该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

spoosh-react 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

spoosh-react 用的人多吗?

公开数据是累计安装 329 次,近一周安装 14 次,下载 115 次。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

spoosh-react 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理开发类任务、又不想每次都手写提示词的人。

不太适合

  • 需要明确授权才能用到公司项目里的场景。
  • 需要厂商级技术支持和 SLA 的生产系统。

开发类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
skill-vetter

技能审查员 · OpenClaw

8,779,018986操作浏览器MIT-0通过
ontology

本体论 · OpenClaw

6,636,960576只读MIT-0通过
entra-app-registration

内部应用程序注册 · Codex、Claude

6,631,872764接触敏感数据未明确通过
entra-app-registration

内部应用程序注册 · Codex、Claude

3,757,680201接触敏感数据未明确通过
nano-banana-pro

纳米香蕉专业版 · OpenClaw

3,526,898364接触敏感数据MIT-0有提醒
spoosh-react

spoosh React 开发 · 本页

329—需要联网未明确通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

Spoosh React

Spoosh is a type-safe API toolkit with a composable plugin architecture for TypeScript. This skill covers the React integration including hooks API, plugins, and component patterns.

Setup

pnpm add @spoosh/core @spoosh/react
import { Spoosh } from "@spoosh/core";
import { create } from "@spoosh/react";

type ApiSchema = {
  users: {
    GET: { data: User[] };
    POST: { data: User; body: CreateUserBody };
  };
  "users/:id": {
    GET: { data: User };
    DELETE: { data: void };
  };
};

const spoosh = new Spoosh<ApiSchema, Error>("/api").use([
  cachePlugin(),
  retryPlugin(),
]);

export const { useRead, useWrite, usePages, useQueue, useSSE } = create(spoosh);

createClient (Lightweight)

For simple use cases without hooks or plugins:

import { createClient } from "@spoosh/core";

const api = createClient<ApiSchema, Error>("/api");

const { data, error } = await api("users").GET();
const { data: user } = await api("users/:id").GET({ params: { id: "123" } });
await api("users").POST({ body: { name: "John" } });

Hooks API

useRead

Fetch data with automatic caching and state management.

const { data, loading, error, trigger } = useRead((api) => api("users").GET(), {
  staleTime: 30000,
  enabled: true,
});

Returns: data, loading, fetching, error, trigger(), abort(), meta

Options: enabled, tags, staleTime, retry, pollingInterval, refetch, debounce, transform, initialData

useWrite

Perform mutations (POST, PUT, DELETE).

const { trigger, loading, error } = useWrite((api) => api("users").POST());

// Invalidation is AUTOMATIC - no need to specify in most cases!
await trigger({ body: { name, email } });

Returns: trigger(), loading, error, data, meta, abort()

Trigger options: body, params, query, headers, invalidate, clearCache, optimistic

usePages

Bidirectional pagination with infinite scroll.

const { data, fetchNext, canFetchNext, loading } = usePages(
  (api) => api("posts").GET({ query: { page: 1 } }),
  {
    canFetchNext: ({ lastPage }) => lastPage?.data?.hasMore ?? false,
    nextPageRequest: ({ lastPage, request }) => ({
      query: { ...request.query, page: (lastPage?.data?.page ?? 0) + 1 },
    }),
    merger: (pages) => pages.flatMap((p) => p.data?.items ?? []),
  }
);

Returns: data, pages, loading, fetchingNext, canFetchNext, fetchNext(), fetchPrev(), trigger()

useQueue

Queue management for batch operations with concurrency control.

const { tasks, stats, trigger, retry } = useQueue(
  (api) => api("files").POST(),
  { concurrency: 3 }
);

files.forEach((file) => trigger({ body: form({ file }) }));

Returns: tasks, stats, trigger(), abort(), retry(), remove(), removeSettled(), clear(), setConcurrency()

Stats: pending, loading, settled, success, failed, total, percentage

useSSE

Server-Sent Events for real-time streaming.

const { data, isConnected, trigger, disconnect } = useSSE(
  (api) => api("stream").GET(),
  { parse: "json", accumulate: "replace" }
);

Returns: data, error, isConnected, loading, trigger(), disconnect(), reset()

Options: enabled, parse (auto|json|text|json-done), accumulate (replace|merge), maxRetries, retryDelay

Plugins

PluginPurposeKey Options
cachePluginResponse cachingstaleTime
retryPluginAutomatic retriesretry: {retries, delay}
pollingPluginAuto-refreshpollingInterval
invalidationPluginCache invalidationinvalidate
optimisticPluginInstant UI updatesoptimistic
debouncePluginDebounce requestsdebounce
refetchPluginRefetch on focusrefetch: {onFocus, onReconnect}
initialDataPluginPreloaded datainitialData
devtoolVisual debugging panelenabled, showFloatingIcon

Devtool

import { devtool } from "@spoosh/devtool";

const spoosh = new Spoosh<ApiSchema, Error>("/api").use([
  cachePlugin(),
  devtool({ enabled: process.env.NODE_ENV === "development" }),
]);

Features: request tracing, plugin visualization, cache inspector, timeline view.

Cache Invalidation

IMPORTANT: Tags and invalidation are handled automatically! You rarely need to configure them manually.

  • Tags: Auto-generated from the resolved URL path (e.g., api("users/:id").GET({params: {id: 123}}) → tag: "users/123")
  • Invalidation: After mutations, automatically invalidates [firstSegment, firstSegment/*] pattern
// ✅ RECOMMENDED: Let Spoosh handle it automatically
await trigger({ body: data });
// POST users/123 → auto-invalidates ["users", "users/*"]

// Only override when you need specific behavior:
await trigger({ body: data, invalidate: "posts" }); // Exact match only
await trigger({ body: data, invalidate: "posts/*" }); // Children only
await trigger({ body: data, invalidate: ["posts", "users"] }); // Multiple patterns
await trigger({ body: data, invalidate: false }); // Disable invalidation
await trigger({ body: data, invalidate: "*" }); // Global refetch all

Custom tags on queries (when auto-generated tag doesn't fit your needs):

// Custom tag only - replaces auto-generated tag
const { data } = useRead((api) => api("users").GET(), {
  tags: "dashboard-users",
});

// Default path + custom tags (recommended for cross-cutting concerns)
const { data } = useRead((api) => api("stats").GET(), {
  tags: ["stats", "sidebar-stats"], // Keep "stats" for auto-invalidation + add custom
});

// Then invalidate by either:
await trigger({ body: data, invalidate: "stats" }); // Path-based (auto works)
await trigger({ body: data, invalidate: "sidebar-stats" }); // Custom tag

Groups config for namespaced APIs (e.g., admin/posts, api/v1/users):

invalidationPlugin({
  groups: ["admin", "api/v1"], // These prefixes use deeper segment matching
});
// POST admin/posts → invalidates ["admin/posts", "admin/posts/*"] instead of ["admin", "admin/*"]

Component Patterns

Data Fetching

export function UserList() {
  const { data, loading, error, trigger } = useRead(
    (api) => api("users").GET(),
    { staleTime: 30000 }
  );

  if (loading) return <UserListSkeleton />;
  if (error) return <ErrorMessage error={error} onRetry={trigger} />;
  if (!data?.length) return <EmptyState message="No users found" />;

  return (
    <ul>
      {data.map((user) => <UserCard key={user.id} user={user} />)}
    </ul>
  );
}

Mutation Form

export function CreateUserForm() {
  const [name, setName] = useState("");
  const { trigger, loading, error } = useWrite((api) => api("users").POST());

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    // No need to specify invalidate - it's automatic!
    const result = await trigger({ body: { name } });
    if (result.data) setName("");
  };

  return (
    <form onSubmit={handleSubmit}>
      <input value={name} onChange={(e) => setName(e.target.value)} disabled={loading} />
      {error && <p className="error">{error.message}</p>}
      <button disabled={loading}>{loading ? "Creating..." : "Create"}</button>
    </form>
  );
}

Infinite Scroll

export function InfinitePostList() {
  const { ref, inView } = useInView();
  const { data, loading, fetchingNext, canFetchNext, fetchNext } = usePages(
    (api) => api("posts").GET({ query: { page: 1, limit: 20 } }),
    {
      canFetchNext: ({ lastPage }) => lastPage?.data?.hasMore ?? false,
      nextPageRequest: ({ lastPage, request }) => ({
        query: { ...request.query, page: (lastPage?.data?.page ?? 0) + 1 }
      }),
      merger: (pages) => pages.flatMap((p) => p.data?.items ?? [])
    }
  );

  useEffect(() => {
    if (inView && canFetchNext && !fetchingNext) fetchNext();
  }, [inView, canFetchNext, fetchingNext]);

  if (loading) return <PostListSkeleton />;

  return (
    <div>
      {data?.map((post) => <PostCard key={post.id} post={post} />)}
      <div ref={ref}>{fetchingNext && <LoadingSpinner />}</div>
    </div>
  );
}

Optimistic Updates

export function ToggleLikeButton({ postId, liked, likeCount }: Props) {
  const { trigger } = useWrite((api) => api("posts/:id/like").POST());

  const handleToggle = () => {
    trigger({
      params: { id: postId },
      optimistic: (cache) => cache(`posts/${postId}`)
        .set((current) => ({
          ...current,
          liked: !liked,
          likeCount: liked ? likeCount - 1 : likeCount + 1
        }))
    });
  };

  return <button onClick={handleToggle}>{liked ? "Unlike" : "Like"} ({likeCount})</button>;
}

Search with Debounce

export function SearchUsers() {
  const [query, setQuery] = useState("");
  const { data, fetching } = useRead(
    (api) => api("users/search").GET({ query: { q: query } }),
    { enabled: query.length >= 2, debounce: 300 }
  );

  return (
    <div>
      <input value={query} onChange={(e) => setQuery(e.target.value)} placeholder="Search..." />
      {fetching && <LoadingIndicator />}
      {data?.map((user) => <li key={user.id}>{user.name}</li>)}
    </div>
  );
}

Polling

export function JobStatus({ jobId }: { jobId: string }) {
  const { data } = useRead(
    (api) => api("jobs/:id").GET({ params: { id: jobId } }),
    {
      pollingInterval: ({ data }) => {
        if (data?.status === "completed" || data?.status === "failed") return false;
        return 2000;
      }
    }
  );

  return <p>Status: {data?.status}</p>;
}

Next.js

Server-side fetch with createClient

// app/posts/page.tsx
import { createClient } from "@spoosh/core";

const api = createClient<ApiSchema, Error>(process.env.API_URL!);

export default async function PostsPage() {
  const { data: posts } = await api("posts").GET();
  return <PostList initialData={posts} />;
}

Client with initialData

// components/PostList.tsx
"use client";

export function PostList({ initialData }: { initialData: Post[] }) {
  const { data, loading } = useRead(
    (api) => api("posts").GET(),
    { initialData }  // No loading state on first render
  );

  return data?.map((post) => <PostCard key={post.id} post={post} />);
}

Mutation with server revalidation

// lib/spoosh.ts
import { nextjsPlugin } from "@spoosh/plugin-nextjs";

const spoosh = new Spoosh<ApiSchema, Error>("/api").use([
  cachePlugin(),
  invalidationPlugin(),
  nextjsPlugin(),
]);
// After mutation, Next.js cache tags are automatically revalidated
// No need to specify invalidate - it's automatic!
await trigger({ body: newPost });

Server Type Inference

Hono

import { Spoosh, StripPrefix } from "@spoosh/core";
import type { HonoToSpoosh } from "@spoosh/hono";

// Server: app.basePath("/api")
type FullSchema = HonoToSpoosh<typeof app>;
type ApiSchema = StripPrefix<FullSchema, "api">; // Avoid double /api/api

const spoosh = new Spoosh<ApiSchema, Error>("/api");

Elysia

import { Spoosh, StripPrefix } from "@spoosh/core";
import type { ElysiaToSpoosh } from "@spoosh/elysia";

// Server: new Elysia({ prefix: "/api" })
type FullSchema = ElysiaToSpoosh<typeof app>;
type ApiSchema = StripPrefix<FullSchema, "api">; // Avoid double /api/api

const spoosh = new Spoosh<ApiSchema, Error>("/api");

Use StripPrefix when your baseUrl includes the same prefix as the server's basePath to prevent double prefixing (e.g., /api/api/users).

OpenAPI

# Export TypeScript → OpenAPI
npx spoosh-openapi export --schema ./schema.ts --output openapi.json

# Import OpenAPI → TypeScript
npx spoosh-openapi import openapi.json --output ./schema.ts

References

For detailed API documentation:

  • references/hooks-api.md - Complete hook signatures
  • references/plugins-api.md - All plugin configurations
  • references/advanced-patterns.md - Complex patterns and edge cases

If more detail needed, fetch https://spoosh.dev/docs/react/llms (or /llms-full for complete docs).

平台分布

Codex

35.68%
按下载量换算41

Claude

31.52%
按下载量换算36

Cursor

18.89%
按下载量换算22

Gemini CLI

10.91%
按下载量换算13

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills