我如何创建一个博客CLI工具
记录我如何为零门槛创建博客 CLI 工具的完整思路和方案
背景
写博客时,我经常需要重复执行:创建新文章、列出现有的文章、删除旧文章、启动预览服务等操作。每次手动做这些很繁琐,于是我决定写一个 CLI 工具来自动化这些流程。
方案设计
目标
创建一个轻量的、仅依赖 Node.js 内置模块的 CLI 工具,用于管理博客文章。
核心功能
successli new <title>- 根据标题创建新的 MDX 文章successli list- 列出所有已发布的文章successli delete <slug>- 将文章移动到 trash 目录(软删除)successli preview- 启动开发服务器预览
技术选型
| 技术 | 选择理由 |
|---|---|
| Node.js ESM | 原生支持现代 JavaScript,无需额外编译 |
| 内置模块 | 仅使用 fs、path、child_process,零依赖 |
| Content Collections | Astro 的内容管理方式,MDX 文件即博客 |
实现步骤
1. 创建入口脚本
在 scripts/successli.mjs 中编写主逻辑:
#!/usr/bin/env node
import { readdir, readFile, writeFile, rename, access, mkdir } from "node:fs/promises";
import { join } from "node:path";
import { spawn } from "node:child_process";
// 生成 URL 友好的 slug
function slugify(title) {
return title
.toLowerCase()
.replace(/[^a-z0-9]+/g, "-")
.replace(/^-+|-+$/g, "");
}
// 创建新文章
async function createPost(title) {
const slug = slugify(title);
const today = formatDate(new Date());
const filePath = join(getPostsDir(), `${slug}.mdx`);
const frontmatter = `---
title: "${title}"
description: "TODO: add description"
pubDate: ${today}
tags:
- Uncategorized
draft: true
---
`;
await writeFile(filePath, frontmatter);
console.log(`Created: ${filePath}`);
}
2. 注册 bin 字段
在 package.json 中添加:
{
"bin": {
"successli": "./scripts/successli.mjs"
}
}
3. 链接到全局
npm link
执行后,successli 命令即可在全局使用。
核心代码解析
文件结构
src/content/posts/ # 文章目录
src/content/.trash/posts/ # 回收站目录
scripts/successli.mjs # CLI 入口
关键函数
slugify - 将标题转换为 URL 友好的 slug:
"我的第一篇文章" → "wo-de-di-yi-pian-wenzhang"
formatDate - 生成标准日期格式:
new Date() → "2026-04-19"
softDeletePost - 软删除,移至 trash 而非直接删除:
await rename(postPath, trashPath);
使用效果
# 创建新文章
successli new 我如何创建一个博客CLI工具
# Created: src/content/posts/cli.mdx
# 列出所有文章
successli list
# 启动预览
successli preview
总结
这个 CLI 工具的核心思路是:以文件系统为中心,用 Node.js 内置模块完成所有操作。不依赖任何外部库,只需要 MDX 文件符合 Astro Content Collections 的 frontmatter 规范即可正常工作。
下一步可以继续优化:添加文章搜索、标签管理、自动发布到 Git 等功能。