Token导航 LogoToken导航TokenDH.com
前端设计需要联网github未标认证来源可访问许可证需确认审计通过

create-ryos-app创建 ryos 应用程序

Agent Skill

create-ryos-app 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

546

周安装

23

GitHub Stars

1,129

下载量

191
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

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

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

命令行安装

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

skills.shnpx skills
npx skills add https://github.com/ryokun6/ryos --skill create-ryos-app

简介

创建 ryOS 应用程序组件和菜单栏结构。

  • 适用于嵌入式系统或受限环境应用开发。create-ryos-app 属于前端设计类 Skill,可作为该场景下的辅助能力补充。
  • 包含组件、钩子、注册表和国际化支持。
  • 安装需确认 src/apps/ 目录和 appRegistry.tsx 配置。
  • 最后一步需使用 localize 技能同步翻译键值对。

SKILL.md

Creating ryOS Applications

Quick Start Checklist

- [ ] 1. Create app directory: src/apps/[app-name]/
- [ ] 2. Create main component: components/[AppName]AppComponent.tsx
- [ ] 3. Create menu bar: components/[AppName]MenuBar.tsx
- [ ] 4. Create logic hook: hooks/use[AppName]Logic.ts
- [ ] 5. Create app definition: index.tsx (include 6 help items)
- [ ] 6. Add icon: public/icons/default/[app-name].png
- [ ] 7. Register in src/config/appRegistry.tsx
- [ ] 8. Add translation keys to src/lib/locales/en/translation.json
- [ ] 9. Localize (last): add en strings, sync locales; use the localize skill to finish

Directory Structure

src/apps/[app-name]/
├── components/
│   ├── [AppName]AppComponent.tsx  # Main component (required)
│   └── [AppName]MenuBar.tsx       # Menu bar (required)
├── hooks/
│   └── use[AppName]Logic.ts       # Logic hook (recommended)
└── index.tsx                      # App definition (required)

1. App Definition (index.tsx)

export const appMetadata = {
  name: "[App Name]",
  version: "1.0.0",
  creator: { name: "Ryo Lu", url: "https://ryo.lu" },
  github: "https://github.com/ryokun6/ryos",
  icon: "/icons/default/[app-name].png",
};

// Always include exactly 6 help items (icon, title, description each).
export const helpItems = [
  { icon: "🚀", title: "Getting Started", description: "How to use this app" },
  { icon: "📂", title: "Open & Save", description: "Open and save files from the File menu" },
  { icon: "✏️", title: "Editing", description: "Use the Edit menu for cut, copy, paste" },
  { icon: "👁️", title: "View Options", description: "Adjust view and layout from the View menu" },
  { icon: "⌨️", title: "Shortcuts", description: "Use keyboard shortcuts for faster workflows" },
  { icon: "❓", title: "Help & About", description: "Open Help from the Help menu for more info" },
];

2. Main Component ([AppName]AppComponent.tsx)

import { WindowFrame } from "@/components/layout/WindowFrame";
import { [AppName]MenuBar } from "./[AppName]MenuBar";
import { AppProps } from "@/apps/base/types";
import { use[AppName]Logic } from "../hooks/use[AppName]Logic";
import { HelpDialog } from "@/components/dialogs/HelpDialog";
import { AboutDialog } from "@/components/dialogs/AboutDialog";
import { appMetadata } from "..";

export function [AppName]AppComponent({
  isWindowOpen,
  onClose,
  isForeground,
  skipInitialSound,
  instanceId,
}: AppProps) {
  const {
    t,
    translatedHelpItems,
    isHelpDialogOpen,
    setIsHelpDialogOpen,
    isAboutDialogOpen,
    setIsAboutDialogOpen,
    isXpTheme,
  } = use[AppName]Logic({ isWindowOpen, isForeground, instanceId });

  const menuBar = (
    <[AppName]MenuBar
      onClose={onClose}
      onShowHelp={() => setIsHelpDialogOpen(true)}
      onShowAbout={() => setIsAboutDialogOpen(true)}
    />
  );

  if (!isWindowOpen) return null;

  return (
    <>
      {!isXpTheme && isForeground && menuBar}
      <WindowFrame
        title={t("apps.[app-name].title")}
        onClose={onClose}
        isForeground={isForeground}
        appId="[app-name]"
        skipInitialSound={skipInitialSound}
        instanceId={instanceId}
        menuBar={isXpTheme ? menuBar : undefined}
      >
        <div className="flex flex-col h-full bg-os-window-bg font-os-ui">
          {/* App content */}
        </div>
      </WindowFrame>
      <HelpDialog
        isOpen={isHelpDialogOpen}
        onOpenChange={setIsHelpDialogOpen}
        appId="[app-name]"
        helpItems={translatedHelpItems}
      />
      <AboutDialog
        isOpen={isAboutDialogOpen}
        onOpenChange={setIsAboutDialogOpen}
        metadata={appMetadata}
        appId="[app-name]"
      />
    </>
  );
}

3. Logic Hook (use[AppName]Logic.ts)

import { useState } from "react";
import { useTranslation } from "react-i18next";
import { useTranslatedHelpItems } from "@/hooks/useTranslatedHelpItems";
import { useThemeStore } from "@/stores/useThemeStore";
import { helpItems } from "..";

export function use[AppName]Logic({ instanceId }: { instanceId: string }) {
  const { t } = useTranslation();
  const translatedHelpItems = useTranslatedHelpItems("[app-name]", helpItems);
  const currentTheme = useThemeStore((state) => state.current);
  const isXpTheme = currentTheme === "xp" || currentTheme === "win98";

  const [isHelpDialogOpen, setIsHelpDialogOpen] = useState(false);
  const [isAboutDialogOpen, setIsAboutDialogOpen] = useState(false);

  return {
    t,
    translatedHelpItems,
    isXpTheme,
    isHelpDialogOpen,
    setIsHelpDialogOpen,
    isAboutDialogOpen,
    setIsAboutDialogOpen,
  };
}

4. Menu Bar ([AppName]MenuBar.tsx)

Match existing app menubars: structure, classes, and spacing.

  • Wrapper: <MenuBar inWindowFrame={isXpTheme}> — no extra gap between menus (layout uses space-x-0).
  • Trigger: MenubarTrigger className="text-md px-2 py-1 border-none focus-visible:ring-0".
  • Content: MenubarContent align="start" sideOffset={1} className="px-0".
  • Items: MenubarItem className="text-md h-6 px-3".
  • Separators: MenubarSeparator className="h-[2px] bg-black my-1".
import { MenuBar } from "@/components/layout/MenuBar";
import {
  MenubarMenu,
  MenubarTrigger,
  MenubarContent,
  MenubarItem,
  MenubarSeparator,
} from "@/components/ui/menubar";
import { useThemeStore } from "@/stores/useThemeStore";
import { useTranslation } from "react-i18next";

interface [AppName]MenuBarProps {
  onClose: () => void;
  onShowHelp: () => void;
  onShowAbout: () => void;
}

export function [AppName]MenuBar({ onClose, onShowHelp, onShowAbout }: [AppName]MenuBarProps) {
  const { t } = useTranslation();
  const currentTheme = useThemeStore((state) => state.current);
  const isXpTheme = currentTheme === "xp" || currentTheme === "win98";
  const isMacOsxTheme = currentTheme === "macosx";

  return (
    <MenuBar inWindowFrame={isXpTheme}>
      <MenubarMenu>
        <MenubarTrigger className="text-md px-2 py-1 border-none focus-visible:ring-0">
          {t("common.menu.file")}
        </MenubarTrigger>
        <MenubarContent align="start" sideOffset={1} className="px-0">
          <MenubarSeparator className="h-[2px] bg-black my-1" />
          <MenubarItem onClick={onClose} className="text-md h-6 px-3">
            {t("common.menu.close")}
          </MenubarItem>
        </MenubarContent>
      </MenubarMenu>
      <MenubarMenu>
        <MenubarTrigger className="text-md px-2 py-1 border-none focus-visible:ring-0">
          {t("common.menu.help")}
        </MenubarTrigger>
        <MenubarContent align="start" sideOffset={1} className="px-0">
          <MenubarItem onClick={onShowHelp} className="text-md h-6 px-3">
            {t("apps.[app-name].menu.help")}
          </MenubarItem>
          {!isMacOsxTheme && (
            <>
              <MenubarSeparator className="h-[2px] bg-black my-1" />
              <MenubarItem onClick={onShowAbout} className="text-md h-6 px-3">
                {t("apps.[app-name].menu.about")}
              </MenubarItem>
            </>
          )}
        </MenubarContent>
      </MenubarMenu>
    </MenuBar>
  );
}

5. Register in appRegistry.tsx

// Import
import { appMetadata as [appName]Metadata, helpItems as [appName]HelpItems } from "@/apps/[app-name]";

// Lazy component
const Lazy[AppName]App = createLazyComponent<unknown>(
  () => import("@/apps/[app-name]/components/[AppName]AppComponent")
    .then(m => ({ default: m.[AppName]AppComponent })),
  "[app-name]"
);

// Add to registry
["[app-name]"]: {
  id: "[app-name]",
  name: "[App Name]",
  icon: { type: "image", src: [appName]Metadata.icon },
  description: "App description",
  component: Lazy[AppName]App,
  helpItems: [appName]HelpItems,
  metadata: [appName]Metadata,
  windowConfig: {
    defaultSize: { width: 650, height: 475 },
    minSize: { width: 400, height: 300 },
  } as WindowConstraints,
},

AppProps Interface

PropTypeDescription
isWindowOpenbooleanWindow visibility
onClose() => voidClose handler
isForegroundbooleanWindow is active
instanceIdstringUnique instance ID
skipInitialSoundbooleanSkip open sound
initialDataTInitialDataOptional startup data

Menu Bar Placement

  • macOS/System7: Render outside WindowFrame when isForeground
  • XP/Win98: Pass via menuBar prop to WindowFrame
const isXpTheme = currentTheme === "xp" || currentTheme === "win98";
return (
  <>
    {!isXpTheme && isForeground && menuBar}
    <WindowFrame menuBar={isXpTheme ? menuBar : undefined}>

WindowFrame Options

PropValuesUse
material"default", "transparent", "notitlebar"Window style
interceptClosebooleanShow save dialog before close
keepMountedWhenMinimizedbooleanPreserve state when minimized

Common Patterns

Initial Data

interface ViewerInitialData { filePath: string; }
export function ViewerAppComponent({ initialData }: AppProps<ViewerInitialData>) {
  const filePath = initialData?.filePath ?? "";
}

Launch Other Apps

import { useLaunchApp } from "@/hooks/useLaunchApp";
const launchApp = useLaunchApp();
launchApp("photos", { path: "/image.png" });

Global Store (Zustand)

// src/stores/use[AppName]Store.ts
import { create } from "zustand";
import { persist } from "zustand/middleware";

export const use[AppName]Store = create<State>()(
  persist((set) => ({ /* state and actions */ }), { name: "[app-name]-storage" })
);

9. Localize (Do Last)

After the app is built and wired up, finish by localizing:

  1. Add translation keys for all user-facing strings (menu labels, dialogs, status, help).
  2. Add English entries under apps.[app-name].* in src/lib/locales/en/translation.json.
  3. Sync other locales (e.g. bun run scripts/sync-translations.ts --mark-untranslated).

Use the localize skill for the full workflow: extract strings → t() calls → en keys → sync. Do this step last so all UI copy is stable before extracting and syncing.

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

34.23%
按下载量换算65

Claude

29.09%
按下载量换算56

Cursor

18.84%
按下载量换算36

Gemini CLI

8.42%
按下载量换算16

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

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

安装前确认

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

来源信息

继续浏览同类 Skills