乐于分享
好东西不私藏

CLI-Anything - 让所有软件都成为 AI Agent 可操控的原生工具

CLI-Anything - 让所有软件都成为 AI Agent 可操控的原生工具

CLI-Anything 介绍与使用说明 / CLI-Anything Guide

Making All Software Agent-Native — 让所有软件都成为 AI Agent 可操控的原生工具


目录 / Table of Contents

  1. 1. 项目概述 / Project Overview
  2. 2. 两阶段工作流 / Two-Phase Workflow
  3. 3. 运行机制详解 / How It Works
  4. 4. 快速上手指南 / Quick Start
  5. 5. 学习路径建议 / Learning Path
  6. 6. 项目关键文件索引 / Key Files Reference

1. 项目概述 / Project Overview

项目链接 (Project Links)

资源
链接
GitHub 仓库
https://github.com/HKUDS/CLI-Anything/tree/main
CLI-Hub(在线浏览 & 安装)
https://clianything.cc/
技术报告
https://arxiv.org/abs/2606.03854
许可证
Apache 2.0

项目定位 (Positioning)

CLI-Anything 是一个 AI Agent 原生的 CLI 生成与集成平台,由香港大学数据科学实验室(HKUDS)开源。

Today's Software Serves Humans. Tomorrow's Users will be Agents.
CLI-Anything: Bridging the Gap Between AI Agents and the World's Software.

它的核心目标是:为任意软件(如 GIMP、Blender、LibreOffice 等)自动生成结构化的命令行接口(CLI),让 AI Agent 可以像人使用命令行一样控制这些软件。

传统软件是为人类设计的图形界面(GUI),AI Agent 很难直接操作它们。CLI-Anything 解决了这个问题——它是一座连接 AI Agent 与真实软件的桥梁。一条命令,即可让任何软件变为 AI Agent 可操控的状态(支持 Pi、OpenClaw、nanobot、Cursor、Claude Code 等平台)。

为什么选择 CLI?(Why CLI?)

CLI 是人类和 AI Agent 的通用接口:

  • • 结构化、可组合(Structured & Composable):文本命令与 LLM 格式天然匹配,可链式组合完成复杂工作流
  • • 轻量、普遍(Lightweight & Universal):跨系统工作,依赖最少
  • • 自描述(Self-Describing)--help 自动提供文档,Agent 可自行发现能力
  • • 确定性(Deterministic & Reliable):一致的输出使 Agent 行为可预测
  • • Agent 优先(Agent-First Design):结构化 JSON 输出消除解析复杂性

核心价值 (Core Value)

能力
说明
全自动 7 阶段流水线
从源码分析、CLI 设计、代码实现、测试到 PyPI 发布,全程自动
CLI-Hub 包管理器
pip install cli-anything-hub
,集中安装、发现、更新所有社区 CLI
多 Agent 平台支持
Claude Code、Cursor、Codex、OpenClaw、Nanobot、Reasonix 等
真实软件集成
直接调用后端软件(LibreOffice、Blender、GIMP 等),不是 GUI 自动化
双格式输出
JSON(供 Agent 解析)+ 人类可读格式,--json 一键切换
SKILL.md 技能系统
每个 CLI 自带 AI 可发现的技能定义,Agent 可自主安装使用
Preview / Live Preview
部分 CLI 支持实时预览,Agent 可观察中间状态再决策

技术栈 (Tech Stack)

  • • 语言:Python 3.10+
  • • CLI 框架:Click 8.0+
  • • 测试框架:pytest 7.0+
  • • 打包规范:PEP 420 namespace packages(命名空间包)
  • • 架构:Monorepo(单体仓库),每个 CLI 是独立的 Python 包

项目架构 (Architecture)

架构图来源:assets/architecture.png

CLI-Anything 的整体架构分为两大核心子系统:

造 CLI(Build):开发者在 AI 编程平台中运行 /cli-anything 命令,触发 7 阶段流水线。流水线从分析目标软件源码开始,自动设计命令体系、生成 Python 代码、编写测试、生成 SKILL.md 技能文档,最终打包发布到 PyPI。

用 CLI(Use) :发布后的 CLI 通过 CLI-Hub 包管理器被用户或 AI Agent 发现、安装、调用。每个 CLI 通过 --json 提供结构化输出,通过 SKILL.md 提供 Agent 可读的能力描述,形成完整的 Agent-to-Software 操作链路。

项目文件目录结构 (Repository Structure)

CLI-Anything/

│  ── 每个软件的独立 CLI harness ────────────────────────
├── <软件名>/agent-harness/            # 每个软件的 CLI 包(如 gimp/、blender/、libreoffice/)
│   ├── <SOFTWARE>.md                  # 该软件特有的架构分析 SOP 文档
│   ├── setup.py                       # PyPI 打包配置(namespace package)
│   └── cli_anything/<软件名>/          # 具体实现代码
│       ├── __init__.py
│       ├── <软件名>_cli.py            # 主 CLI 入口(Click 命令树 + REPL)
│       ├── core/                      # 核心业务模块(project.py / session.py / export.py 等)
│       ├── utils/                     # 工具模块(后端封装、REPL 皮肤等)
│       └── tests/                     # 测试套件(test_core.py / test_full_e2e.py / TEST.md)

│  ── AI 技能定义 ────────────────────────────────────────
├── skills/                            # 所有 CLI 的 SKILL.md 统一存放位置
│   └── cli-anything-<软件名>/          # 每个 CLI 对应一个目录
│       └── SKILL.md                   # AI Agent 可读的技能描述文档

│  ── CLI-Hub 包管理器 ─────────────────────────────────
├── cli-hub/                           # CLI-Hub 包管理器源码
│   └── cli_hub/
│       ├── cli.py                     # 主命令入口(list / search / install / launch / matrix)
│       ├── registry.py                # 注册表获取与缓存(远程 JSON + 本地缓存)
│       ├── installer.py               # 安装策略分发(pip / npm / uv / bundled)
│       ├── matrix.py                  # Matrix 工作流(多 CLI 组合能力查询)
│       └── preview.py                 # Preview 渲染(HTML 生成、live session)

│  ── Agent 平台插件(造 CLI 的工具)───────────────────
├── cli-anything-plugin/               # 给 AI 编程平台(Claude Code 等)的插件
│   ├── HARNESS.md                     # 7 阶段流水线完整规范(最核心的设计文档)
│   ├── commands/                      # 斜杠命令定义(Agent 读的指令)
│   │   ├── cli-anything.md            #   /cli-anything 主命令
│   │   ├── refine.md                  #   /cli-anything:refine 增量改进
│   │   ├── test.md                    #   /cli-anything:test 运行测试
│   │   ├── validate.md                #   /cli-anything:validate 规范校验
│   │   └── list.md                    #   /cli-anything:list 列出 CLI
│   ├── guides/                        # 各阶段的详细指南文档
│   │   ├── pypi-publishing.md         #   PyPI 发布规范
│   │   ├── skill-generation.md        #   SKILL.md 生成指南
│   │   ├── session-locking.md         #   Session 文件锁机制
│   │   ├── preview-methodology.md     #   Preview 设计指南
│   │   ├── mcp-backend.md             #   MCP 后端模式
│   │   ├── filter-translation.md      #   滤镜翻译(MLT → ffmpeg)
│   │   └── auto-save-dry-run.md       #   自动保存 + dry-run
│   ├── skill_generator.py             # SKILL.md 自动生成脚本
│   └── repl_skin.py                   # 统一 REPL 皮肤(复制到各 CLI 中使用)

│  ── 全局注册表 ───────────────────────────────────────
├── registry.json                      # Harness CLI 注册表(name / install_cmd / entry_point 等元数据)
├── public_registry.json               # 第三方公共 CLI 注册表
├── matrix_registry.json               # Matrix 工作流组合注册表

│  ── 文档与资源 ───────────────────────────────────────
├── assets/                            # 图片、截图等资源
├── docs/                              # 文档目录
├── README.md / README_CN.md           # 项目主页(中英日德多语言)
├── CONTRIBUTING.md                    # 贡献指南
└── LICENSE                            # Apache 2.0 许可证

关键设计原则cli_anything/ 目录没有__init__.py,这是 PEP 420 namespace package 的要求——多个独立安装的 PyPI 包(cli-anything-gimpcli-anything-blender 等)可以在同一个 Python 环境中共存,各自贡献 cli_anything/gimp/cli_anything/blender/ 子包,互不冲突。


2. 两阶段工作流 / Two-Phase Workflow

CLI-Anything 有 两个完全独立的阶段,大模型(LLM)的参与方式截然不同:

┌──────────────────────────────────────────────────────────────────────────┐
│                        阶段一:造 CLI(Build Phase)                        │
│                                                                          │
│  使用者:开发者 / 贡献者                                                   │
│  工具:Claude Code、Cursor、Codex 等 AI 编程平台                           │
│  依赖:需要大模型(由宿主平台提供),不需要额外配置 API Key                  │
│  触发:/cli-anything <software-path>                                      │
│  产出:完整的 CLI Python 包(发布到 PyPI)                                  │
└──────────────────────────────────────────────────────────────────────────┘
                                    │
                                    │  发布到 PyPI
                                    ▼
┌──────────────────────────────────────────────────────────────────────────┐
│                        阶段二:用 CLI(Use Phase)                          │
│                                                                          │
│  使用者:任何人 / 任何工具                                                  │
│  工具:终端、bash 脚本、AI Agent、CI/CD 流水线                              │
│  依赖:完全不依赖大模型,不需要任何 API Key                                  │
│  触发:pip install cli-anything-<software>                                 │
│  产出:在终端中直接使用的 CLI 命令                                          │
└──────────────────────────────────────────────────────────────────────────┘

阶段一:造 CLI(Build Phase)

前提条件

  • • Python 3.10+
  • • 目标软件源码(本地路径或 GitHub URL)
  • • 一个支持的 AI 编程平台:Claude Code、Cursor、Codex、OpenClaw 等

触发方式

在 AI 编程平台中安装 CLI-Anything 插件后,运行主命令:

/cli-anything <software-path-or-repo>

例如:

# 从本地源码生成 GIMP CLI
/cli-anything /home/user/gimp

# 从 GitHub 仓库生成 Blender CLI

/cli-anything https://github.com/blender/blender

7 阶段流水线详细说明

Phase 0: 获取源码(Source Acquisition)

如果传入 GitHub URL,Agent 先 git clone 到本地。然后从目录名推导软件名。

Phase 1: 代码库分析(Codebase Analysis)

Agent 阅读目标软件源码,理解其架构:

  • • 找到核心库/框架(如 GIMP 的 Script-Fu、Blender 的 bpy)
  • • 识别数据模型(项目文件格式:XML / JSON / 二进制)
  • • 发现已有的 CLI 工具(如 gimp -i -bmeltffmpeg
  • • 分析撤销/重做系统

为什么需要大模型? 每个软件的源码结构完全不同,需要理解力而非模板匹配。

Phase 2: CLI 架构设计(CLI Architecture Design)

Agent 基于分析结果设计命令体系:

  • • 选择交互模型:有状态 REPL + 无状态子命令(推荐两者兼备)
  • • 定义命令组(如 project / layer / filter / export)
  • • 设计状态模型(哪些状态需要在命令间持久化)
  • • 规划输出格式(JSON + 人类可读双格式)
  • • 产出 <SOFTWARE>.md 设计文档

Phase 3: 实现(Implementation)

Agent 按照 HARNESS.md 规范逐文件生成代码:

gimp/agent-harness/
├── setup.py                       # PyPI 打包配置
├── GIMP.md                        # Phase 2 的设计文档
└── cli_anything/gimp/             # 具体实现
    ├── gimp_cli.py                # 主 CLI 入口(Click 命令树 + REPL)
    ├── core/                      # 核心业务逻辑
    │   ├── project.py             # 项目创建/打开/保存
    │   ├── session.py             # 有状态会话、撤销/重做
    │   └── export.py              # 导出/渲染管线
    └── utils/
        ├── gimp_backend.py        # 封装真实 GIMP 的调用
        └── repl_skin.py           # REPL 界面皮肤

关键实现规则(来自 HARNESS.md):

  1. 1. 必须调用真实软件,不能用 Python 重新实现软件功能
  2. 2. 每个命令必须支持 --json 输出
  3. 3. 不带子命令时进入交互式 REPL 模式
  4. 4. 全局 Session 对象追踪项目状态,支持多步操作

Phase 4: 测试规划(Test Planning)

Agent 先写 TEST.md 计划,再写代码:

  • • 规划 test_core.py:每个核心模块需要多少单元测试
  • • 规划 test_full_e2e.py:端到端工作流场景

Phase 5: 测试实现(Test Implementation)

Agent 写测试代码、运行 pytest、分析失败原因、自动修复代码、迭代直到全部通过。

Phase 6: 测试文档(Test Documentation)

将完整 pytest 输出追加到 TEST.md,记录通过率和覆盖缺口。

Phase 6.5: SKILL.md 生成(SKILL.md Generation)

运行 skill_generator.py 脚本自动提取 CLI 元数据,生成 SKILL.md 文件。此阶段不依赖大模型。

Phase 7: 打包发布(PyPI Publishing)

生成 setup.py,执行 pip install -e . 本地安装,验证命令在 PATH 中可用。

API Key 管理

重要:CLI-Anything 本身不需要配置任何 LLM API Key。

大模型的 Key 由宿主平台(Claude Code / Cursor / Codex)管理。CLI-Anything 只是这些平台里运行的一套"指令手册"(HARNESS.md + 插件命令),它不调用任何 LLM API。

辅助命令

命令
作用
/cli-anything:refine <path> [focus]
增量改进已有 CLI,扩展命令覆盖率;可指定 focus 区域
/cli-anything:test <path>
运行测试并更新 TEST.md
/cli-anything:validate <path>
校验 CLI 是否符合 HARNESS.md 规范(52 项检查)
/cli-anything:list
列出当前环境中所有已安装/已生成的 CLI

阶段二:用 CLI(Use Phase)

核心特点

  • • 不需要大模型,不需要任何 API Key
  • • 使用者无关性:人类、bash 脚本、AI Agent、CI/CD 流水线都可以直接调用
  • • 安装后就是一个标准的 Python CLI 包,出现在系统 PATH 中

安装方式

方式 A:通过 CLI-Hub 包管理器(推荐)

pip install cli-anything-hub
cli-hub install gimp           # 安装 GIMP CLI
cli-hub list                   # 浏览所有可用 CLI
cli-hub search image           # 按关键词搜索
cli-hub info gimp              # 查看 CLI 详情
cli-hub launch gimp            # 启动使用

方式 B:直接 pip install

pip install cli-anything-gimp
cli-anything-gimp --help       # 直接使用

使用方式

# 人类在终端中直接使用
cli-anything-gimp --json project new -w 1920 -h 1080 -o canvas.json

# bash 脚本中使用

cli-anything-gimp --json export render output.png --overwrite

# AI Agent 使用(Agent 读取 SKILL.md 后自主决定调用哪些命令)

SKILL.md 是给 Agent 读的"说明书"。AI Agent 通过读取 SKILL.md 了解有哪些命令可用、参数是什么,然后自主拼出命令。人类不需要读它,直接看 --help 即可。


3. 运行机制详解 / How It Works

以 GIMP CLI 为例,拆解整个运行机制。

整体架构(5 层)

┌──────────────────────────────────────────────────────────────┐
│  使用者(可选,以下任一)                                        │
│  - 人类用户在终端操作                                           │
│  - bash / Python 脚本                                        │
│  - AI Agent(Claude Code、OpenClaw 等,读取 SKILL.md 后调用)   │
└──────────────────────────────┬───────────────────────────────┘
                               │  执行 CLI 命令
                               ▼
┌──────────────────────────────────────────────────────────────┐
│  第 2 层:CLI-Hub 包管理器(cli-hub)                          │
│  负责发现、安装、更新 CLI;也是可选的                             │
│  你也可以直接 pip install cli-anything-gimp 跳过它              │
│  源码:cli-hub/cli_hub/                                       │
└──────────────────────────────┬───────────────────────────────┘
                               │  查询 registry.json + pip install
                               ▼
┌──────────────────────────────────────────────────────────────┐
│  第 3 层:注册表(registry.json)                              │
│  存储所有 CLI 的元数据:名称、安装命令、入口点                    │
│  文件:registry.json / public_registry.json                   │
└──────────────────────────────┬───────────────────────────────┘
                               │  指向安装源(git+https://...)
                               ▼
┌──────────────────────────────────────────────────────────────┐
│  第 4 层:具体 CLI 包(cli-anything-gimp)                     │
│  独立 Python 包,用 Click 构建,提供具体命令                     │
│  源码:gimp/agent-harness/cli_anything/gimp/gimp_cli.py       │
└──────────────────────────────┬───────────────────────────────┘
                               │  调用后端
                               ▼
┌──────────────────────────────────────────────────────────────┐
│  第 5 层:后端执行(Pillow / 真实 GIMP 批处理模式)              │
│  实际完成图像操作                                               │
└──────────────────────────────────────────────────────────────┘

cli-hub install gimp 的执行链路

  1. 1. 查询注册表 — cli-hub/cli_hub/registry.py 中的 get_cli("gimp") 从远程 registry.json 中查找 GIMP 的元数据(有本地缓存,TTL 1 小时)
  2. 2. 判断安装策略 — cli-hub/cli_hub/installer.py 中的 _install_strategy() 判断使用 pipnpm 还是 command
  3. 3. 执行安装 — _pip_install() 实际运行 pip install git+https://...#subdirectory=gimp/agent-harness
  4. 4. 记录状态 — 安装成功后写入 ~/.cli-hub/installed.json

registry.json 中的 GIMP 条目示例:

{
  "name"
: "gimp",
  "display_name"
: "GIMP",
  "install_cmd"
: "pip install git+https://github.com/.../gimp/agent-harness",
  "entry_point"
: "cli-anything-gimp",
  "skill_md"
: "skills/cli-anything-gimp/SKILL.md",
  "category"
: "image-design",
  "requires"
: "GIMP (apt install gimp)"
}

entry_point 对应 setup.py 中的:

entry_points={
    "console_scripts"
: [
        "cli-anything-gimp=cli_anything.gimp.gimp_cli:main"
,
    ],
}

pip 安装后,系统 PATH 中出现 cli-anything-gimp 命令,指向 Python 模块的 main() 函数。

cli-anything-gimp --json project new 的命令处理链路

  1. 1. 系统 PATH 找到 cli-anything-gimp,调用 cli_anything.gimp.gimp_cli:main
  2. 2. Click 框架解析 --json 全局选项,设置 _json_output = True
  3. 3. Click 路由到 project 命令组下的 new 子命令
  4. 4. project_new() 函数调用 core/project.py 中的 create_project()
  5. 5. output() 函数根据 _json_output 决定输出 JSON 还是人类可读格式
# gimp_cli.py 核心结构
@click.group(invoke_without_command=True)

@click.option("--json", "use_json", is_flag=True)

def
 cli(ctx, use_json):
    global
 _json_output
    _json_output = use_json
    if
 ctx.invoked_subcommand is None:
        ctx.invoke(repl)   # 不带子命令时进入 REPL

@cli.group()

def
 project():
    """Project management commands."""


@project.command("new")

@click.option("--width", "-w", type=int, default=1920)

def
 project_new(width, height, ...):
    proj = proj_mod.create_project(width=width, ...)
    output(proj_mod.get_project_info(proj), "Created project")

SKILL.md 的作用与生成机制

作用:SKILL.md 是 AI Agent 发现和使用 CLI 的"说明书"。它包含:

  • • YAML frontmatter(触发元数据:名称、描述)
  • • 安装方式
  • • 所有命令组、参数、使用示例
  • • Agent 专属指导(--json 用法、错误处理)

生成方式cli-anything-plugin/skill_generator.py 脚本自动从 CLI 源码中提取元数据:

  • • 解析 gimp_cli.py 中的 Click 装饰器(@click.group()@click.command()
  • • 提取 setup.py 中的版本号
  • • 提取 README.md 中的系统包安装命令
  • • 用 Jinja2 模板渲染最终文档

输出两份:

  • • skills/cli-anything-gimp/SKILL.md(仓库根目录规范副本)
  • • cli_anything/gimp/skills/SKILL.md(包内兼容副本,随 pip 分发)

4. 核心机制源码解析 / Core Mechanism Deep Dive

本章深入解读 CLI-Hub 包管理器的三个核心文件,帮助你理解"CLI 从发现到安装"的完整链路。

4.1 registry.py — CLI 的注册、发现、缓存机制

文件路径cli-hub/cli_hub/registry.py(118 行)

定位:CLI-Hub 包管理器的数据源层。当用户执行 cli-hub listcli-hub searchcli-hub install 时,所有 CLI 信息的"从哪里来"都由这个文件负责。

核心设计:双注册表 + 本地缓存

远程注册表(GitHub Pages 托管)
├── registry.json          <-- Harness CLI(项目自建的 CLI)
└── public_registry.json   <-- 第三方公共 CLI(npm/pip/brew 等来源)
         |
         |  HTTP GET(TTL 1 小时内用缓存)
         v
本地缓存(~/.cli-hub/)
├── registry_cache.json
└── public_registry_cache.json
         |
         |  merge + 标记 _source
         v
统一 CLI 列表(fetch_all_clis())

关键代码段解读

(1)缓存机制 _fetch_json()

CACHE_TTL = 3600  # 1 小时

def
 _fetch_json(url, cache_file, force_refresh=False):
    # 优先读本地缓存(1 小时内有效)

    if
 not force_refresh and cache_file.exists():
        cached = json.loads(cache_file.read_text())
        if
 time.time() - cached.get("_cached_at", 0) < CACHE_TTL:
            return
 cached["data"]

    # 缓存过期或不存在 -> 请求远程

    try
:
        resp = requests.get(url, timeout=15)
        resp.raise_for_status()
        data = resp.json()
    except
 (requests.RequestException, ValueError):
        # 网络失败时降级:返回过期缓存(不报错,保证可用性)

        cached_data = _load_cached_data(cache_file)
        if
 cached_data is not None:
            return
 cached_data
        raise
  # 连缓存都没有才真正报错

设计要点

  • • 1 小时 TTL 避免频繁网络请求
  • • 网络故障时降级到旧缓存而不是崩溃——保证离线环境下 cli-hub list 仍然可用

(2)双注册表合并 fetch_all_clis()

def fetch_all_clis(force_refresh=False):
    registry = fetch_registry(force_refresh)       # 拉 harness 注册表
    all_clis = []

    for
 cli in registry["clis"]:
        entry = dict(cli)                          # 复制(避免污染缓存)
        entry["_source"] = "harness"               # 标记来源
        all_clis.append(entry)

    public = fetch_public_registry(force_refresh)  # 拉公共注册表(可选)
    if
 public:
        for
 cli in public["clis"]:
            entry = dict(cli)
            entry["_source"] = "public"            # 标记来源
            all_clis.append(entry)

    return
 all_clis

设计要点

  • • 两个注册表独立获取,公共注册表失败不影响 harness 注册表
  • • 每条 CLI 打上 _source 标签,前端显示时区分来源(harness 显示为空白,public 显示为黄色的 npm/pip 标签)
  • • dict(cli) 复制条目防止 _source 标签污染缓存数据

(3)查询与搜索 get_cli() / search_clis()

def get_cli(name, force_refresh=False):
    """按名称精确查找(大小写不敏感)"""

    name_lower = name.lower()
    for
 cli in fetch_all_clis(force_refresh):
        if
 cli["name"].lower() == name_lower:
            return
 cli
    return
 None

def
 search_clis(query, force_refresh=False):
    """按关键词模糊搜索(名称/描述/分类/显示名)"""

    query_lower = query.lower()
    results = []
    for
 cli in fetch_all_clis(force_refresh):
        if
 (query_lower in cli["name"].lower()
                or
 query_lower in cli["description"].lower()
                or
 query_lower in cli.get("category", "").lower()
                or
 query_lower in cli.get("display_name", "").lower()):
            results.append(cli)
    return
 results

完整数据流

用户输入: cli-hub install gimp
         |
         v
cli.py 调用 installer.install_cli("gimp")
         |
         v
installer.py 调用 registry.get_cli("gimp")
         |
         v
registry.py: get_cli -> fetch_all_clis -> fetch_registry + fetch_public_registry
         |                                      |
         |                               读缓存 / 请求远程
         v
返回 gimp 的元数据 dict(包含 install_cmd / entry_point 等)
         |
         v
installer.py 根据元数据执行安装

4.2 installer.py — CLI 的安装策略分发

文件路径cli-hub/cli_hub/installer.py(605 行)

定位:CLI-Hub 的执行层,负责"知道了一个 CLI 怎么装之后,真正去装它"。

核心设计:策略模式(Strategy Pattern)

install_cli(name)
    |
    |-- get_cli(name)           <-- 从 registry 获取元数据
    |
    |-- _install_strategy(cli)  <-- 判断安装策略
    |   |-- "pip"       -> harness CLI 默认策略
    |   |-- "npm"       -> 有 npm_package 字段的公共 CLI
    |   |-- "uv"        -> 用 uv 安装的公共 CLI
    |   |-- "bundled"   -> 随母软件捆绑的 CLI
    |   +-- "command"   -> 自定义安装命令
    |
    +-- _perform_action(cli, "install")  <-- 按策略分发
        |
        |-- _pip_install(cli)      -> subprocess: pip install ...
        |-- _npm_install(cli)      -> subprocess: npm install -g ...
        |-- _uv_install(cli)       -> subprocess: uv tool install ...
        |-- _bundled_install(cli)  -> 检测命令是否已存在
        +-- _generic_install(cli)  -> subprocess: 执行任意 install_cmd

关键代码段解读

(1)策略判断 _install_strategy()

def _install_strategy(cli):
    """根据 CLI 元数据决定用哪种包管理器"""

    strategy = cli.get("install_strategy")   # 优先读显式声明
    if
 strategy:
        return
 strategy

    if
 cli.get("_source", "harness") == "harness":
        return
 "pip"                         # harness CLI 默认走 pip
    if
 cli.get("npm_package") or cli.get("package_manager") == "npm":
        return
 "npm"                         # 有 npm 包的走 npm
    if
 cli.get("package_manager") == "uv":
        return
 "uv"
    if
 cli.get("package_manager") == "bundled":
        return
 "bundled"
    return
 "command"                         # 兜底:执行 install_cmd

判断优先级install_strategy 字段 > _source 字段 > npm_package > package_manager > 兜底为 command

(2)pip 安装 _pip_install() — 最常用的策略

def _pip_install(cli):
    install_cmd = cli["install_cmd"]
    # 把 "pip install git+https://..." 解析成 pip 的参数

    result = subprocess.run(
        [sys.executable, "-m", "pip", "install"]
        + install_cmd.replace("pip install ", "").split(),
        capture_output=True, text=True
    )
    if
 result.returncode == 0:
        return
 True, f"Installed {cli['display_name']} ({cli['entry_point']})"
    return
 False, f"pip install failed:\n{result.stderr}"

设计要点:使用 sys.executable -m pip 而不是直接调 pip,保证安装到当前 Python 环境中。

(3)统一分发 _perform_action()

def _perform_action(cli, action):  # action = "install" | "uninstall" | "update"
    strategy = _install_strategy(cli)
    actions = {
        "pip"
:     {"install": _pip_install,     "uninstall": _pip_uninstall,     "update": _pip_update},
        "npm"
:     {"install": _npm_install,     "uninstall": _npm_uninstall,     "update": _npm_update},
        "uv"
:      {"install": _uv_install,      "uninstall": _uv_uninstall,      "update": _uv_update},
        "command"
: {"install": _generic_install, "uninstall": _generic_uninstall, "update": _generic_update},
        "bundled"
: {"install": _bundled_install, "uninstall": _bundled_uninstall, "update": _bundled_update},
    }
    handler = actions.get(strategy, actions["command"]).get(action)
    return
 strategy, handler(cli)

标准的策略模式:5 种策略 x 3 种操作 = 15 个处理函数,按字典分发。

(4)安装状态持久化 install_cli()

def install_cli(name):
    cli = get_cli(name)                       # 从 registry 获取元数据
    strategy, (success, msg) = _perform_action(cli, "install")  # 按策略安装

    if
 success:
        installed = _load_installed()         # 读 ~/.cli-hub/installed.json
        installed[cli["name"]] = _installed_entry(cli, source, strategy)
        _save_installed(installed)            # 写回

    return
 success, msg

~/.cli-hub/installed.json 的结构示例:

{
  "gimp"
: {
    "version"
: "1.0.0",
    "entry_point"
: "cli-anything-gimp",
    "source"
: "harness",
    "strategy"
: "pip",
    "install_cmd"
: "pip install git+https://...#subdirectory=gimp/agent-harness"
  }

}

cli-hub list 命令中的绿色标记  就是通过对比 installed.json 和 registry 来渲染的。

Matrix 批量安装(高级功能)

installer.py 还支持 Matrix — 批量安装一组 CLI(用于多工具工作流组合):

def install_matrix(name, capability=None, recipe=None, only=None, resume=False):
    # 1. 从 matrix_registry.json 获取 matrix 定义

    # 2. 解析 scope(全量 / 按 capability / 按 recipe / 子集)

    # 3. 遍历 matrix 中的每个 CLI,调用 install_cli()

    # 4. 记录结果到 matrix_state.json(支持 --resume 重试失败的)

    # 5. 安装完成后渲染 matrix skill 文件

4.3 registry.json — CLI 元数据结构

文件路径registry.json(约 1460 行)

定位:整个 CLI 生态的**"通讯录"**。CLI-Hub 所有的发现、安装、展示功能,都依赖这个文件提供的元数据。文件托管在 https://clianything.cc/registry.json,本地缓存在 ~/.cli-hub/registry_cache.json

整体 JSON 结构

{
  "meta"
: {
    "repo"
: "https://github.com/HKUDS/CLI-Anything",
    "description"
: "CLI-Hub - Agent-native stateful CLI interfaces...",
    "updated"
: "2026-06-10"
  }
,
  "clis"
: [
    {
 /* CLI 条目 1 */ },
    {
 /* CLI 条目 2 */ },
    ...
  ]

}

完整字段说明

以 Audacity(音频编辑)为例,拆解每个字段的含义:

{
  "name"
: "audacity",
  "display_name"
: "Audacity",
  "version"
: "1.0.0",
  "description"
: "Audio editing and processing via sox",
  "requires"
: "sox (apt install sox)",
  "homepage"
: "https://www.audacityteam.org",
  "source_url"
:null,
  "install_cmd"
: "pip install git+https://github.com/HKUDS/CLI-Anything.git#subdirectory=audacity/agent-harness",
  "entry_point"
: "cli-anything-audacity",
  "skill_md"
: "skills/cli-anything-audacity/SKILL.md",
  "category"
: "audio",
  "contributors"
: [
    {
 "name": "CLI-Anything-Team", "url": "https://github.com/HKUDS/CLI-Anything" }
  ]

}
字段
类型
说明
name
string
唯一标识符(小写),用于 cli-hub install <name>
display_name
string
人类可读名称,用于显示
version
string
CLI 版本号
description
string
一句话描述,用于 cli-hub search 模糊匹配
requires
string
前置依赖(安装前需注意的软件)
homepage
string
软件官网链接
source_url
string/null
源码 URL(可选)
install_cmd
string
安装命令,被 _pip_install() 解析执行
entry_point
string
pip 安装后在 PATH 中出现的命令名,用于卸载和 cli-hub launch
skill_md
string/null
SKILL.md 在仓库中的路径,用于 cli-hub info 展示
category
string
分类标签,用于 cli-hub list --category <cat> 过滤
contributors
array
贡献者列表(name + url),用于 cli-hub info 展示

各字段被哪些功能使用

字段
使用方
使用方式
nameget_cli()
 / install_cli()
精确查找 + 安装标识
display_namecli-hub list
 / cli-hub info
显示美观的软件名
descriptioncli-hub search <query>
关键词模糊匹配
install_cmd_pip_install()
实际执行的 pip 命令
entry_point_pip_uninstall()
 / cli-hub launch
卸载包名 / PATH 中的命令名
skill_mdcli-hub info
显示 SKILL.md 链接
categorycli-hub list --category
过滤分类
requirescli-hub info
提示用户需要预装什么
contributorscli-hub info
展示贡献者

install_cmd 的特殊设计

pip install git+https://github.com/HKUDS/CLI-Anything.git#subdirectory=audacity/agent-harness

这个 URL 直接指向 Git 仓库的子目录。pip 会:

  1. 1. clone 整个 CLI-Anything 仓库(临时)
  2. 2. 只安装 audacity/agent-harness/ 子目录中的包
  3. 3. 安装完成后删除临时 clone

这意味着不需要提前把包发布到 PyPI,直接从 GitHub 安装,极大降低了贡献门槛。

public_registry.json 对比

公共 CLI(第三方工具)的条目字段略有不同,增加了安装策略相关字段:

{
  "name"
: "some-public-cli",
  "install_strategy"
: "npm",
  "npm_package"
: "@some/package",
  "npx_cmd"
: "npx @some/package",
  "package_manager"
: "npm",
  "install_cmd"
: "npm install -g @some/package",
  "install_notes"
: "...",
  "uninstall_cmd"
: "npm uninstall -g @some/package",
  "update_cmd"
: "npm install -g @some/package@latest"
}

公共注册表支持 npmuvbundledcommand 等多种安装策略,比 harness 注册表更灵活。


4.4 三文件协同:完整调用链

以 cli-hub install gimp 为例,展示三个文件如何端到端协同:

用户执行: cli-hub install gimp
                |
                v
cli.py: install("gimp")
    click.echo(f"Installing {name}...")
    success, msg = install_cli(name)          <-- 调用 installer.py
                |
                v
installer.py: install_cli("gimp")
    cli = get_cli("gimp")                     <-- 调用 registry.py
                |
                v
registry.py: get_cli("gimp")
    fetch_all_clis()
        -> fetch_registry()                  -> 读缓存 or 请求 registry.json
        -> fetch_public_registry()           -> 读缓存 or 请求 public_registry.json
        -> 合并 + 打 _source 标签
    找到 name="gimp" 的条目
    返回 dict: {name, install_cmd, entry_point, ...}
                |
                v
installer.py 拿到元数据
    strategy = _install_strategy(cli)        -> "pip"(harness 默认)
    _perform_action(cli, "install")
        -> _pip_install(cli)
        -> subprocess.run([sys.executable, "-m", "pip", "install",
                          "git+https://...#subdirectory=gimp/agent-harness"])
                |
                v
pip 从 GitHub 安装 cli-anything-gimp 包
    -> 系统 PATH 中出现 cli-anything-gimp 命令
                |
                v
installer.py 记录状态
    installed["gimp"] = {version, entry_point, source, strategy}
    _save_installed(installed)               -> 写入 ~/.cli-hub/installed.json
                |
                v
cli.py 显示结果
    [OK] Installed GIMP (cli-anything-gimp)
    Run it with: cli-anything-gimp
    Or launch:   cli-hub launch gimp

三个文件的职责总结

文件
角色
职责
registry.json
数据本身
定义所有 CLI 的元数据(名称、安装命令、入口点等)
registry.py
数据源层
获取、缓存、合并、查询 CLI 元数据
installer.py
执行层
根据元数据选择安装策略、执行安装、记录状态

5. 完整 CLI 实现解析 / Complete CLI Implementation Deep Dive

本章以 GIMP CLI 为范例,深入解读"一个完整 CLI 长什么样"。GIMP CLI 是项目中最成熟的参考实现,涵盖了 Click 命令树、双格式输出、REPL 交互、会话状态管理、PEP 420 打包规范、SKILL.md 技能文档等所有核心模式。

5.1 gimp_cli.py — Click 命令树、双格式输出与 REPL

文件路径gimp/agent-harness/cli_anything/gimp/gimp_cli.py(819 行)

定位:GIMP CLI 的主入口文件,定义了整个命令体系结构。

整体架构

main()                          <-- entry_point 入口
  |
  +-- cli()                     <-- @click.group (根组)
        |                         处理全局选项: --json / --project / --dry-run
        |                         无子命令时自动进入 REPL
        |
        +-- project             <-- @cli.group (项目管理)
        |     +-- new / open / save / info / profiles / json
        |
        +-- layer               <-- @cli.group (图层管理)
        |     +-- new / add-from-file / list / remove / duplicate / move / set / flatten / merge-down
        |
        +-- canvas              <-- @cli.group (画布操作)
        |     +-- info / resize / scale / crop / mode / dpi
        |
        +-- filter              <-- @cli.group (滤镜管理)
        |     +-- list-available / info / add / remove / set / list
        |
        +-- media               <-- @cli.group (媒体文件)
        |     +-- probe / list / check / histogram
        |
        +-- export              <-- @cli.group (导出/渲染)
        |     +-- presets / preset-info / render
        |
        +-- session             <-- @cli.group (会话管理)
        |     +-- status / undo / redo / history
        |
        +-- draw                <-- @cli.group (绘图操作)
        |     +-- text / rect
        |
        +-- repl                <-- @cli.command (交互式 REPL)

共 9 个命令组 + 35 个子命令,覆盖了 GIMP 图像编辑的完整功能域。

关键设计模式解读

(1)根命令组 — invoke_without_command=True

@click.group(invoke_without_command=True)
@click.option("--json", "use_json", is_flag=True, help="Output as JSON")

@click.option("--project", "project_path", type=str, default=None,
              help
="Path to .gimp-cli.json project file"
)

@click.option("--dry-run", "dry_run", is_flag=True, default=False,
              help
="Run command without saving changes to disk"
)

@click.pass_context

def
 cli(ctx, use_json, project_path, dry_run):
    """GIMP CLI -- Stateful image editing from the command line."""

    global
 _json_output
    _json_output = use_json

    if
 project_path:
        sess = get_session()
        if
 not sess.has_project():
            proj = proj_mod.open_project(project_path)
            sess.set_project(proj, project_path)

    # 关键:无子命令时自动进入 REPL

    if
 ctx.invoked_subcommand is None:
        ctx.invoke(repl, project_path=None)

设计要点

  • • invoke_without_command=True 允许根命令不绑定子命令就能执行——这是"无参数启动即进入 REPL"的关键
  • • --json--project--dry-run 三个全局选项在根命令组中处理,所有子命令自动继承
  • • 如果用户传了 --project,会在任何子命令执行前自动加载项目文件

(2)双格式输出 — output() 函数

def output(data, message: str = ""):
    if
 _json_output:
        click.echo(json.dumps(data, indent=2, default=str))  # JSON 格式
    else
:
        if
 message:
            click.echo(message)                                # 人类可读格式
        if
 isinstance(data, dict):
            _print_dict(data)
        elif
 isinstance(data, list):
            _print_list(data)
        else
:
            click.echo(str(data))

这是整个 CLI 最核心的设计之一:同一个数据源,两种输出格式

模式
触发方式
输出示例
典型使用者
人类可读(默认)
不加 --json
name: untitled
 / width: 1920
终端用户、脚本调试
JSON 结构化
加 --json
{"name": "untitled", "width": 1920}
AI Agent、自动化流水线

_print_dict() 和 _print_list() 递归处理嵌套数据结构,保证人类模式下复杂数据也能清晰展示。

(3)命令处理标准流程 — 以 project_new 为例

@project.command("new")
@click.option("--width", "-w", type=int, default=1920, help="Canvas width")

@click.option("--height", "-h", type=int, default=1080, help="Canvas height")

@click.option("--mode", type=click.Choice(["RGB", "RGBA", "L", "LA"]), default="RGB")

@click.option("--background", "-bg", default="#ffffff", help="Background color")

@click.option("--dpi", type=int, default=72, help="Resolution in DPI")

@click.option("--name", "-n", default="untitled", help="Project name")

@click.option("--output", "-o", type=str, default=None, help="Save path")

@handle_error

def
 project_new(width, height, mode, background, dpi, name, profile, output):
    """Create a new project."""

    proj = proj_mod.create_project(...)     # 1. 调用 core 模块执行实际逻辑
    sess = get_session()
    sess.set_project(proj, output)          # 2. 更新全局会话状态
    if
 output:
        proj_mod.save_project(proj, output) # 3. 如有输出路径,持久化到文件
    output_data = proj_mod.get_project_info(proj)
    globals
()["output"](output_data, ...)   # 4. 双格式输出结果

每个命令都遵循相同的 4 步模式:调用 core -> 更新 session -> 持久化 -> 双格式输出。这个模式在 35 个命令中高度一致。

(4)错误处理装饰器 — @handle_error

def handle_error(func):
    def
 wrapper(*args, **kwargs):
        try
:
            return
 func(*args, **kwargs)
        except
 FileNotFoundError as e:
            if
 _json_output:
                click.echo(json.dumps({"error": str(e), "type": "file_not_found"}))
            else
:
                click.echo(f"Error: {e}", err=True)
            if
 not _repl_mode:
                sys.exit(1)            # REPL 模式下不退出进程!
        except
 (ValueError, IndexError, RuntimeError) as e:
            ...
    return
 wrapper

关键设计:在 REPL 模式下,错误只打印不退出。这是 REPL 可用性的基础——一条命令出错不应终止整个交互会话。

(5)自动保存 — @cli.result_callback()

@cli.result_callback()
def
 auto_save_on_exit(result, use_json, project_path, dry_run, **kwargs):
    """Auto-save project after one-shot commands if state was modified."""

    if
 _repl_mode:
        return
                    # REPL 模式不自动保存(手动控制)
    if
 dry_run:
        return
                    # dry-run 模式不保存
    sess = get_session()
    if
 sess.has_project() and sess._modified and sess.project_path:
        sess.save_session()       # 一次性命令执行后自动保存

Click 的 result_callback 在所有子命令执行完毕后自动调用。这实现了一次性命令的"执行完自动保存"语义。

(6)REPL 实现

@cli.command()
def
 repl(project_path):
    from
 cli_anything.gimp.utils.repl_skin import ReplSkin
    global
 _repl_mode
    _repl_mode = True

    skin = ReplSkin("gimp", version="1.0.0")
    pt_session = skin.create_prompt_session()  # prompt_toolkit 会话

    while
 True:
        line = skin.get_input(pt_session, ...)
        if
 line.lower() in ("quit", "exit", "q"):
            break

        if
 line.lower() == "help":
            skin.help(_repl_commands)
            continue


        args = shlex.split(line)               # 解析命令行输入(支持引号)
        cli.main(args, standalone_mode=False)   # 复用整个 Click 命令树!

核心技巧:REPL 不是重新实现命令解析,而是把用户输入通过 shlex.split() 拆成参数列表,然后直接传给 cli.main()。这意味着 REPL 模式和一次性命令模式共享完全相同的命令处理逻辑,零重复代码。

(7)全局会话状态 — Session 类

class Session:
    MAX_UNDO = 50

    def
 __init__(self):
        self
.project: Optional[Dict] = None      # 项目数据(JSON dict)
        self
.project_path: Optional[str] = None   # 项目文件路径
        self
._undo_stack: List[Dict] = []         # 撤销栈(深拷贝快照)
        self
._redo_stack: List[Dict] = []         # 重做栈
        self
._modified: bool = False              # 脏标记(用于自动保存)

每个修改性命令执行前都会调用 sess.snapshot("描述") 保存快照到撤销栈。undo() 弹出栈顶恢复到上一状态,redo() 反向操作。最多保留 50 级历史。

内部模块分工

模块
职责
行数
gimp_cli.py
命令定义、输出格式化、REPL
819
core/project.py
项目 CRUD、配置文件
131
core/layers.py
图层增删改查
379
core/filters.py
滤镜管理与应用
382
core/canvas.py
画布操作(缩放/裁剪/色彩模式)
193
core/media.py
媒体文件探测与校验
211
core/export.py
导出渲染(Pillow 路径 + GIMP 后端路径)
562
core/session.py
会话状态管理、undo/redo、文件锁保存
156
utils/repl_skin.py
REPL 皮肤(prompt_toolkit 封装)
567
utils/gimp_backend.py
GIMP 原生后端调用(batch mode)
545

gimp_cli.py 是"薄"的命令层,真正的业务逻辑都在 core/ 模块中。这种分层让命令定义保持简洁,业务逻辑可独立测试。


5.2 setup.py — PEP 420 Namespace Package 打包规范

文件路径gimp/agent-harness/setup.py(62 行)

定位:定义 GIMP CLI 如何被打包成一个可通过 pip install 安装的 Python 包。

完整文件逐行解读

from setuptools import setup, find_namespace_packages

with
 open("cli_anything/gimp/README.md", "r", encoding="utf-8") as fh:
    long_description = fh.read()

setup(
    name="cli-anything-gimp",           # PyPI 包名
    version="1.0.0",
    ...
    packages=find_namespace_packages(include=["cli_anything.*"]),
    ...
    entry_points={
        "console_scripts"
: [
            "cli-anything-gimp=cli_anything.gimp.gimp_cli:main"
,
        ],
    },
    ...
)

逐字段解读

字段
说明
namecli-anything-gimp
PyPI 包名,也是 pip install 时使用的名字
version1.0.0
版本号,遵循 semver
packagesfind_namespace_packages(include=["cli_anything.*"])PEP 420 关键配置
(见下文)
python_requires>=3.10
最低 Python 版本
install_requiresclick>=8.0.0
prompt-toolkit>=3.0.0
运行时依赖
extras_requirepillow
dev
可选依赖组(pip install cli-anything-gimp[dev]
entry_pointscli-anything-gimp=cli_anything.gimp.gimp_cli:mainconsole_scripts 关键配置
(见下文)
package_datacli_anything.gimp: ["skills/*.md"]
随包分发的非 Python 文件(SKILL.md 副本)

核心概念 1:PEP 420 Namespace Package

问题:CLI-Anything 是一个 monorepo,有 50+ 个软件的 CLI,每个都是独立的 pip 包。它们都需要安装在 cli_anything 命名空间下:

pip install cli-anything-gimp     -> cli_anything.gimp
pip install cli-anything-blender  -> cli_anything.blender
pip install cli-anything-inkscape -> cli_anything.inkscape

如果用传统 Python 包,每个包的 cli_anything/ 目录都需要 __init__.py,但多个包的 __init__.py 会冲突。

解决方案:PEP 420 namespace packages——cli_anything/ 目录没有__init__.py

gimp/agent-harness/
    cli_anything/            <-- 没有 __init__.py(namespace 层)
        gimp/                <-- 有 __init__.py(实际包层)
            __init__.py
            gimp_cli.py
            core/
                __init__.py
                project.py
                layers.py
                ...

find_namespace_packages(include=["cli_anything.*"]) 会自动发现 cli_anything.gimp 及其子包,但不会在 cli_anything/ 层创建 __init__.py。这样多个独立安装的包可以安全共存于同一个 cli_anything 命名空间。

核心概念 2:console_scripts entry_points

entry_points={
    "console_scripts"
: [
        "cli-anything-gimp=cli_anything.gimp.gimp_cli:main"
,
    ],
},

这行配置告诉 pip:安装此包后,在系统 PATH 中创建一个名为 cli-anything-gimp 的可执行命令,指向 cli_anything.gimp.gimp_cli 模块的 main() 函数。

安装后用户在终端直接执行:

cli-anything-gimp --help
cli-anything-gimp project new -o canvas.json

pip 实际创建的是一个小型 wrapper 脚本(通常在 ~/.local/bin/ 或虚拟环境的 bin/ 中),内容大致等价于:

#!/usr/bin/env python3
from
 cli_anything.gimp.gimp_cli import main
main()

依赖管理策略

install_requires=[
    "click>=8.0.0"
,          # 命令框架(必须)
    "prompt-toolkit>=3.0.0"
, # REPL 交互(必须)
],
extras_require={
    "pillow"
: ["Pillow>=10.0.0"],              # 图像后端(可选)
    "dev"
: ["pytest>=7.0.0", "pytest-cov>=4.0.0",
            "Pillow>=10.0.0"
, "numpy>=1.24.0"], # 开发依赖
},

设计要点

  • • click 和 prompt-toolkit 是硬依赖——没有它们 CLI 无法运行
  • • Pillow 是可选依赖——CLI 本身不需要它就能启动和显示帮助,只有实际渲染图像时才需要
  • • 这种分层依赖设计让 CLI 的安装更轻量,用户可以先装 CLI 看看有什么命令,再按需安装后端

5.3 SKILL.md — AI Agent 如何发现和理解 CLI

文件路径skills/cli-anything-gimp/SKILL.md(257 行)

定位:这是 AI Agent 的"能力感知入口"。Agent 通过读取这个文件来了解:这个 CLI 能做什么?怎么安装?有哪些命令?怎么用?

SKILL.md 的结构解析

SKILL.md
  |
  +-- YAML Frontmatter          <-- 机器可读的触发元数据
  |     name: "cli-anything-gimp"
  |     description: "..."
  |
  +-- # 标题 + 简介             <-- 一句话定位
  |
  +-- ## Installation           <-- 安装方式 + 前置依赖
  |
  +-- ## Usage                  <-- 基本用法(含 REPL 说明)
  |
  +-- ## Command Groups         <-- 命令组速查表(9 个组 x N 个命令)
  |     +-- Project / Layer / Canvas / Filter / Media
  |     +-- Export / Session / Draw
  |
  +-- ## Examples               <-- 典型工作流示例
  |
  +-- ## State Management       <-- 会话状态说明(undo/redo)
  |
  +-- ## Output Formats         <-- 双格式输出说明
  |
  +-- ## For AI Agents          <-- Agent 使用指南(6 条最佳实践)
  |
  +-- ## Version                <-- 版本号

关键章节解读

(1)YAML Frontmatter — Agent 的触发器

---
name:
 "cli-anything-gimp"
description:
 >-
  Command-line interface for Gimp - A stateful command-line interface
  for image editing, built on Pillow. Designed for AI agents and pow...
---

Agent 平台通过扫描 SKILL.md 的 YAML frontmatter 来判断是否应该激活这个技能。name 和 description 是触发匹配的关键字段。当 Agent 平台发现"用户需要图像编辑"时,会匹配到这个 description 并自动加载此 SKILL。

(2)Command Groups — 能力速查表

每个命令组用 Markdown 表格列出所有子命令:

### Layer

| Command | Description |
|---------|-------------|
| `new` | Create a new blank layer |
| `add-from-file` | Add a layer from an image file |
| `list` | List all layers |
| ...

Agent 通过解析这些表格快速了解 CLI 的能力边界,决定用哪个命令完成任务。这种设计让 Agent 不需要执行 --help 就能预知所有可用命令。

(3)For AI Agents — Agent 专属最佳实践

1. **Always use `--json` flag** for parseable output
2.
 **Check return codes** - 0 for success, non-zero for errors
3.
 **Parse stderr** for error messages on failure
4.
 **Use absolute paths** for all file operations
5.
 **Verify outputs exist** after export operations
6.
 **Review rendered outputs** after offset, draw, blend-mode,
   or filter changes instead of trusting saved project state alone

这 6 条指南是专门为 AI Agent 设计的:告诉 Agent 用什么输出格式、怎么判断成功/失败、怎么处理路径、什么时候需要验证结果。这些是人类开发者通常隐含的知识,对 Agent 来说需要显式说明。

SKILL.md 的生成机制

SKILL.md 不是手写的,而是由 cli-anything-plugin/skill_generator.py(587 行)自动从源码中提取生成的:

gimp_cli.py 中的 Click 装饰器
    @click.group() / @click.command() / @click.option()
         |
         v
skill_generator.py
    1. 正则解析 Click 装饰器 -> 提取命令名、参数、帮助文本
    2. 读取 setup.py -> 提取版本号
    3. 读取 README.md -> 提取系统依赖(apt install 等)
    4. Jinja2 模板渲染 -> 生成完整 SKILL.md
         |
         v
输出两份副本:
    skills/cli-anything-gimp/SKILL.md        <-- 仓库根目录规范副本
    cli_anything/gimp/skills/SKILL.md        <-- 包内副本(随 pip 分发)

这就是为什么 HARNESS.md(Phase 6.5)规定"SKILL.md 由脚本生成"——因为从 Click 装饰器中提取元数据是确定性的,不需要大模型参与。

两份 SKILL.md 的用途对比

副本位置
用途
被谁读取
skills/cli-anything-gimp/SKILL.md
仓库级别的技能索引,Agent 平台通过 npx skills add 安装
本地 Agent 环境(Claude Code、Cursor 等)
cli_anything/gimp/skills/SKILL.md
随 pip 包分发,安装后即可用
已安装 CLI 的用户/Agent,通过 package_data 随包获取

5.4 三者关系:从源码到 Agent 发现的完整链路

开发者编写 gimp_cli.py(Click 命令定义)
    |
    +-- setup.py 定义如何打包
    |       使用 PEP 420 namespace package
    |       声明 console_scripts entry_point
    |       |
    |       v
    |   pip install cli-anything-gimp
    |       -> cli_anything.gimp 安装到 Python 环境
    |       -> cli-anything-gimp 命令出现在 PATH 中
    |       -> skills/SKILL.md 随包分发
    |
    +-- skill_generator.py 自动提取元数据
            -> 生成 skills/cli-anything-gimp/SKILL.md
            -> Agent 平台安装此 SKILL.md
            -> Agent 读取 SKILL.md 知道所有可用命令
            -> Agent 通过 cli-anything-gimp 命令调用
文件
核心职责
解决的问题
gimp_cli.py
定义命令体系
CLI 能做什么
setup.py
定义打包安装
CLI 怎么分发
SKILL.md
定义 Agent 接口
Agent 怎么发现和使用 CLI

6. 快速上手指南 / Quick Start

CLI-Anything 提供两种使用入口,根据你的目标选择:

场景 A:使用现有 CLI 生态(Use Existing CLIs)

适合:想立即使用已有 CLI 的用户或开发者。

# 1. 安装 CLI-Hub 包管理器
pip install cli-anything-hub

# 2. 浏览可用 CLI

cli-hub list
cli-hub search image      # 按关键词搜索
cli-hub info gimp          # 查看某个 CLI 详情

# 3. 安装并使用

cli-hub install gimp
cli-hub launch gimp        # 启动(等价于直接运行 cli-anything-gimp)

# 4. 直接使用(安装后命令已在 PATH 中)

cli-anything-gimp --json project new -w 1920 -h 1080 -o canvas.json
cli-anything-gimp --help

场景 B:让 AI Agent 自动发现并使用 CLI(Agent-Driven Usage)

适合:想让 AI Agent 自主选择合适 CLI 完成任务的场景。

# 1. 安装 CLI-Hub 元技能(给 SKILL 兼容的 Agent 使用)
npx skills add HKUDS/CLI-Anything --skill cli-hub-meta-skill -g -y

# 2. 然后在 Agent 中提示:

#    "在 CLI-Hub 中找到合适的 CLI 并完成以下任务:..."

Agent 会自动:读取 SKILL.md → 发现可用 CLI → 安装 → 调用正确命令。

支持的平台:Claude Code、OpenClaw、Nanobot、Codex、Reasonix、Antigravity 等。

场景 C:为新软件生成 CLI(Build a New CLI)

适合:目标软件还没有对应 CLI,需要从零生成的贡献者。

前提:

  • • Python 3.10+
  • • 目标软件源码(本地路径或 GitHub URL)
  • • 已安装 CLI-Anything 插件的 AI 编程平台

步骤:

# 1. 在 Claude Code 中安装插件
/plugin marketplace add HKUDS/CLI-Anything
/plugin install cli-anything

# 2. 运行主命令,生成完整 CLI(7 阶段自动执行)

/cli-anything /path/to/software-source

# 3. 如需增量改进

/cli-anything:refine /path/to/software-source "specific feature area"

# 4. 如需重新运行测试

/cli-anything:test /path/to/software-source

# 5. 如需校验规范合规性

/cli-anything:validate /path/to/software-source

7. 学习路径建议 / Learning Path

如果你想深入学习这个项目,建议按以下优先级阅读源码:

优先级 1(核心机制,必读)

文件 / 目录
学习目标
cli-hub/cli_hub/registry.py
理解 CLI 的注册、发现、缓存机制
cli-hub/cli_hub/installer.py
理解 CLI 的安装策略分发(pip/npm/uv/bundled)
registry.json
理解 CLI 元数据结构(name / install_cmd / entry_point / skill_md)

优先级 2(一个完整 CLI 的实现)

文件 / 目录
学习目标
gimp/agent-harness/cli_anything/gimp/gimp_cli.py
学习 Click 命令树设计、双格式输出、REPL 实现
gimp/agent-harness/setup.py
学习 PEP 420 namespace package 的打包规范
skills/cli-anything-gimp/SKILL.md
理解 AI Agent 如何发现和理解 CLI

优先级 3(CLI 生成流水线)

文件 / 目录
学习目标
cli-anything-plugin/HARNESS.md
7 阶段流水线的完整规范(最重要的设计文档)
cli-anything-plugin/commands/cli-anything.md
主命令的定义(Agent 读这个知道怎么执行流水线)
cli-anything-plugin/skill_generator.py
SKILL.md 的自动生成逻辑

优先级 4(深入理解)

文件 / 目录
学习目标
cli-anything-plugin/guides/pypi-publishing.md
PyPI 发布规范
cli-anything-plugin/guides/skill-generation.md
SKILL.md 生成指南
cli-anything-plugin/guides/preview-methodology.md
Preview 机制设计
cli-hub/cli_hub/cli.py
CLI-Hub 完整的命令实现(list/search/install/launch/matrix)

8. 项目关键文件索引 / Key Files Reference

核心配置文件

文件路径
说明
registry.json
全局 CLI 注册表:所有 harness CLI 的元数据(name / install_cmd / entry_point / category / contributors)
public_registry.json
第三方公共 CLI 注册表
matrix_registry.json
Matrix(多 CLI 工作流组合)注册表

CLI-Hub 包管理器

文件路径
说明
cli-hub/cli_hub/cli.py
CLI-Hub 主命令入口(list / search / info / install / launch / matrix)
cli-hub/cli_hub/registry.py
注册表获取与缓存(远程 JSON + 本地缓存,TTL 1 小时)
cli-hub/cli_hub/installer.py
安装策略分发(pip / npm / uv / command / bundled)
cli-hub/cli_hub/matrix.py
Matrix 工作流逻辑(多 CLI 组合能力查询)
cli-hub/cli_hub/preview.py
Preview 渲染与检查(HTML 生成、live session)

插件 / CLI 生成工具

文件路径
说明
cli-anything-plugin/HARNESS.md
7 阶段流水线规范(最核心的设计文档)
cli-anything-plugin/commands/cli-anything.md/cli-anything
 主命令定义
cli-anything-plugin/commands/refine.md/cli-anything:refine
 增量改进命令
cli-anything-plugin/commands/test.md/cli-anything:test
 测试命令
cli-anything-plugin/commands/validate.md/cli-anything:validate
 规范校验命令
cli-anything-plugin/commands/list.md/cli-anything:list
 列表命令
cli-anything-plugin/skill_generator.py
SKILL.md 自动生成脚本
cli-anything-plugin/repl_skin.py
统一 REPL 皮肤(复制到各 CLI 中使用)

指南文档

文件路径
适用场景
cli-anything-plugin/guides/pypi-publishing.md
打包发布到 PyPI
cli-anything-plugin/guides/skill-generation.md
SKILL.md 生成与定制
cli-anything-plugin/guides/session-locking.md
Session 文件锁机制
cli-anything-plugin/guides/preview-methodology.md
Preview / Live Preview 设计
cli-anything-plugin/guides/mcp-backend.md
MCP 后端模式(软件有 MCP server 时使用)
cli-anything-plugin/guides/filter-translation.md
视频/音频滤镜翻译(如 MLT → ffmpeg)
cli-anything-plugin/guides/auto-save-dry-run.md
自动保存 + dry-run 模式

典型 CLI 实现(以 GIMP 为例)

文件路径
说明
gimp/agent-harness/setup.py
PyPI 包配置(namespace package 示范)
gimp/agent-harness/cli_anything/gimp/gimp_cli.py
主 CLI 入口(Click 命令树 + REPL)
gimp/agent-harness/cli_anything/gimp/core/project.py
项目管理逻辑
gimp/agent-harness/cli_anything/gimp/core/session.py
有状态会话、撤销/重做
gimp/agent-harness/cli_anything/gimp/core/export.py
导出/渲染管线
skills/cli-anything-gimp/SKILL.md
GIMP CLI 的 AI 技能描述文件

常见问题 / FAQ

Q:必须安装 Claude Code 才能使用 CLI 吗?

不需要。 CLI 生成后是标准的 Python 包,任何人都可以通过 pip install 安装并直接使用,不需要任何 AI 工具或 API Key。Claude Code 只是在生成新 CLI 时需要。

Q:项目需要配置 LLM API Key 吗?

不需要。 大模型的 API Key 由宿主平台(Claude Code / Cursor / Codex)管理。CLI-Anything 本身不调用任何 LLM API。

Q:AI Agent 是怎么知道有哪些命令可用的?

Agent 读取每个 CLI 附带的 SKILL.md 文件。这是一个结构化的 Markdown 文档,列出了所有命令组、参数、示例,专门设计为 AI 可读格式。

Q:为什么选择 CLI 而不是 MCP 或其他协议?

CLI 是人类和 AI Agent 的通用接口:

  • • 结构化、可组合:文本命令与 LLM 格式天然匹配
  • • 轻量、普遍:跨系统工作,依赖最少
  • • 自描述--help 自动提供文档
  • • 确定性强:一致的输出使 Agent 行为可预测

Q:生成 CLI 时,大模型具体做了什么?

阶段
大模型做的事
能否用脚本替代?
Phase 1 代码分析
读懂陌生代码库的架构
不能,每个软件结构不同
Phase 2 架构设计
基于理解设计命令体系
不能,需要判断力
Phase 3 代码实现
写几百到上千行 Python
不能,API 因软件而异
Phase 4-5 测试
设计测试、分析失败、修 bug
部分能(跑 pytest),修 bug 不能
Phase 6.5 SKILL.md
不需要大模型,用脚本生成
Phase 7 打包发布
不需要大模型,标准流程
基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-07-10 10:04:01 HTTP/1.1 GET : https://www.yeyulingfeng.com/a/849703.html
  2. 运行时间 : 0.132912s [ 吞吐率:7.52req/s ] 内存消耗:5,094.85kb 文件加载:145
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=068cd3b4284a7f01ecf19fb66cf37c70
  1. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/autoload_static.php ( 6.05 KB )
  7. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/ralouphie/getallheaders/src/getallheaders.php ( 1.60 KB )
  10. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  11. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  12. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  13. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  14. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  15. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  16. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  17. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  18. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  19. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/guzzlehttp/guzzle/src/functions_include.php ( 0.16 KB )
  21. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/guzzlehttp/guzzle/src/functions.php ( 5.54 KB )
  22. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  23. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  24. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  25. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/provider.php ( 0.19 KB )
  26. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  27. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  28. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  29. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/common.php ( 0.03 KB )
  30. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  32. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/alipay.php ( 3.59 KB )
  33. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  34. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/app.php ( 0.95 KB )
  35. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/cache.php ( 0.78 KB )
  36. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/console.php ( 0.23 KB )
  37. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/cookie.php ( 0.56 KB )
  38. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/database.php ( 2.48 KB )
  39. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/filesystem.php ( 0.61 KB )
  40. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/lang.php ( 0.91 KB )
  41. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/log.php ( 1.35 KB )
  42. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/middleware.php ( 0.19 KB )
  43. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/route.php ( 1.89 KB )
  44. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/session.php ( 0.57 KB )
  45. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/trace.php ( 0.34 KB )
  46. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/view.php ( 0.82 KB )
  47. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/event.php ( 0.25 KB )
  48. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  49. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/service.php ( 0.13 KB )
  50. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/AppService.php ( 0.26 KB )
  51. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  52. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  53. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  54. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  55. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  56. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/services.php ( 0.14 KB )
  57. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  58. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  59. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  60. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  61. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  62. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  63. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  64. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  65. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  66. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  67. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  68. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  69. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  70. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  71. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  72. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  73. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  74. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  75. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  76. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  77. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  78. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  79. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  80. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  81. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  82. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  83. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  84. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  85. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  86. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  87. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/Request.php ( 0.09 KB )
  88. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  89. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/middleware.php ( 0.25 KB )
  90. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  91. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  92. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  93. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  94. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  95. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  96. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  97. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  98. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  99. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  100. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  101. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  102. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  103. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/route/app.php ( 3.94 KB )
  104. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  105. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  106. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/controller/Index.php ( 9.87 KB )
  108. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/BaseController.php ( 2.05 KB )
  109. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  110. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  111. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  112. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  113. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  114. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  115. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  116. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  117. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  118. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  119. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  120. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  121. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  122. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  123. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  124. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  125. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  126. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  127. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  128. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  129. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  130. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  131. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  132. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  133. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  134. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  135. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/controller/Es.php ( 3.30 KB )
  136. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  137. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  138. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  139. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  140. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  141. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  142. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  143. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  144. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/runtime/temp/c935550e3e8a3a4c27dd94e439343fdf.php ( 31.50 KB )
  145. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000836s ] mysql:host=127.0.0.1;port=3306;dbname=wenku;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000940s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000367s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000293s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000474s ]
  6. SELECT * FROM `set` [ RunTime:0.000207s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000634s ]
  8. SELECT * FROM `article` WHERE `id` = 849703 LIMIT 1 [ RunTime:0.000688s ]
  9. UPDATE `article` SET `lasttime` = 1783649041 WHERE `id` = 849703 [ RunTime:0.011832s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 64 LIMIT 1 [ RunTime:0.000330s ]
  11. SELECT * FROM `article` WHERE `id` < 849703 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000565s ]
  12. SELECT * FROM `article` WHERE `id` > 849703 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000481s ]
  13. SELECT * FROM `article` WHERE `id` < 849703 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.002102s ]
  14. SELECT * FROM `article` WHERE `id` < 849703 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.001894s ]
  15. SELECT * FROM `article` WHERE `id` < 849703 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.016549s ]
0.135802s