目录

OpenCLI:轻量级AI命令行框架

OpenCLI:轻量级AI命令行框架

1. 学习目标

通过本文你将掌握:

  • 理解 OpenCLI 的设计理念和架构
  • 熟练安装和使用 OpenCLI 开发 CLI 工具
  • 掌握 AI 集成的使用方法
  • 开发自定义命令和扩展
  • 最佳实践和性能优化

2. 项目概述

2.1 什么是 OpenCLI

OpenCLI 是一个用 Go 语言编写的轻量级 CLI 框架:

“A fast, lightweight CLI framework with AI support”

核心特点

特性说明
轻量约 2MB 二进制文件,无外部依赖
快速启动时间 < 10ms
AI 集成内置 AI 对话和命令生成
模块化可插拔的 AI 提供商
简单5 分钟上手

2.2 与 AutoCLI 的区别

项目定位语言AI 集成方式
OpenCLICLI 框架Go 100%内置 AI 包
AutoCLI自然语言生成 CLIGo 100%Prompt 驱动

选择建议

  • 想快速构建 CLI 工具 → OpenCLI
  • 想用自然语言生成 CLI → AutoCLI

2.3 技术栈

├── Go 100%
├── MIT License
├── 无外部依赖
├── 模块化架构
│   ├── cli - 核心框架
│   ├── ai - AI 集成
│   ├── parser - 命令解析
│   └── generator - 代码生成
└── 支持多 AI 提供商

3. 系统架构

3.1 架构概览

┌─────────────────────────────────────┐
│           OpenCLI User              │
│     (命令行输入 / AI 对话)          │
├─────────────────────────────────────┤
│           CLI Layer                 │
│    命令解析 + 参数处理 + 输出        │
├─────────────────────────────────────┤
│           AI Layer                  │
│   AI 提供商抽象 + Prompt 管理        │
├─────────────────────────────────────┤
│         Provider Plugins             │
│  OpenAI / Claude / Gemini / Ollama  │
└─────────────────────────────────────┘

3.2 核心模块

cli 包 — 核心框架:

import "github.com/jackwener/opencli/cli"

func main() {
    app := cli.New("myapp", "A sample CLI")
    
    app.Command("greet", "Greet someone", func(c *cli.Context) error {
        name := c.String("name", "World")
        fmt.Printf("Hello, %s!\n", name)
        return nil
    })
    
    app.Run(os.Args)
}

ai 包 — AI 集成:

import "github.com/jackwener/opencli/ai"

func main() {
    // 创建 AI 客户端
    client := ai.New(ai.OpenAI,
        ai.WithAPIKey(os.Getenv("OPENAI_API_KEY")),
    )
    
    // 对话
    resp, err := client.Chat("Hello!")
    fmt.Println(resp)
}

parser 包 — 命令解析:

import "github.com/jackwener/opencli/parser"

cmd, err := parser.Parse("greet --name John")
// → Command{Name: "greet", Args: [], Flags: {name: "John"}}

generator 包 — 代码生成:

import "github.com/jackwener/opencli/generator"

code, err := generator.FromPrompt("Create a tool to fetch weather")
// → 生成完整的 Go CLI 代码

3.3 AI 提供商抽象

OpenCLI 使用统一的 AI 接口:

type Provider interface {
    Chat(ctx context.Context, msg string) (string, error)
    Generate(ctx context.Context, prompt string) (string, error)
    Embeddings(ctx context.Context, text string) ([]float64, error)
}

内置提供商

提供商实现配置
OpenAIOpenAI ProviderOPENAI_API_KEY
ClaudeAnthropic ProviderANTHROPIC_API_KEY
GeminiGoogle ProviderGOOGLE_API_KEY
OllamaLocal ProviderOLLAMA_BASE_URL

4. 安装与配置

4.1 环境要求

  • Go 1.21+
  • Git

4.2 安装步骤

二进制安装

# macOS / Linux
curl -fsSL https://raw.githubusercontent.com/jackwener/opencli/main/install.sh | bash

# Windows
iwr https://raw.githubusercontent.com/jackwener/opencli/main/install.ps1 | iex

源码安装

go install github.com/jackwener/opencli@latest

源码构建

git clone https://github.com/jackwener/opencli.git
cd opencli
go build -o opencli .

4.3 配置 AI 提供商

环境变量

# OpenAI (默认)
export OPENAI_API_KEY=sk-...

# Anthropic Claude
export ANTHROPIC_API_KEY=sk-ant-...

# Google Gemini
export GOOGLE_API_KEY=AIza...

# Ollama (本地)
export OLLAMA_BASE_URL=http://localhost:11434

配置文件 (~/.opencli.yaml):

ai:
  provider: openai
  model: gpt-4o
  temperature: 0.7

cli:
  prompt: "You are a helpful CLI assistant"
  history: true
  history_size: 100

5. 使用指南

5.1 创建新 CLI 项目

方式一:命令行生成

opencli new myapp
cd myapp
go build -o myapp .
./myapp --help

方式二:手动创建

package main

import (
    "fmt"
    "github.com/jackwener/opencli/cli"
)

func main() {
    app := cli.New("myapp", "My awesome CLI")
    
    app.Command("greet", "Greet someone", greetHandler)
    
    app.Run()
}

func greetHandler(c *cli.Context) error {
    name := c.String("name", "World")
    fmt.Printf("Hello, %s!\n", name)
    return nil
}

5.2 AI 对话模式

# 启动 AI 对话
opencli chat

# 或单次查询
opencli ask "How do I parse JSON in Go?"

5.3 命令生成

# 自然语言生成命令
opencli generate "Create a tool to fetch weather for a city"

# 指定输出文件
opencli generate "Create a tool to backup databases" --output backup.go

5.4 内置命令

命令说明
opencli new <name>创建新项目
opencli chat启动 AI 对话
opencli ask <prompt>单次 AI 查询
opencli generate <prompt>从 Prompt 生成代码
opencli completion <shell>生成 Shell 补全脚本

6. 开发扩展

6.1 自定义命令

app.Command("weather", "Get weather for a city", func(c *cli.Context) error {
    city := c.String("city", "")
    if city == "" {
        return fmt.Errorf("city is required")
    }
    
    // 调用天气 API
    weather, err := fetchWeather(city)
    if err != nil {
        return err
    }
    
    fmt.Printf("Weather in %s: %s\n", city, weather)
    return nil
})

// 注册 flag
app.String("city", "", "City name")

6.2 自定义 AI 提供商

// 实现 Provider 接口
type CustomProvider struct {
    APIKey string
    Endpoint string
}

func (p *CustomProvider) Chat(ctx context.Context, msg string) (string, error) {
    // 调用自定义 AI API
    resp, err := http.Post(p.Endpoint, "application/json", 
        strings.NewReader(fmt.Sprintf(`{"message":"%s"}`, msg)))
    // 处理响应...
    return respText, nil
}

// 注册提供商
ai.RegisterProvider("custom", &CustomProvider{APIKey: "..."})

6.3 中间件

// 日志中间件
app.Use(func(next cli.Handler) cli.Handler {
    return func(c *cli.Context) error {
        start := time.Now()
        err := next(c)
        fmt.Printf("Command %s took %v\n", c.Command(), time.Since(start))
        return err
    }
})

// 认证中间件
app.Use(func(next cli.Handler) cli.Handler {
    return func(c *cli.Context) error {
        if !isAuthenticated() {
            return fmt.Errorf("authentication required")
        }
        return next(c)
    }
})

6.4 插件系统

# 安装插件
opencli plugin install github.com/user/myplugin

# 使用插件
opencli myplugin command

插件开发

package myplugin

import "github.com/jackwener/opencli"

func init() {
    opencli.RegisterPlugin(opencli.Plugin{
        Name: "myplugin",
        Commands: []opencli.Command{
            {Name: "myplugin cmd", Handler: myHandler},
        },
    })
}

7. 最佳实践

7.1 项目结构

mycli/
├── cmd/
│   ├── root.go
│   ├── greet.go
│   └── weather.go
├── internal/
│   └── api/
├── go.mod
├── go.sum
└── main.go

main.go

package main

import (
    "github.com/jackwener/opencli/cli"
    "mycli/cmd"
)

func main() {
    app := cli.New("mycli", "My CLI tool")
    
    app.Command("greet", "Greet someone", cmd.GreetHandler)
    app.Command("weather", "Get weather", cmd.WeatherHandler)
    
    app.Run()
}

7.2 错误处理

app.Command("risky", "A risky command", func(c *cli.Context) error {
    result, err := doRiskyThing()
    if err != nil {
        // 返回用户友好的错误
        return cli.Exit("Operation failed: " + err.Error(), 1)
    }
    return nil
})

7.3 性能优化

优化项方法
减少依赖使用标准库替代外部包
并行处理使用 goroutine 并行执行独立任务
缓存缓存 AI 响应减少 API 调用
懒加载按需加载命令和插件

缓存示例

cache := ai.NewCache(ai.CacheOptions{
    MaxSize: 100,
    TTL:    time.Hour,
})

client := ai.New(ai.OpenAI,
    ai.WithCache(cache),
)

7.4 测试

package cmd

import (
    "testing"
    "github.com/jackwener/opencli/cli"
)

func TestGreetHandler(t *testing.T) {
    app := cli.New("test", "")
    app.Command("greet", "", GreetHandler)
    
    // 模拟执行
    err := app.Run([]string{"greet", "--name", "World"})
    if err != nil {
        t.Errorf("unexpected error: %v", err)
    }
}

8. 与其他框架对比

框架语言二进制大小AI 集成学习曲线
OpenCLIGo~2MB内置
CobraGo~10MB
ClickPythonN/A
AutoCLIGo~5MBPrompt 驱动

OpenCLI 优势

  • 极小的二进制体积
  • 无外部依赖
  • 内置 AI 支持
  • 简单易用

9. FAQ

Q: OpenCLI 和 Cobra 有什么区别?

A: Cobra 是一个纯粹的 CLI 框架,而 OpenCLI 在 Cobra 基础上增加了 AI 集成。OpenCLI 约 2MB(vs Cobra 10MB+),且无外部依赖。

Q: 支持流式输出吗?

A: 支持。通过 ai.WithStreaming() 启用流式响应。

Q: 如何处理敏感数据?

A: 使用环境变量存储 API Key,不在代码或配置文件中明文存储。

Q: 可以离线使用吗?

A: 可以。使用 Ollama Provider 连接本地模型,完全离线可用。

Q: 支持哪些平台?

A: macOS、Linux、Windows 全平台支持。

10. 总结

OpenCLI 是一个极简主义设计 的 CLI 框架:

特性优势
~2MB 二进制极小分发体积
零依赖安装简单,环境干净
内置 AI开箱即用的 AI 能力
模块化易于扩展和定制

适用场景

  • 需要 AI 集成的 CLI 工具
  • 对二进制体积敏感的项目
  • 快速原型开发
  • 微服务命令行工具

不适用场景

  • 复杂的 CLI 应用(考虑 Cobra)
  • 非 Go 项目(考虑对应语言框架)

🦞 每日08:00自动更新