avatar

mdo

Hello

  • 首页
  • 知识库
  • 归档
  • 标签
  • 关于
主页 开发 CLI 工具
文章

开发 CLI 工具

发表于 2026-09-5 更新于 2026-09- 5
作者 mdo
12~16 分钟 阅读

如果追求极小的二进制体积、无依赖且执行速度极快,Node.js 确实不适合(打包后通常有几十 MB)。最佳的选择是使用 Go 或 Rust。

其中 Go 语言 是开发 CLI 工具的绝对利器,语法简单,交叉编译极强。编译后的二进制文件只有 几 MB,且压缩后能控制在 2MB-3MB 左右。

下面是使用 Go 语言 开发的完整方案。


第一步:初始化 Go 项目

确保你本地安装了 Go 环境,在空目录中运行:

bash

mkdir git-m-cli && cd git-m-cli
go mod init git-m-cli

请谨慎使用此类代码。


第二步:编写核心代码

创建 main.go 文件,写入以下代码。为了保持体积小和零第三方依赖,我们直接使用 Go 原生的 net/http 库来请求大模型。

go

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
	"os/exec"
	"strings"
)

// 配置大模型信息(你可以直接硬编码,或者编译时注入)
const (
	API_KEY  = "你的_DEEPSEEK_API_KEY" // 💡 替换为你的 API Key
	BASE_URL = "https://deepseek.com"
	MODEL    = "deepseek-chat"
)

// OpenAI/DeepSeek 请求体结构
type Message struct {
	Role    string `json:"role"`
	Content string `json:"content"`
}

type ChatRequest struct {
	Model       string    `json:"model"`
	Messages    []Message `json:"messages"`
	Temperature float64   `json:"temperature"`
}

type ChatResponse struct {
	Choices []struct {
		Message struct {
			Content string `json:"content"`
		} `json:"message"`
	} `json:"choices"`
}

func main() {
	// 1. 获取 Git 暂存区的 Diff
	diffCmd := exec.Command("git", "diff", "--cached")
	var diffOut bytes.Buffer
	diffCmd.Stdout = &diffOut
	if err := diffCmd.Run(); err != nil {
		fmt.Println("❌ 错误: 当前目录似乎不是一个 Git 仓库或没有配置 Git。")
		os.Exit(1)
	}

	diff := strings.TrimSpace(diffOut.String())
	if diff == "" {
		fmt.Println("⚠️ 提示: 没有发现已暂存(Staged)的文件,请先运行 `git add` 。")
		os.Exit(0)
	}

	// 限制 Diff 长度,防止超出 Token 限制(截取前 15000 个字符)
	if len(diff) > 15000 {
		diff = diff Harvey[:15000]
	}

	fmt.Println("🤖 正在分析暂存区代码并生成备注...")

	// 2. 构造 Prompt
	prompt := fmt.Sprintf(`你是一个专业的 Git 提交助手。请根据以下代码的 diff 内容,生成一条精炼、准确、结构清晰的 Git commit message。
请严格使用 Angular 规范格式(例如: feat(scope): add something 或 fix: resolve bug)。
不要输出任何解释性文本、不要包裹 markdown 代码块(如 \`\`\`),只输出 commit message 本身。

---
%s
---`, diff)

	// 3. 构建 HTTP 请求
	reqBody := ChatRequest{
		Model: MODEL,
		Messages: []Message{
			{Role: "user", Content: prompt},
		},
		Temperature: 0.1,
	}

	jsonData, err := json.Marshal(reqBody)
	if err != nil {
		fmt.Printf("❌ 序列化失败: %v\n", err)
		os.Exit(1)
	}

	req, err := http.NewRequest("POST", BASE_URL, bytes.NewBuffer(jsonData))
	if err != nil {
		fmt.Printf("❌ 创建请求失败: %v\n", err)
		os.Exit(1)
	}

	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", "Bearer "+API_KEY)

	// 4. 发送请求并解析
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		fmt.Printf("❌ 请求大模型失败: %v\n", err)
		os.Exit(1)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	if resp.StatusCode != http.StatusOK {
		fmt.Printf("❌ 接口响应错误 (状态码 %d): %s\n", resp.StatusCode, string(body))
		os.Exit(1)
	}

	var chatResp ChatResponse
	if err := json.Unmarshal(body, &chatResp); err != nil || len(chatResp.Choices) == 0 {
		fmt.Println("❌ 解析大模型返回数据失败。")
		os.Exit(1)
	}

	commitMessage := strings.TrimSpace(chatResp.Choices[0].Message.Content)
	fmt.Printf("\n📝 AI 建议的备注: %s\n\n", commitMessage)

	// 5. 执行真正地 Git Commit
	fmt.Println("🚀 正在提交到 Git...")
	commitCmd := exec.Command("git", "commit", "-m", commitMessage)
	commitCmd.Stdout = os.Stdout
	commitCmd.Stderr = os.Stderr
	if err := commitCmd.Run(); err != nil {
		fmt.Printf("❌ Git 提交失败: %v\n", err)
		os.Exit(1)
	}

	fmt.Println("\n✅ 提交成功!")
}

请谨慎使用此类代码。


第三步:极致体积压缩编译 (关键)

Go 默认编译出来的二进制文件会包含调试信息和符号表。我们可以通过编译参数和压缩工具让体积缩减 70% 以上。

在终端运行以下编译命令:

bash

# -s -w 参数用于移除调试信息和符号表,极大缩减体积
go build -ldflags="-s -w" -o git-m

请谨慎使用此类代码。

此时编译出来的二进制文件 git-m 大概只有 5MB 左右。

进一步压榨体积(可选,推荐)

你可以使用终端著名的压缩加壳工具 UPX。如果你的电脑没有安装,可以通过包管理器安装(如 brew install upx 或 apt install upx)。

安装后对二进制文件进行压缩:

bash

upx --best git-m

请谨慎使用此类代码。

经过 UPX 压缩后,这个二进制文件会直接缩减到 1.5MB - 2.5MB 左右,且完全不影响运行速度!


第四步:配置全局 Git 别名

  1. 把编译好的 git-m 移动到系统的环境变量目录(例如 /usr/local/bin),让它在任何地方都能被敲出来:

    bash

    mv git-m /usr/local/bin/
    

    请谨慎使用此类代码。

  2. 配置 Git 别名:

    bash

    git config --global alias.m "!git-m"
    

    请谨慎使用此类代码。

现在你在任何项目里输入 git m,就能享受到仅有 2MB 体积、零延时启动、一键 AI 提交的极致体验了。


为了让这个 Go 语言工具更完美,你需要我补充哪部分呢?

  • 如何在编译时动态注入 API_KEY(这样就不用把密钥写死在源码里了)

  • 增加一个确认机制(AI 生成备注后,需要你敲击回车或输入 y 才会真正 Commit)

  • 改为 Rust 语言 版本(Rust 编译后不经过 UPX 就能做到 3MB 左右,但代码稍显复杂)

知识库
许可协议:  CC BY 4.0
分享

相关文章

10月 7, 2026

比尔盖茨的智慧:想多赚钱,就每天循环做这3件事

我们总有一种非常固执的错觉,认为那些站在财富金字塔顶端的人,必然拥有某种超越常人的特异功能。我们在脑海中给比尔盖茨这样的大佬描绘了一幅极其悲壮的奋斗画像。大家总觉得,他之所以能富可敌国,肯定是因为他每天只睡三个小时,同时对着八个电脑屏幕疯狂敲击键盘,每一秒钟都在做出价值几亿美金的生死抉择。 为了模仿

9月 28, 2026

程序员越想创业,越不要急着动手

一个能源方面的前辈找到我,希望通过我把一些人工的工作 AI 自动化。 能源方面我不懂,找 Gemini 聊完发现这个是可以复制的,非常兴奋。我跟老婆说,这个项目做好以后可以做成平台,推广到其他公司,你就等着做总裁夫人吧! 她听完以后跟我说,这个项目还是太定制化,和我之前做的一个项目很像。 那个项目一

9月 25, 2026

忍了一年多,我终于对i18n下手了过去一年,我主要参与国际机票业务的开发工作,因此每天都要和多语言(i18n)打交道

前言 大家好,我是奈德丽。 过去一年,我主要参与国际机票业务的开发工作,因此每天都要和多语言(i18n)打交道。熟悉我的朋友都知道,我这个人比较“惜力”(并不是,实际上只是忍不下去了),对于重复笨拙的工作非常抵触,于是,我开始思考如何优化团队的多语言管理模式。 痛点背景 先说说我们在机票项目中遇到的

下一篇

开发一个git cli提交助手

上一篇

Rust 优化版本

最近更新

  • 比尔盖茨的智慧:想多赚钱,就每天循环做这3件事
  • iOS 侧载(Sideloading)工具
  • 程序员越想创业,越不要急着动手
  • 注册 Chat Participant
  • 中秋给在外游子的一封信

热门标签

API CodeGeex Coding Cursor DeepSeek Docker Gitkraken Harness Laravel Management

目录

©2026 mdo. 保留部分权利。