Token导航 LogoToken导航

Agent Skill · 研究检索

epic-routing(史诗般的路由)

epic-routing 用于查找、检索和筛选相关信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要根据关键词、任务场景或来源线索快速定位候选结果时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

epic-routing 是研究检索类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为需要联网;许可证为 MIT,第三方扫描已通过,按安装量在研究检索类的 73,675 个 Skill 里排第 56,650。

总安装 447周安装 19GitHub Stars 5,501下载 157核验 2026-05-01

安装说明

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

安装方式

通过对话安装

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

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

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/epicweb-dev/epic-stack --skill epic-routing

这个 Skill 是做什么的

研究检索类 Skill 主要解决「找资料、核对事实、把来源整理清楚」的问题,通常会让助手先检索再总结。

Epic Routing 基于文件系统设计轻量级路由结构,推荐从简单路径开始逐步增加嵌套复杂度。适合需要创建资源型路由(无 UI)、配置加载器/动作函数或理解参数传递机制的项目。新增路由前应评估实际需求,避免过度设计导致维护成本上升和导航混乱。

安装命令为 npx skills add https://github.com/epicweb-dev/epic-stack --skill epic-routing。处理动态参数时应做好输入清洗,防止注入攻击或路径遍历漏洞利用。

来源仓库内路径:skills/epic-routing

上手步骤

4 步
  1. 1

    确认自己的宿主工具

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

  2. 2

    拿到安装命令

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

  3. 3

    安装后重启宿主

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

  4. 4

    按最小权限试用

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

常见问题

6 条

epic-routing 怎么安装?

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

epic-routing 支持哪些 AI 工具?

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

epic-routing 需要什么权限?

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

epic-routing 是免费的吗?

来源标注的许可证是 MIT。本站不代收任何费用,也不托管安装包;能否商用、要不要署名,以许可证原文为准。

epic-routing 用的人多吗?

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

epic-routing 安全吗?

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

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

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 3 个目录同时收录,说明这个 Skill 流传比较广。
  • 许可证明确为 MIT,商用和分发边界好判断。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理研究检索类任务、又不想每次都手写提示词的人。
  • 需要许可证清楚、并且有第三方扫描结果的团队项目。

不太适合

  • 需要厂商级技术支持和 SLA 的生产系统。

研究检索类 Skill 对比

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

寻找技能 · Codex、Claude

31,199,81316,486操作浏览器MIT有提醒
self-improving-agent

自我改进 Agent · OpenClaw

16,464,0023,396接触敏感数据MIT-0通过
soultrace

灵魂追踪 · Codex、Claude

7,588,94412需要联网未明确有提醒
self-improving

自我完善 · OpenClaw

6,829,2841,046需要联网MIT-0通过
microsoft-foundry

微软代工厂 · Codex、Claude

6,614,144764调用外部服务未明确有提醒
epic-routing

史诗般的路由 · 本页

4475,501需要联网MIT通过

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

SKILL.md 原文

Epic Stack: Routing

When to use this skill

Use this skill when you need to:

  • Create new routes or pages in an Epic Stack application
  • Implement nested layouts
  • Configure resource routes (routes without UI)
  • Work with route parameters and search params
  • Understand Epic Stack's file-based routing conventions
  • Implement loaders and actions in routes

Patterns and conventions

Routing Philosophy

Following Epic Web principles:

Do as little as possible - Keep your route structure simple. Don't create complex nested routes unless you actually need them. Start simple and add complexity only when there's a clear benefit.

Avoid over-engineering - Don't create abstractions or complex route structures "just in case". Use the simplest structure that works for your current needs.

Example - Simple route structure:

// ✅ Good - Simple, straightforward route
// app/routes/users/$username.tsx
export async function loader({ params }: Route.LoaderArgs) {
	const user = await prisma.user.findUnique({
		where: { username: params.username },
		select: { id: true, username: true, name: true },
	})
	return { user }
}

export default function UserRoute({ loaderData }: Route.ComponentProps) {
	return <div>{loaderData.user.name}</div>
}

// ❌ Avoid - Over-engineered route structure
// app/routes/users/$username/_layout.tsx
// app/routes/users/$username/index.tsx
// app/routes/users/$username/_components/UserHeader.tsx
// app/routes/users/$username/_components/UserDetails.tsx
// Unnecessary complexity for a simple user page

Example - Add complexity only when needed:

// ✅ Good - Add nested routes only when you actually need them
// If you have user notes, then nested routes make sense:
// app/routes/users/$username/notes/_layout.tsx
// app/routes/users/$username/notes/index.tsx
// app/routes/users/$username/notes/$noteId.tsx

// ❌ Avoid - Creating nested routes "just in case"
// Don't create complex structures before you need them

File-based routing with react-router-auto-routes

Epic Stack uses react-router-auto-routes instead of React Router's standard convention. This enables better organization and code co-location.

Basic structure:

app/routes/
├── _layout.tsx        # Layout for child routes
├── index.tsx          # Root route (/)
├── about.tsx          # Route /about
└── users/
    ├── _layout.tsx    # Layout for user routes
    ├── index.tsx      # Route /users
    └── $username/
        └── index.tsx  # Route /users/:username

Configuration in app/routes.ts:

import { type RouteConfig } from '@react-router/dev/routes'
import { autoRoutes } from 'react-router-auto-routes'

export default autoRoutes({
	ignoredRouteFiles: [
		'.*',
		'**/*.css',
		'**/*.test.{js,jsx,ts,tsx}',
		'**/__*.*',
		'**/*.server.*', // Co-located server utilities
		'**/*.client.*', // Co-located client utilities
	],
}) satisfies RouteConfig

Route Groups

Route groups are folders that start with _ and don't affect the URL but help organize related code.

Common examples:

  • _auth/ - Authentication routes (login, signup, etc.)
  • _marketing/ - Marketing pages (home, about, etc.)
  • _seo/ - SEO routes (sitemap, robots.txt)

Example:

app/routes/
├── _auth/
│   ├── login.tsx          # URL: /login
│   ├── signup.tsx         # URL: /signup
│   └── forgot-password.tsx # URL: /forgot-password
└── _marketing/
    ├── index.tsx          # URL: /
    └── about.tsx          # URL: /about

Route Parameters

Use $ to indicate route parameters:

Syntax:

  • $param.tsx → :param in URL
  • $username.tsx → :username in URL

Example route with parameter:

// app/routes/users/$username/index.tsx
export async function loader({ params }: Route.LoaderArgs) {
	const username = params.username // Type-safe!

	const user = await prisma.user.findUnique({
		where: { username },
	})

	return { user }
}

Nested Layouts with _layout.tsx

Use _layout.tsx to create shared layouts for child routes.

Example:

// app/routes/users/$username/notes/_layout.tsx
export async function loader({ params }: Route.LoaderArgs) {
	const owner = await prisma.user.findFirst({
		where: { username: params.username },
	})
	return { owner }
}

export default function NotesLayout({ loaderData }: Route.ComponentProps) {
	return (
		<main className="container">
			<h1>{loaderData.owner.name}'s Notes</h1>
			<Outlet /> {/* Child routes render here */}
		</main>
	)
}

Child routes ($noteId.tsx, index.tsx, etc.) will render where <Outlet /> is.

Resource Routes (Routes without UI)

Resource routes don't render UI; they only return data or perform actions.

Characteristics:

  • Don't export a default component
  • Export loader or action or both
  • Useful for APIs, downloads, webhooks, etc.

Example:

// app/routes/resources/healthcheck.tsx
export async function loader({ request }: Route.LoaderArgs) {
	// Check application health
	const host =
		request.headers.get('X-Forwarded-Host') ?? request.headers.get('host')

	try {
		await Promise.all([
			prisma.user.count(), // Check DB
			fetch(`${new URL(request.url).protocol}${host}`, {
				method: 'HEAD',
				headers: { 'X-Healthcheck': 'true' },
			}),
		])
		return new Response('OK')
	} catch (error) {
		return new Response('ERROR', { status: 500 })
	}
}

Loaders and Actions

Loaders - Load data before rendering (GET requests) Actions - Handle data mutations (POST, PUT, DELETE)

Loader pattern:

export async function loader({ request, params }: Route.LoaderArgs) {
	const userId = await requireUserId(request)

	const data = await prisma.something.findMany({
		where: { userId },
	})

	return { data }
}

export default function RouteComponent({ loaderData }: Route.ComponentProps) {
	return <div>{/* Use loaderData.data */}</div>
}

Action pattern:

export async function action({ request }: Route.ActionArgs) {
	const userId = await requireUserId(request)
	const formData = await request.formData()

	// Validate and process data
	await prisma.something.create({
		data: { /* ... */ },
	})

	return redirect('/success')
}

export default function RouteComponent() {
	return (
		<Form method="POST">
			{/* Form fields */}
		</Form>
	)
}

Search Params

Access query parameters using useSearchParams:

import { useSearchParams } from 'react-router'

export default function SearchPage() {
	const [searchParams, setSearchParams] = useSearchParams()
	const query = searchParams.get('q') || ''
	const page = Number(searchParams.get('page') || '1')

	return (
		<div>
			<input
				value={query}
				onChange={(e) => setSearchParams({ q: e.target.value })}
			/>
			{/* Results */}
		</div>
	)
}

Code Co-location

Epic Stack encourages placing related code close to where it's used.

Typical structure:

app/routes/users/$username/notes/
├── _layout.tsx              # Layout with loader
├── index.tsx                # Notes list
├── $noteId.tsx              # Note view
├── $noteId_.edit.tsx        # Edit note
├── +shared/                 # Code shared between routes
│   └── note-editor.tsx      # Shared editor
└── $noteId.server.ts        # Server-side utilities

The + prefix indicates co-located modules that are not routes.

Naming Conventions

  • _layout.tsx - Layout for child routes
  • index.tsx - Root route of the segment
  • $param.tsx - Route parameter
  • $param_.action.tsx - Route with parameter + action (using _)
  • [.]ext.tsx - Resource route (e.g., robots[.]txt.ts)

Common examples

Example 1: Create a basic route with layout

// app/routes/products/_layout.tsx
export async function loader({ request }: Route.LoaderArgs) {
	const categories = await prisma.category.findMany()
	return { categories }
}

export default function ProductsLayout({ loaderData }: Route.ComponentProps) {
	return (
		<div>
			<nav>
				{loaderData.categories.map(cat => (
					<Link key={cat.id} to={`/products/${cat.slug}`}>
						{cat.name}
					</Link>
				))}
			</nav>
			<Outlet />
		</div>
	)
}

// app/routes/products/index.tsx
export default function ProductsIndex() {
	return <div>Products list</div>
}

Example 2: Route with dynamic parameter

// app/routes/products/$slug.tsx
export async function loader({ params }: Route.LoaderArgs) {
	const product = await prisma.product.findUnique({
		where: { slug: params.slug },
	})

	if (!product) {
		throw new Response('Not Found', { status: 404 })
	}

	return { product }
}

export default function ProductPage({ loaderData }: Route.ComponentProps) {
	return (
		<div>
			<h1>{loaderData.product.name}</h1>
			<p>{loaderData.product.description}</p>
		</div>
	)
}

export function ErrorBoundary() {
	return (
		<GeneralErrorBoundary
			statusHandlers={{
				404: ({ params }) => (
					<p>Product "{params.slug}" not found</p>
				),
			}}
		/>
	)
}

Example 3: Resource route for download

// app/routes/resources/download-report.tsx
export async function loader({ request }: Route.LoaderArgs) {
	const userId = await requireUserId(request)

	const report = await generateReport(userId)

	return new Response(report, {
		headers: {
			'Content-Type': 'application/pdf',
			'Content-Disposition': 'attachment; filename="report.pdf"',
		},
	})
}

Example 4: Route with multiple nested parameters

// app/routes/users/$username/posts/$postId/comments/$commentId.tsx
export async function loader({ params }: Route.LoaderArgs) {
	// params contains: { username, postId, commentId }
	const comment = await prisma.comment.findUnique({
		where: { id: params.commentId },
		include: {
			post: {
				include: { author: true },
			},
		},
	})

	return { comment }
}

Common mistakes to avoid

  • ❌ Over-engineering route structure: Keep routes simple - don't create complex nested structures unless you actually need them
  • ❌ Creating abstractions prematurely: Start with simple routes, add complexity only when there's a clear benefit
  • ❌ Using React Router's standard convention: Epic Stack uses react-router-auto-routes, not the standard convention
  • ❌ Exporting default component in resource routes: Resource routes should not export components
  • ❌ Not using nested layouts when needed: Use _layout.tsx when you have shared UI, but don't create layouts unnecessarily
  • ❌ Forgetting <Outlet /> in layouts: Without <Outlet />, child routes won't render
  • ❌ Using incorrect names for parameters: Should be $param.tsx, not :param.tsx or [param].tsx
  • ❌ Mixing route groups with URLs: Groups (_auth/) don't appear in the URL
  • ❌ Not validating params: Always validate that parameters exist before using them
  • ❌ Duplicating route logic: Use layouts and shared components, but only when it reduces duplication

References

平台分布

Claude Code

28.02%
按下载量换算44

Gemini CLI

22.2%
按下载量换算35

windsurf

16.57%
按下载量换算26

Cursor

13.04%
按下载量换算20

OpenCode

7.08%
按下载量换算11

Codex

3.03%
按下载量换算5

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

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

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。

继续浏览同类 Skills