你有没有过这样的经历:
早上 9 点刚进办公室,老板一个电话打过来:“小王啊,上个月那个 AI 项目客户是谁来着?合同金额多少?谁负责的?”
你打开 CRM 系统查客户,翻了三页才找到;再去 Jira 找项目进度,发现任务被拆成了十几个子项,根本对不上号;最后还得去财务系统导个报表,确认付款情况……折腾半小时,咖啡都凉了。
而这时候,隔壁组的小李却只敲了一行命令:
$ firm related project.ai_validation
不到一秒,整个项目的全貌就出来了:客户信息、负责人、预算、截止日期、沟通记录、相关文件链接……一清二楚。
老板看了直呼:“这小子,有点东西。”
这不是科幻片,也不是大厂黑科技。这是最近在 GitHub 上悄悄火起来的一个开源项目——firm,一个专为技术人员打造的“文本化工作管理系统”。
它不靠花里胡哨的 UI,也不依赖云服务,而是用纯文本 + 代码的方式,把你公司的组织结构、客户关系、项目流程全部建模成一张可查询、可编程、可自动化的“业务图谱”。
听起来很抽象?别急,咱们今天就来把它扒个底朝天。从安装到实战,从 CLI 命令到 Rust 集成,从基础概念到 AI 赋能,带你玩转这个极客味十足的“企业操作系统”。
准备好了吗?我们先从一句话开始:
你的公司,其实是一张图。
0x0001 为什么我们需要“Business-as-Code”?
被 SaaS 绑架的现代企业
现在的公司,活得像个“拼图爱好者”。
HR 用飞书,销售用 Salesforce,研发用 Jira,财务用金蝶,运营用 Notion……每个系统都自称“一体化平台”,结果呢?数据孤岛遍地开花。
你想知道“哪个客户最近最活跃”,得手动把 CRM 里的联系记录、邮件系统的发信日志、客服系统的工单数据全都导出来,再拿 Excel 搓一个报表。
更离谱的是,这些系统的 API 还经常改接口、限频率、收钱。你花了几十万买的 SaaS 服务,结果连自己的数据都拿不完整。
这就像你买了辆宝马,但钥匙在 4S 店手里,想开车得先打电话预约。
那么问题来了:有没有一种方式,能让我真正“拥有”我的业务数据?
有。
答案就是:把你的公司写成代码。
这就是 firm 想做的事——Business-as-Code(业务即代码)。
就像 DevOps 把基础设施变成代码(Infrastructure-as-Code),CI/CD 把发布流程变成脚本一样,firm 把你的组织、客户、项目、任务、沟通记录……全都定义成 .firm 文件,存进 Git 仓库。
从此,你的公司不再是一个个割裂的 SaaS 账户,而是一个版本可控、本地存储、结构清晰的代码库。
你可以:
-
git diff看上周客户合同改了啥 -
grep找出所有预算超 5 万的项目 -
写个脚本自动给即将到期的任务发提醒 -
让 LLM 读取整个业务图谱,帮你生成周报
是不是感觉突然掌握了“上帝视角”?
而且最重要的是——这一切都不需要联网,数据永远在你手里。
0x0002 安装 & 快速上手:三分钟让你的公司“跑”起来
安装:一行命令搞定
firm 是用 Rust 写的,性能杠杠的,安装也极其简单。
Linux / macOS 用户:
curl -fsSL https://raw.githubusercontent.com/42futures/firm/main/install.sh | sudo bash
Windows 用户(PowerShell):
irm https://raw.githubusercontent.com/42futures/firm/main/install.ps1 | iex
安装完后,输入 firm --version 看看有没有反应。如果输出类似 firm 0.1.0,恭喜你,环境 ready!
💡 小贴士:
irm是Invoke-RestMethod的缩写,Windows 7+ 自带。如果你还在用 XP……建议先升级系统。
初始化 workspace:你的“公司根目录”
firm 的所有数据都存在一个叫 workspace 的文件夹里。你可以理解为这是你公司的“源码目录”。
新建一个文件夹,比如叫 my-company:
mkdir my-company && cd my-company
然后就可以开始添加实体了。
添加第一个实体:用 CLI 还是手写 DSL?
firm 支持两种方式定义实体:
方法一:交互式添加(适合新手)
运行:
firm add
你会看到类似这样的提示:
Adding new entity
> Type: organization
> ID: megacorp
> Name: Megacorp Ltd.
> Email: mega@corp.com
> Urls: ["corp.com"]
填完回车,firm 会自动生成一个 .firm 文件,路径通常是 generated/organization.firm。
方法二:手动编写 DSL(适合老司机)
你也可以直接创建一个 org.firm 文件,写入:
organization megacorp {
name = "Megacorp Ltd."
email = "mega@corp.com"
urls = ["https://corp.com"]
}
保存即可。
两种方式效果完全一样。CLI 更傻瓜,DSL 更灵活。你可以混着用。
查看数据:list、get、related 三大法宝
现在我们来看看怎么查数据。
1. firm list:列出所有某类实体
比如你想看所有“任务”:
firm list task
输出可能是:
Found 7 entities with type 'task'
ID: task.design_homepage
Name: Design new homepage
Is completed: false
Assignee ref: person.jane_doe
ID: task.setup_ci_cd
Name: Set up CI/CD pipeline
Is completed: true
Assignee ref: person.zhang_san
2. firm get:查看某个实体详情
firm get person john_doe
输出:
Found 'person' entity with ID 'john_doe'
ID: person.john_doe
Name: John Doe
Email: john@doe.com
Phone: +1-555-1234
Role: Lead Engineer
3. firm related:查看关系链(这才是精髓!)
这才是 firm 最牛的地方——图查询能力。
假设你有一个客户联系人 john_doe,你想知道他最近有什么互动:
firm related contact john_doe
输出:
Found 1 relationship for 'contact' entity with ID 'john_doe'
ID: interaction.megacorp_intro
Type: Call
Subject: Initial discussion about Project X
Interaction date: 2025-09-30 09:45:00 +02:00
Initiator ref: person.jane_smith
Primary contact ref: contact.john_doe
Notes: Interested in AI validation solution. Will send proposal next week.
看到了吗?你不仅能查到“谁跟客户聊过”,还能拿到聊天内容、时间、后续动作……这一切都通过引用字段自动关联。
这就叫“业务可追溯”。
0x0003 核心架构解析:Rust + Tree-sitter + 图模型
你以为 firm 就是个简单的配置文件管理器?Too young.
它的底层架构非常讲究,分为三大模块:
firm_core:核心数据引擎
这是整个系统的“大脑”,负责:
-
定义实体模型(Entity) -
管理字段类型(String, Boolean, Currency, DateTime…) -
构建实体之间的引用关系(Reference) -
提供图遍历和查询能力
它的设计理念是:一切皆实体,一切可引用。
比如你可以定义:
project ai_validation {
name = "AI Model Validation System"
client_ref = organization.megacorp
team_refs = [person.jane_doe, person.zhang_san]
budget = 80000 CNY
start_date = 2025-10-01
due_date = 2026-01-31
status = "in_progress"
}
这里的 client_ref 和 team_refs 都是指向其他实体的引用。firm_core 会在内存中构建一张有向图,让你可以轻松实现:
# 查这个项目的客户是谁?
firm get $(firm get project ai_validation | grep client_ref)
# 查这个客户下有多少个项目?
firm related organization megacorp | grep project
firm_lang:DSL 解析器
.firm 文件不是随便写的 JSON 或 YAML,而是一种领域特定语言(DSL)。
为了正确解析它,firm 使用了 Tree-sitter[1] —— 一个高性能的语法解析框架,也是 VS Code、Neovim 等编辑器背后的技术。
这意味着:
-
语法高亮(未来可支持) -
错误定位精准 -
可扩展性强(能加新关键字)
比如这段 DSL:
task setup_database {
title = "Set up PostgreSQL cluster"
assignee_ref = person.dba_li
depends_on = [task.network_setup, task.server_provisioning]
estimated_hours = 16.5
}
会被 firm_lang 解析成 AST(抽象语法树),再转换为 firm_core 能理解的 Entity 对象。
firm_cli:命令行入口
CLI 层负责把用户的命令翻译成对 firm_core 的调用。
比如你输入:
firm list task
CLI 会:
-
扫描 workspace 下所有 .firm文件 -
用 firm_lang解析成实体列表 -
过滤出类型为 task的实体 -
格式化输出到终端
整个过程毫秒级完成,比大多数 Web UI 还快。
0x0004 用 Rust 当库集成:打造你的“自动化中台”
光用 CLI 还不够?那我们可以把 firm 当作一个库,嵌入到自己的程序里。
想象一下这个场景:
你想做一个“每日任务提醒机器人”,每天下午 5 点自动检查:
-
哪些任务明天到期? -
谁是负责人? -
发邮件或钉钉提醒。
传统做法:对接 Jira API + 钉钉 Webhook + 写定时脚本。
现在?只需要一段 Rust 代码:
第一步:引入依赖
在你的 Cargo.toml 里加上:
[dependencies]
firm_core = { git = "https://github.com/42futures/firm.git" }
firm_lang = { git = "https://github.com/42futures/firm.git" }
tokio = { version = "1", features = ["full"] }
reqwest = "0.11"
第二步:加载 workspace 并查询
use firm_lang::workspace::Workspace;
use firm_core::{EntityGraph, EntityId, FieldId};
#[tokio::main]
asyncfn main() -> Result<(), Box<dyn std::error::Error>> {
// 1. 加载本地 workspace
letmut workspace = Workspace::new();
workspace.load_directory("./my-company")?;
let build = workspace.build()?;
// 2. 构建实体图
letmut graph = EntityGraph::new();
graph.add_entities(build.entities)?;
graph.build();
// 3. 查询即将到期的任务
let tomorrow = chrono::Utc::now() + chrono::Duration::days(1);
let due_tasks: Vec<_> = graph.entities()
.filter(|e| e.entity_type().as_str() == "task")
.filter(|e| !e.get_field(&FieldId::new("completed")).unwrap_or(false))
.filter(|e| {
ifletOk(due) = e.get_field::<chrono::DateTime<chrono::Utc>>(&FieldId::new("due_date")) {
due.date_naive() == tomorrow.date_naive()
} else {
false
}
})
.collect();
// 4. 给每个负责人发提醒
for task in due_tasks {
let assignee_ref = task.get_field(&FieldId::new("assignee_ref"));
ifletSome(EntityId::Reference(ref_id)) = assignee_ref {
let assignee = graph.get_entity(ref_id).unwrap();
let name = assignee.get_field(&FieldId::new("name")).unwrap_or("Someone");
let title = task.get_field(&FieldId::new("title")).unwrap_or("A task");
send_dingtalk_reminder(name, title).await?;
}
}
Ok(())
}
asyncfn send_dingtalk_reminder(name: &str, task: &str) -> Result<(), reqwest::Error> {
let client = reqwest::Client::new();
let webhook_url = "https://oapi.dingtalk.com/robot/send?access_token=xxx";
let body = serde_json::json!({
"msgtype": "text",
"text": {
"content": format!("【明日截止】{},请处理任务:{}", name, task)
}
});
client.post(webhook_url)
.json(&body)
.send()
.await?
.error_for_status()?;
Ok(())
}
就这么一段代码,你就有了一个完全自主可控的任务提醒系统,不依赖任何 SaaS,数据全在本地,还能随时扩展。
比如你想加上“优先级高于 2 的任务提前两天提醒”,只需改个条件就行。
这才是真正的“自动化自由”。
0x0005 高级玩法:自定义 Schema + AI 接管业务
自定义 Schema:让你的 DSL 更贴合业务
firm 默认提供了一些通用 schema,比如 person、organization、task、project。
但每个公司都有自己的业务逻辑。比如你是做咨询的,可能需要 engagement(项目委派)、deliverable(交付物)、invoice(发票)等类型。
怎么办?自己定义!
你可以在 .firm 文件中这样写:
schema engagement {
fields = [
{ name = "client_ref", type = "reference", target = "organization" },
{ name = "lead_consultant_ref", type = "reference", target = "person" },
{ name = "start_date", type = "datetime" },
{ name = "end_date", type = "datetime" },
{ name = "status", type = "string", enum = ["proposed", "active", "on_hold", "completed"] },
{ name = "hourly_rate", type = "currency" }
]
}
engagement ai_audit_2025 {
client_ref = organization.finbank
lead_consultant_ref = person.elena_chen
start_date = 2025-11-01
end_date = 2026-02-28
status = "proposed"
hourly_rate = 1500 CNY
}
通过 schema 关键字,你可以声明新的实体类型,并规定字段类型、是否必填、枚举值等。
firm_core 会在加载时进行校验,确保数据一致性。
这就像数据库的 DDL(Data Definition Language),只不过是以文本形式存在的。
AI Ready:让大模型读懂你的公司
如果说“代码化”让你拥有了对业务的控制权,那么“AI-ready”则让你获得了智能代理权。
因为 .firm 文件是纯文本,结构清晰,字段明确,天然适合 LLM 理解。
你可以这样做:
场景 1:让 AI 帮你写周报
写个脚本,把本周完成的任务、参与的会议、产出的文档汇总起来,喂给通义千问:
# pseudo code
weekly_data = """
## 本周工作摘要
- 完成任务:3项
- task.setup_ci_cd
- task.review_docs
- task.client_meeting_notes
- 新增客户互动:2次
- interaction.qa_discussion (with megacorp)
- interaction.pricing_negotiation (with startup_xyz)
"""
prompt = f"""
你是技术主管,请根据以下数据生成一份简洁的周报:
{weekly_data}
要求:
1. 分点陈述
2. 突出成果
3. 不超过100字
"""
llm_response = call_qwen(prompt)
print(llm_response)
输出可能是:
本周完成 CI/CD 搭建与文档评审,推进两大客户技术讨论与报价谈判,项目进展顺利。
一键生成,老板满意。
场景 2:AI 自动分配任务
你可以训练一个 Agent,让它根据以下规则自动创建任务:
-
新客户签约 → 创建“欢迎邮件”、“环境初始化”任务 -
项目延期 → 提醒 PM 并生成“风险评估”任务 -
某人连续三天没更新任务状态 → 发私信提醒
这一切都可以基于 firm 的图数据自动触发。
未来甚至可以做到:
“Alexa,告诉公司 AI,启动‘Q4 冲刺模式’。”
→ 自动生成冲刺计划、分配资源、设定里程碑、安排每日站会提醒。
细思极恐,但也无比诱人。
0x0006 对比现有工具:firm vs Notion vs Jira vs Airtable
|
|
firm |
|
|
|
|---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
结论很明显:
-
如果你是非技术团队,想要快速协作 → 选 Notion/Airtable。 -
如果你是软件团队,追求敏捷开发 → Jira 仍是主流。 -
但如果你是技术极客/初创公司/独立开发者,想要完全掌控业务流 + 自动化 + AI 赋能 → firm是目前最接近理想的工具。
它不是替代品,而是一种新范式:把公司当成一个可运行的程序来管理。
0x0007 实战案例:用 firm 搭建一个微型创业公司
让我们动手实战一把。
假设你开了个小公司,叫“智码科技”,做 AI 解决方案。
目标:
-
管理客户、项目、员工 -
自动化任务提醒 -
支持 AI 生成月报
步骤 1:初始化 workspace
mkdir zhimatech && cd zhimatech
步骤 2:创建人员档案
people.firm:
person zhang_san {
name = "张三"
email = "zhang@zhimatech.com"
role = "ML Engineer"
join_date = 2025-01-01
}
person li_si {
name = "李四"
email = "li@zhimatech.com"
role = "Frontend Developer"
join_date = 2025-03-15
}
步骤 3:添加客户
clients.firm:
organization client_a {
name = "安煋金融"
email = "contact@anxing.com"
urls = ["https://anxing.com"]
industry = "FinTech"
}
organization client_b {
name = "蓝海教育"
email = "hello@lanhai.edu"
urls = ["https://lanhai.edu"]
industry = "EdTech"
}
步骤 4:定义项目
projects.firm:
project anxing_fraud_detection {
name = "反欺诈模型开发"
client_ref = organization.client_a
team_refs = [person.zhang_san, person.li_si]
budget = 120000 CNY
start_date = 2025-10-01
due_date = 2026-01-31
status = "planning"
}
步骤 5:创建任务
tasks.firm:
task task.model_research {
title = "调研主流反欺诈模型"
project_ref = project.anxing_fraud_detection
assignee_ref = person.zhang_san
due_date = 2025-10-10
priority = 2
completed = false
}
步骤 6:查询与自动化
现在你可以:
# 查张三的所有任务
firm related person zhang_san | grep task
# 查安煋金融的相关项目
firm related organization client_a
# 写个cron脚本,每天检查逾期任务
#!/bin/bash
OVERDUE=$(firm list task --filter "due_date < now && completed == false")
if [ -n "$OVERDUE" ]; then
echo "⚠️ 有任务逾期:" | mail -s "任务告警" admin@zhimatech.com
fi
一套轻量级但完整的“企业管理系统”就此诞生。
参考资料:
-
GitHub 仓库:https://github.com/42futures/firm[2] -
Tree-sitter 官网:https://tree-sitter.github.io/tree-sitter/[3] -
Rust 官方文档:https://www.rust-lang.org/[4]
参考资料
Tree-sitter: https://tree-sitter.github.io/tree-sitter/
[2]https://github.com/42futures/firm: https://github.com/42futures/firm
[3]https://tree-sitter.github.io/tree-sitter/: https://tree-sitter.github.io/tree-sitter/
[4]https://www.rust-lang.org/: https://www.rust-lang.org/

