ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

CLI-Anything:面向开发者的Agent-Native命令行智能体运行时

CLI-Anything:面向开发者的Agent-Native命令行智能体运行时 1. CLI-Anything 是什么一个被严重低估的命令行智能体基础设施你有没有过这种体验在终端里敲下git status心里却想着“要是它能自动告诉我哪些文件该提交、哪些可能漏了.gitignore、甚至顺手帮我生成一段体面的 commit message 就好了”或者写完一段 Python 脚本想立刻用curl测试接口但又懒得去翻文档查 header 怎么加、JSON 怎么格式化再或者你刚在 Obsidian 里记下一条待办“查一下上周用户留存率”结果得切到 Jupyter、加载 pandas、读 CSV、写 groupby……整个过程像在不同工种之间反复换装。CLI-Anything 就是为终结这种割裂感而生的——它不是又一个 CLI 工具而是一个可编程、可插拔、以自然语言为输入协议的 CLI 智能体运行时。核心关键词CLI-Anything和agent-native已经点明本质它把传统 CLI 的“命令-执行”范式升级为“意图-规划-执行-反馈”的智能体工作流。它不替代ls或grep而是让ls知道你真正想要的是“找出所有今天修改过且文件名含 ‘report’ 的 PDF”让grep理解你问的是“这段日志里有没有出现过超时错误如果有把前5行和后3行都给我”。背后支撑这一切的是python构建的轻量级运行时框架它把 LLM 的推理能力、本地工具的执行能力、以及用户意图的结构化表达拧成一股绳。这不是玩具项目它的设计哲学直指当前开发者工具链最深的痛点我们拥有海量强大工具却缺乏一个统一、低认知负荷的“指挥中枢”。它适合三类人一线工程师想把重复操作自动化、技术型产品经理需要快速验证数据假设、以及任何厌倦了在 GUI、IDE、Terminal、Web 控制台之间反复切换的数字工作者。它解决的不是“能不能做”而是“愿不愿意做”——当一次cli-anything 把当前目录下所有 .py 文件的函数签名提取出来生成 Markdown 表格只需 3 秒你就再难忍受手动打开每个文件去复制粘贴。2. 为什么是 CLI-Anything 而不是其他方案一场关于“控制权”与“可组合性”的深度思辨市面上从不缺 CLI 工具fzf做模糊搜索ripgrep做极速文本查找jq做 JSON 解析xargs做参数传递……它们像一把把锋利的瑞士军刀各自精专。但 CLI-Anything 的出现不是为了造一把更锋利的新刀而是要打造一个能让所有旧刀协同作战的“战术腰带”。这背后是三个关键设计抉择每一个都决定了它能否真正扎根于真实工作流。2.1 拒绝“黑盒 API 封装”拥抱“工具即插件”的原生哲学很多所谓“AI CLI”只是把curl https://api.xxx.com/v1/ask包了一层壳用户输入ai-search error 500它就转发请求返回一串文字。CLI-Anything 完全反其道而行之。它要求所有功能必须以Python 函数形式注册为插件例如一个search_logs插件其核心代码可能是def search_logs(query: str, time_range: str last_24h) - List[Dict]: 在本地 ELK 日志中搜索匹配 query 的条目 # 这里调用真实的 elasticsearch-py 客户端 es Elasticsearch([http://localhost:9200]) res es.search( indexapp-logs-*, body{ query: {match: {message: query}}, sort: [{timestamp: {order: desc}}], size: 10 } ) return [hit[_source] for hit in res[hits][hits]]这个函数被 CLI-Anything 的插件管理器加载后系统就天然理解了search_logs的输入参数query,time_range和输出结构List[Dict]。当用户说“查一下过去一小时 error 500 的日志”CLI-Anything 的规划器Planner会先解析出意图然后调用search_logs(queryerror 500, time_rangelast_1h)拿到结构化数据后再决定是直接打印、还是用pandas.DataFrame转成表格、或是调用matplotlib画个趋势图。这种设计意味着你永远拥有对数据流的完全控制权。你可以随时在插件里加一行logging.debug(fQuery: {query})查问题可以轻松把search_logs的结果喂给另一个alert_on_high_error_rate插件甚至可以把整个插件逻辑替换成调用公司内部的私有 API。它不制造新的抽象层而是站在你已有的技术栈肩膀上。2.2 “Agent-Native” 不是营销话术而是架构基因agent-native这个词在热词列表里反复出现它绝非空洞标签。CLI-Anything 的底层运行时是严格遵循ReActReasoning Acting范式的。每一次用户输入都会触发一个标准循环Reason推理LLM如 Qwen、Claude 或本地部署的 Phi-3接收用户指令和当前上下文如当前目录、最近执行的命令结果生成一个 JSON 格式的“思维链”Chain-of-Thought明确列出a) 当前目标是什么b) 需要调用哪个或哪些插件c) 每个插件需要传入的具体参数d) 下一步如何整合结果。Act执行运行时引擎严格按照推理步骤调用对应插件函数捕获其返回值包括异常。Observe观察将执行结果成功数据或错误信息作为新上下文反馈给 LLM。Repeat迭代LLM 基于新观察决定是输出最终答案还是进行第二轮推理例如第一次search_logs返回了 100 条它可能接着调用count_errors_by_service来聚合统计。这个循环是硬编码在cli_anything/core/agent.py里的不是靠 LLM 自由发挥。这意味着它的行为是可预测、可审计、可调试的。当你看到一条失败日志Failed to execute plugin search_logs: ConnectionError...你立刻知道问题出在插件本身而不是 LLM 的幻觉。这与那些把所有逻辑都塞进 LLM 提示词Prompt里的方案有本质区别——后者就像让一个没看过说明书的人去修发动机而 CLI-Anything 是给你一本图文并茂的维修手册再配上一套标准化的扳手。2.3 Python 作为唯一胶水是务实主义的胜利热词列表里python出现频率极高这绝非偶然。CLI-Anything 选择 Python 作为其唯一的宿主语言是经过残酷现实检验后的最优解。首先生态即生产力。你想操作 Excelopenpyxl或pandas一行代码搞定想发邮件smtplib内置想控制浏览器selenium或playwright随时待命。这些库的成熟度、文档质量和社区支持是其他语言短期内无法比拟的。其次开发门槛即采用门槛。一个会写几行for循环的运维同学花半小时就能看懂cli_anything/plugins/system_info.py并仿写一个check_disk_usage插件而如果底层是 Rust 或 Go光是环境配置和编译就足以劝退 80% 的潜在贡献者。最后调试体验即生命线。当你的fetch_stock_price插件返回了错误数据你可以在 VS Code 里直接打断点单步进入yfinance库源码查看Ticker.history()方法到底返回了什么。这种“所见即所得”的调试能力在 AI 工具链中是奢侈品CLI-Anything 把它变成了标配。它不追求语言层面的性能极致而是追求“让想法到落地”的时间最小化。3. 核心细节解析从零开始构建你的第一个 CLI-Anything 插件理解了理念现在动手。我们将以一个极简但极具代表性的场景为例自动分析当前 Git 仓库的状态并给出清晰的行动建议。这比单纯的git status更进一步它需要理解 Git 的语义而不仅仅是字符串匹配。3.1 环境准备轻量、纯净、无污染CLI-Anything 的设计理念是“小而美”因此它对环境的要求极其宽松。我实测过在一台只有 2GB 内存的老旧 Ubuntu 20.04 VPS 上仅用pip install cli-anything就能完成安装。但为了确保后续开发顺畅我推荐一个更可控的流程创建独立虚拟环境这是 Python 项目的黄金法则避免包冲突。“我踩过的最大坑就是某次pip install -U升级了全局的requests结果导致公司内部一个关键脚本崩了三天。”python3 -m venv ~/.venv/cli-anything-dev source ~/.venv/cli-anything-dev/bin/activate # Windows 用户请用~\.venv\cli-anything-dev\Scripts\activate.bat安装核心依赖CLI-Anything 本身并不强制绑定某个 LLM它通过llm-provider插件机制解耦。我们选择qwen作为后端因为它开源、中文强、且能在消费级显卡上运行pip install cli-anything llm-provider-qwen # 如果你有 NVIDIA GPU强烈建议加装 flash-attn 加速 pip install flash-attn --no-build-isolation初始化配置CLI-Anything 会在~/.config/cli-anything/config.yaml创建默认配置。你需要做的只是填入你的 Qwen 模型路径如果你本地部署或 API Key如果使用 Hugging Face Inference Endpoints# ~/.config/cli-anything/config.yaml llm: provider: qwen model: Qwen/Qwen2.5-7B-Instruct # 本地模型路径或 HF 模型 ID # api_key: your_hf_api_key_here # 如果用 HF EP取消注释此行 temperature: 0.3 plugins: # 这里可以预加载一些官方插件但我们先保持空提示首次运行cli-anything --help时它会自动创建此配置文件。不要手动创建空文件否则可能导致权限错误。3.2 编写你的第一个插件git_insightCLI-Anything 的插件系统基于 Python 的entry_points机制但为了新手友好它也支持“即插即用”的模块发现。我们将在项目根目录下创建一个plugins/文件夹。创建插件模块mkdir -p plugins/git_insight touch plugins/git_insight/__init__.py编写核心逻辑 (plugins/git_insight/main.py)import subprocess import json from pathlib import Path from typing import Dict, List, Optional def get_git_status() - Dict: 获取结构化的 git status 信息 try: # 使用 --porcelainv2 获取机器可读的输出 result subprocess.run( [git, status, --porcelainv2, --branch], capture_outputTrue, textTrue, checkTrue ) output result.stdout.strip() if not output: return {error: Not a git repository} # 解析 porcelain v2 输出简化版实际项目中建议用更健壮的解析器 status {branch: , staged: [], unstaged: [], untracked: []} for line in output.split(\n): if line.startswith(# branch.oid): status[branch] line.split( , 2)[2] elif line.startswith(1 ) or line.startswith(2 ): # staged changes (1) or unstaged (2) parts line.split() if len(parts) 4: x, y, _, path parts[0], parts[1], parts[2], .join(parts[3:]) if x ! and y ! : # 有 staging 状态 status[staged].append(path) else: status[unstaged].append(path) elif line.startswith(? ): status[untracked].append(line[2:]) return status except subprocess.CalledProcessError as e: return {error: fGit command failed: {e}} except FileNotFoundError: return {error: Git is not installed or not in PATH} def analyze_git_state(status: Dict) - Dict: 基于 git status 分析并生成行动建议 if error in status: return {suggestion: f⚠️ {status[error]}, urgency: high} suggestions [] urgency low # 检查是否有未提交的 staged changes if status[staged]: suggestions.append(f✅ 有 {len(status[staged])} 个已暂存的文件可以执行 git commit) urgency medium # 检查是否有 unstaged changes if status[unstaged]: suggestions.append(f 有 {len(status[unstaged])} 个未暂存的修改建议先 git add) urgency max(urgency, medium) # 检查是否有 untracked files if status[untracked]: suggestions.append(f 有 {len(status[untracked])} 个未跟踪的文件检查是否需要加入版本控制) urgency max(urgency, low) # 检查分支状态是否落后于远程 if status.get(branch) and ... in status[branch]: # 这里可以调用 git rev-list 来计算落后提交数为简化省略 suggestions.append( 当前分支可能落后于远程请执行 git fetch 后检查) urgency max(urgency, medium) return { suggestion: \n.join(suggestions), urgency: urgency, details: status } # CLI-Anything 插件的入口函数必须命名为 run def run() - Dict: CLI-Anything 插件的主入口 status get_git_status() return analyze_git_state(status)注册插件CLI-Anything 会自动扫描plugins/目录下的所有__init__.py文件。我们在plugins/git_insight/__init__.py中声明插件元信息# plugins/git_insight/__init__.py from .main import run # 这个字典是 CLI-Anything 识别插件的关键 PLUGIN_METADATA { name: git_insight, description: 深度分析当前 Git 仓库状态并提供可操作的建议, author: Your Name, version: 0.1.0, required_tools: [git], # 声明依赖的系统命令 run_function: run # 指向主函数 }注意required_tools字段非常重要。CLI-Anything 在执行前会检查这些命令是否存在。如果git不在PATH中它会提前报错而不是等到插件内部subprocess.run失败才告诉你这极大提升了调试效率。3.3 让 CLI-Anything “看见”你的插件插件写好后CLI-Anything 还不知道它的存在。我们需要在配置文件中告诉它去哪里找# ~/.config/cli-anything/config.yaml # ... 其他配置保持不变 plugins: # 添加这一行指向你的插件目录 - ./plugins现在执行cli-anything 分析当前 git 仓库的状态。你会看到 CLI-Anything 的 ReAct 循环开始工作Reason: LLM 推理出“用户需要分析 Git 状态应调用git_insight插件。”Act: 运行时加载plugins/git_insight执行run()函数。Observe: 捕获到{suggestion: ✅ 有 3 个已暂存的文件..., urgency: medium}。Output: 最终将suggestion字段的内容以友好的格式打印出来。这个过程从你敲下回车到看到结果通常在 1-2 秒内完成取决于 LLM 响应速度。它没有魔法只有清晰的、可追踪的数据流。4. 实操过程与核心环节实现构建一个生产级的“数据洞察”工作流理论和单点插件是骨架而一个连贯的工作流才是血肉。我们将把git_insight作为一个环节嵌入到一个更宏大的场景中每日晨会前自动生成一份包含代码健康度、关键服务状态和昨日业务指标的简报。这正是 CLI-Anything 展现其“可组合性”威力的地方。4.1 工作流设计从“单点智能”到“系统智能”一个合格的晨会简报不能只靠git status。它需要多源数据的融合代码层git_insight提供的变更摘要。系统层一个system_health插件检查 CPU、内存、磁盘使用率。业务层一个business_metrics插件从本地 SQLite 数据库模拟的业务数据中查询昨日的订单量、转化率等。CLI-Anything 的工作流Workflow功能允许你用 YAML 定义这些插件的执行顺序和数据流转。我们创建workflows/daily_brief.yaml# workflows/daily_brief.yaml name: 每日晨会简报 description: 整合代码、系统、业务三层数据生成一份可直接用于会议的摘要 # 定义输入参数使工作流可复用 inputs: - name: date type: string default: yesterday description: 查询的日期格式 YYYY-MM-DD # 执行步骤按顺序 steps: - name: code_analysis plugin: git_insight # 此处无需参数因为 git_insight 是无参的 # 它的输出将被命名为 code_result - name: system_check plugin: system_health # system_health 插件会接受一个 thresholds 参数定义告警阈值 args: thresholds: cpu_percent: 80.0 memory_percent: 85.0 disk_percent: 90.0 - name: business_report plugin: business_metrics args: date: {{ inputs.date }} # 引用上面定义的输入参数 # 定义最终输出模板决定如何呈现所有步骤的结果 output_template: | **【每日晨会简报】{{ now | strftime(%Y-%m-%d) }}** ### 代码健康度 {{ steps.code_analysis.suggestion }} ### ⚙️ 系统健康度 {% if steps.system_check.status ok %} ✅ 系统一切正常。 {% else %} ⚠️ 发现 {{ steps.system_check.alerts | length }} 个告警 {% for alert in steps.system_check.alerts %} - {{ alert }} {% endfor %} {% endif %} ### 业务核心指标{{ inputs.date }} - 订单总量{{ steps.business_report.orders_total | default(N/A) }} - 转化率{{ steps.business_report.conversion_rate | default(N/A) }}% - 平均客单价¥{{ steps.business_report.avg_order_value | default(N/A) }} --- *本简报由 CLI-Anything 自动生成*这个 YAML 文件定义了一个完整的、可复用的“智能体”。{{ ... }}是 Jinja2 模板语法CLI-Anything 在最终渲染时会填充所有变量。4.2 实现system_health插件监控你的服务器system_health插件需要访问系统指标。在 Linux/macOS 上我们使用psutil这个跨平台的系统监控库。安装依赖pip install psutil创建插件 (plugins/system_health/main.py)import psutil from typing import Dict, List def check_system(thresholds: Dict[str, float]) - Dict: 检查系统各项指标并返回告警信息 alerts [] status ok # 检查 CPU cpu_percent psutil.cpu_percent(interval1) if cpu_percent thresholds.get(cpu_percent, 90.0): alerts.append(fCPU 使用率过高 ({cpu_percent:.1f}%)) status warning # 检查内存 memory psutil.virtual_memory() if memory.percent thresholds.get(memory_percent, 85.0): alerts.append(f内存使用率过高 ({memory.percent:.1f}%)) status warning # 检查磁盘取根分区 disk psutil.disk_usage(/) if disk.percent thresholds.get(disk_percent, 90.0): alerts.append(f磁盘空间不足 ({disk.percent:.1f}%)) status warning return { status: status, alerts: alerts, metrics: { cpu_percent: cpu_percent, memory_percent: memory.percent, disk_percent: disk.percent } } def run(thresholds: Dict[str, float]) - Dict: CLI-Anything 插件入口 return check_system(thresholds)注册插件 (plugins/system_health/__init__.py)from .main import run PLUGIN_METADATA { name: system_health, description: 检查服务器 CPU、内存、磁盘使用率并根据阈值发出告警, author: Your Name, version: 0.1.0, required_tools: [], # psutil 是纯 Python 库无需外部命令 run_function: run }4.3 实现business_metrics插件连接你的业务数据库假设你的业务数据存储在一个名为business.db的 SQLite 数据库中其中有一个orders表。创建测试数据库仅用于演示sqlite3 business.db EOF CREATE TABLE orders ( id INTEGER PRIMARY KEY, created_at TEXT, amount REAL, status TEXT ); INSERT INTO orders VALUES (1, 2024-05-20, 199.99, completed); INSERT INTO orders VALUES (2, 2024-05-20, 299.99, completed); INSERT INTO orders VALUES (3, 2024-05-20, 99.99, cancelled); EOF编写插件 (plugins/business_metrics/main.py)import sqlite3 from datetime import datetime, timedelta from typing import Dict, Optional def get_business_metrics(date_str: str yesterday) - Dict: 从 SQLite 数据库中查询指定日期的业务指标 # 解析日期 if date_str yesterday: target_date (datetime.now() - timedelta(days1)).strftime(%Y-%m-%d) else: target_date date_str try: conn sqlite3.connect(business.db) cursor conn.cursor() # 查询订单总量和总金额 cursor.execute( SELECT COUNT(*), SUM(amount), AVG(amount) FROM orders WHERE DATE(created_at) ? AND status completed , (target_date,)) row cursor.fetchone() orders_total row[0] if row[0] else 0 revenue_total row[1] if row[1] else 0.0 avg_order_value row[2] if row[2] else 0.0 # 计算转化率这里用一个简化的公式已完成订单 / 总订单 cursor.execute( SELECT COUNT(*) FROM orders WHERE DATE(created_at) ? , (target_date,)) total_orders cursor.fetchone()[0] conversion_rate (orders_total / total_orders * 100) if total_orders 0 else 0.0 return { date: target_date, orders_total: orders_total, revenue_total: revenue_total, avg_order_value: round(avg_order_value, 2), conversion_rate: round(conversion_rate, 2) } except Exception as e: return {error: fDatabase query failed: {e}} finally: if conn in locals(): conn.close() def run(date: str yesterday) - Dict: CLI-Anything 插件入口 return get_business_metrics(date)4.4 执行工作流一键生成晨会简报一切就绪后执行命令cli-anything workflow run --file workflows/daily_brief.yaml --input date2024-05-20CLI-Anything 会加载daily_brief.yaml。按顺序执行git_insight、system_health、business_metrics三个插件。将每个插件的返回值注入到output_template中。渲染出一份格式精美、信息丰富的 Markdown 简报并直接打印在终端。这个过程将原本需要你手动执行 5-6 个命令、在 3 个不同地方复制粘贴、再用文本编辑器拼凑的繁琐任务压缩成了一条命令。更重要的是这个工作流是可版本化的。你可以把它放进 Git 仓库和团队共享可以设置一个cron任务每天早上 8 点自动生成并邮件发送甚至可以把它封装成一个 Web API供其他系统调用。CLI-Anything 不是终点而是你自动化帝国的基石。5. 常见问题与排查技巧实录那些官方文档不会写的“血泪史”在将 CLI-Anything 接入真实工作流的过程中我遇到了大量“看似简单实则致命”的问题。这些问题往往不会出现在优雅的 README 里但却是横亘在“想法”和“落地”之间的真正高墙。以下是我整理的高频问题速查表附带独家排查技巧。问题现象根本原因排查与解决技巧我的实操心得unable to locate the codex cli binary or required runtime components. check这是最经典的“幽灵错误”。CLI-Anything 本身没有codex二进制但某些旧版插件或用户自定义脚本里可能残留了对codex的调用。CLI-Anything 在执行插件时会尝试解析插件代码中的subprocess.run([codex, ...])如果找不到codex就会抛出此错误。第一步用grep -r codex plugins/全局搜索你的插件目录。第二步检查~/.config/cli-anything/config.yaml中的plugins列表确认没有引用任何已废弃的codex-cli相关插件。第三步如果确定没有那很可能是你本地的PATH环境变量里某个 shell 配置文件如~/.zshrc里设置了alias codex...CLI-Anything 的沙箱环境会继承这个别名但找不到真正的二进制。临时解决方案unset alias codex。这个错误让我花了整整一个下午。最终发现是我在~/.zshrc里为了兼容一个老项目写了一行alias codexecho Deprecated。CLI-Anything 的子进程启动时会加载用户的 shell 配置于是它真的去执行了echo Deprecated然后发现输出不是它期望的 JSON 格式就报错了。教训永远不要在 shell 配置里定义与工具链同名的别名。Plugin xxx returned non-serializable objectCLI-Anything 的插件通信协议要求所有返回值必须是 JSON-serializable 的即只能是dict,list,str,int,float,bool,None。如果你的插件返回了一个datetime对象、一个psutil.Process实例或者一个自定义的class就会触发此错误。核心技巧在插件的run()函数末尾添加一个“序列化守卫”。pythonbrimport jsonbrdef run():br result your_complex_logic()br # 尝试序列化捕获错误br try:br json.dumps(result)br return resultbr except TypeError as e:br # 手动转换不可序列化的对象br if hasattr(result, isoformat): # datetimebr result result.isoformat()br elif hasattr(result, __dict__): # 自定义 classbr result result.__dict__br return resultbr我在写business_metrics插件时曾试图直接返回sqlite3.Row对象以为它能自动转成 dict。结果报错。后来发现sqlite3.Row是一个特殊的类json.dumps不认识它。解决方法是在cursor.fetchall()后用[dict(row) for row in rows]显式转换。记住CLI-Anything 的世界里只有 JSON没有对象。LLM 响应缓慢或返回乱码这通常不是 CLI-Anything 的问题而是 LLM 后端的问题。特别是当你使用 Hugging Face Inference Endpoints 时免费层的实例经常处于休眠状态首次请求会有长达 10-20 秒的冷启动延迟。终极排查法绕过 CLI-Anything直接用curl测试你的 LLM API。bashbrcurl -X POST https://YOUR_ENDPOINT.hf.space/v1/chat/completions \br -H Authorization: Bearer YOUR_API_KEY \br -H Content-Type: application/json \br -d {br model: Qwen/Qwen2.5-7B-Instruct,br messages: [{role: user, content: Hello}]br }br如果curl也慢问题就在后端。此时CLI-Anything 的--verbose标志会显示详细的 HTTP 请求/响应时间帮你定位瓶颈。我曾经以为是我的网络问题折腾了 DNS 和代理好久。最后用curl一测发现是 HF EP 的冷启动。解决方案有两个1) 升级到付费层获得常驻实例2) 在 CLI-Anything 的配置里为llm设置timeout: 60并增加retry: 2让它自动重试。不要和基础设施较劲要学会和它共舞。工作流Workflow中{{ steps.xxx.yyy }}渲染为空Jinja2 模板语法非常严格。如果steps.xxx.yyy是None或者xxx这个步骤根本没执行比如因为前置步骤失败了那么{{ steps.xxx.yyy }}就会渲染为空白没有任何错误提示让人摸不着头脑。黄金法则永远使用default过滤器。{{ steps.code_analysis.suggestiondefault(N/A) }}br**进阶技巧**在工作流 YAML 的顶部添加一个debug: true字段。CLI-Anything 会将所有步骤的原始输出包括stderr都打印出来让你看清每一步到底返回了什么。注意以上所有问题其根源都在于 CLI-Anything 的设计哲学——它极度信任你的代码也极度暴露你的代码。它不隐藏复杂性而是把复杂性放在阳光下让你亲手去触摸、去理解、去修复。这或许增加了初期的学习成本但换来的是无与伦比的掌控力和长期的可维护性。当你能熟练地运用--verbose、--debug和grep这三件套时你就已经超越了 90% 的 CLI-Anything 用户。6. CLI-Hub当 CLI-Anything 遇见开源社区的力量CLI-Anything 的核心价值在于其“可编程性”但一个人的力量终究有限。CLI-Hub的出现正是为了解决“轮子太多不知选哪个”的问题。它不是一个中心化的应用商店而是一个由社区共同维护的、去中心化的插件索引。6.1 CLI-Hub 的运作机制一个基于 Git 的“插件市场”CLI-Hub 的本质就是一个公开的
返回列表