contacts

contacts

在 Joel 的 Vault 中添加、丰富和管理联系人。触发 Inngest 丰富管道以获取完整的多源档案,或手动创建快速联系人。适用于以下场景:'添加联系人'、'丰富此人信息'、'X 是谁'、'VIP 联系人'、'更新联系人',或任何涉及 Vault/Contacts 目录的任务。

61Star
3Fork
更新于 2026/7/23
SKILL.md
readonly只读
name
contacts
description

在 Joel 的 Vault 中添加、丰富和管理联系人。触发 Inngest 丰富管道以获取完整的多源档案,或手动创建快速联系人。适用于以下场景:'添加联系人'、'丰富此人信息'、'X 是谁'、'VIP 联系人'、'更新联系人',或任何涉及 Vault/Contacts 目录的任务。

version
1.0.0

联系人

管理 ~/Vault/Contacts/ 中的联系人。每个联系人是一个带有 YAML 前置元数据的 Markdown 文件。

联系人文件位置

~/Vault/Contacts/<姓名>.md

索引文件:~/Vault/Contacts/index.md — 所有联系人的维基链接列表。

前置元数据模式

---
name: 全名
aliases: [昵称, 用户名]
role: 当前角色/头衔
organizations: [组织1, 组织2]
vip: true  # 或 false
slack_user_id: U0XXXXXXX
slack_dm_channel: D0XXXXXXX  # 未知则为 null
website: https://example.com
github: 用户名
twitter: 用户名
email: user@example.com
tags: [vip, instructor, creator, family, employee]
---

章节

# 姓名

## 联系渠道
- Slack、电子邮件、社交媒体、网站

## 项目
- 活跃项目、课程、合作

## 关键背景
- 关系备注、工作风格、历史

## 近期活动
- YYYY-MM-DD | 渠道 | 摘要

参见 ~/Vault/Contacts/Matt Pocock.md 获取完整丰富的示例。

添加联系人

选项 1:触发丰富管道(推荐)

发送一个 Inngest 事件。contact-enrich 函数会分发给 Slack、Roam、网络/GitHub、Granola、基于大脑的记忆以及其他索引源,通过 LLM 综合,并写入 Vault 文件。

# 通过 curl(CLI 在 Bun v1.3.9 下存在 OTEL 导入错误)
curl -s -X POST "http://localhost:8288/e/$INNGEST_EVENT_KEY" \
  -H "Content-Type: application/json" \
  -d '[{
    "name": "contact/enrich.requested",
    "data": {
      "name": "Person Name",
      "depth": "full",
      "hints": {
        "slack_user_id": "U0XXXXXXX",
        "github": "username",
        "twitter": "handle",
        "email": "user@example.com",
        "website": "https://example.com"
      }
    },
    "ts": EPOCH_MS
  }]'

深度模式:

  • full(约 60 秒,约 $0.05):所有 7 个源 + LLM 综合。适用于新联系人或定期刷新。
  • quick(约 10 秒,约 $0.01):仅 Slack + 记忆。适用于实时 VIP 检测。

提示是可选的,但有助于: 任何已知标识符(Slack ID、GitHub、电子邮件、Twitter、网站)都能引导搜索并改善结果。

选项 2:快速手动创建

对于简单联系人,丰富功能过于繁琐时:

---
name: Person Name
aliases: []
role: Role
organizations: [Org]
vip: false
slack_user_id: null
website: null
github: null
twitter: null
email: null
tags: [tag1]
---

# Person Name

## 联系渠道
- ...

## 关键背景
- ...

写入 ~/Vault/Contacts/Person Name.md 并将 [[Person Name]] 添加到 index.md

更新联系人

使用现有 Vault 路径重新运行丰富:

{
  "name": "contact/enrich.requested",
  "data": {
    "name": "Person Name",
    "vault_path": "Contacts/Person Name.md",
    "depth": "full"
  }
}

综合器会将新数据与现有内容合并——除非矛盾,否则不会丢弃现有事实。

VIP 联系人(ADR-0151)

在前置元数据中标记 vip: true。VIP 会获得深度丰富 + 持续监控

深度丰富手册(一次性)

每个 VIP 都会获得全面处理。以下是我们为 Kent C. Dodds(2026 年 2 月 26 日)所做的:

步骤 来源 捕获内容
1. 网络存在 网络搜索 {name} + {org} 简介、角色、地点、个人详细信息
2. 播客/访谈 网络搜索 {name} podcast interview 出场列表、自有播客、受众
3. Joel 合作 他们的网站、出场页面 联合播客、共同组织活动、共享项目
4. 职业时间线 解析 2-3 个关键访谈记录 起源故事、职业轨迹、关键决策、价值观
5. GitHub 资料 GitHub API 或网页 仓库、关注者、组织、贡献模式
6. X/Twitter 资料 X API v2(使用 x-api 技能) 简介、关注者、近期推文、互动
7. 关键关系 交叉引用记录 + 联系人 与谁合作、提及谁、共同认识的人
8. 内容目录 网站爬取(defuddle) 课程、博客文章、开源项目
9. 受众覆盖 播客数量、社交媒体关注者 会议圈、社区存在

丰富后索引到 Typesense:

  • 批量导入出场/内容到 discoveries 集合(NDJSON,action=upsert
  • 用人员名称别名(例如 kent-c-dodds)标记所有文档以便筛选
  • 字段:idtitleurlsummarytags[]timestamp
  • 编写 Vault/Resources/{name}-media-appearances.md 参考文档,链接回联系人

Vault 笔记中的输出章节:

  • 背景与故事(起源、职业时间线)
  • 教学/工作理念(或非教育者的等效内容)
  • 关键关系(交叉链接 [[wikilinks]] 到其他联系人)
  • 受众与覆盖
  • 内容/产品
  • 与 Joel 的播客/合作历史
  • 近期活动(带时间戳)

持续监控(ADR-0151 第 2-4 阶段)

渠道 工具 信号
Google 快讯 joelclawbot Google 账户 新闻、博客、媒体报道中的姓名提及
X/Twitter 列表 joelclaw X 账户 推文、互动
GitHub 活动 GitHub API(轮询) 新仓库、发布
播客 RSS 订阅监控 新剧集
网站变更 定期 defuddle + 差异比较 博客文章、发布、简介变更

高信号(立即处理):课程发布、角色变更、提及 Joel/egghead/Skill、融资。
低信号(每日/每周摘要):常规推文、博客文章、开源活动。

当前 VIP

  • 丰富后通过网关通知 Joel
  • 每周通过定时 cron 刷新
  • 在渠道情报管道中具有优先级(ADR-0131、ADR-0132)
  • 在 ADR-0151 第 2+ 阶段实施后获得持续监控

Roam Research 丰富

Joel 的 Roam 存档(~/Code/joelhooks/egghead-roam-research/)包含完整的 egghead 时代图谱(2019-2024)。许多联系人那里有广泛的历史。

快速搜索(Python 正则表达式)

cd ~/Code/joelhooks/egghead-roam-research
python3 -c "
import re
with open('egghead-2026-01-19-13-09-38.edn', 'r') as f:
    content = f.read()
pattern = r':block/string\\s+\\\"([^\\\"]*?)\\"'
matches = []
for m in re.findall(pattern, content):
    if '[[SEARCH_TAG]]' in m.lower():
        matches.append(m)
print(f'Found {len(matches)} blocks')
for m in matches[:30]:
    print(f'  - {m[:200]}')
"

人员分类

人员在 Roam 中使用关系前缀标记:

  • [[collaborator/Name]] — 战略合作伙伴(Ian Jones、Alex Hillman)
  • [[client/Name]] — egghead 讲师(Matt Pocock、Jacob Paris)
  • [[staff/Name]] — egghead 团队(Will Johnson、Daniel Miller、Maggie Appleton)
  • [[name]](无前缀)— 非正式引用(Zac 是 [[zac]]

页面标题搜索

python3 -c "
import re
with open('egghead-2026-01-19-13-09-38.edn', 'r') as f:
    content = f.read()
pattern = r':node/title\\s+\\\"([^\\\"]*?SEARCH_TERM[^\\\"]*?)\\"'
for m in re.findall(pattern, content):
    print(f'  page: {m}')
"

添加到联系人

从 Roam 提取人员数据时,将 roam_tag 添加到前置元数据:

roam_tag: "[[collaborator/Ian Jones]]"

这有助于未来的重新查询和交叉引用。

Datalog 查询(高级)

EDN 文件是 Datomic 风格的。Clojure 脚本位于 scripts/ 目录,用于结构化分析。参见 roam-research 技能以获取完整的 Datalog 模式。

解析未知人员

当遇到 Slack 用户 ID(<@U0XXXXXXX>)时:

# 获取令牌并查找资料
SLACK_USER=$(secrets lease slack_user_token --ttl 5m)
curl -s "https://slack.com/api/users.info?user=U0XXXXXXX" \
  -H "Authorization: Bearer $SLACK_USER" | jq '.user.real_name, .user.profile.email'
secrets revoke --all

然后使用解析出的姓名和提示触发丰富。

Inngest 函数

  • 函数:contact-enrichpackages/system-bus/src/inngest/functions/contact-enrich.ts
  • 事件:contact/enrich.requested
  • ADR:~/Vault/docs/decisions/0133-contact-enrichment-pipeline.md
  • 并发:最多 3
  • 来源:Slack、Slack Connect、Roam 存档、GitHub/网络、Granola 会议、基于大脑的记忆以及其他索引源

隐私

  • 联系人文件位于 Vault 中(私有,不在公共仓库中)
  • Slack 数据保持私有——绝不公开显示
  • 电子邮件/电话仅用于 Joel 的参考