contacts
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseContacts
联系人
Manage contacts in . Each contact is a markdown file with YAML frontmatter.
~/Vault/Contacts/在中管理联系人。每个联系人对应一个带有YAML前置元数据的Markdown文件。
~/Vault/Contacts/Contact File Location
联系人文件位置
~/Vault/Contacts/<Name>.mdIndex file: — wikilink list of all contacts.
~/Vault/Contacts/index.md~/Vault/Contacts/<Name>.md索引文件: — 所有联系人的维基链接列表。
~/Vault/Contacts/index.mdFrontmatter Schema
前置元数据Schema
yaml
---
name: Full Name
aliases: [nickname, handle]
role: Current Role / Title
organizations: [Org1, Org2]
vip: true # or false
slack_user_id: U0XXXXXXX
slack_dm_channel: D0XXXXXXX # null if unknown
website: https://example.com
github: username
twitter: handle
email: user@example.com
tags: [vip, instructor, creator, family, employee]
---yaml
---
name: Full Name
aliases: [nickname, handle]
role: Current Role / Title
organizations: [Org1, Org2]
vip: true # or false
slack_user_id: U0XXXXXXX
slack_dm_channel: D0XXXXXXX # null if unknown
website: https://example.com
github: username
twitter: handle
email: user@example.com
tags: [vip, instructor, creator, family, employee]
---Sections
文档章节
markdown
undefinedmarkdown
undefinedName
Name
Contact Channels
联系渠道
- Slack, email, social handles, website
- Slack、邮箱、社交账号、网站
Projects
参与项目
- Active projects, courses, collaborations
- 活跃项目、课程、合作事项
Key Context
关键背景
- Relationship notes, working style, history
- 关系备注、工作风格、过往经历
Recent Activity
近期活动
- YYYY-MM-DD | channel | summary
See `~/Vault/Contacts/Matt Pocock.md` for a fully enriched example.- YYYY-MM-DD | 渠道 | 摘要
可参考`~/Vault/Contacts/Matt Pocock.md`查看完整的富信息示例。Adding a Contact
添加联系人
Option 1: Fire the Enrichment Pipeline (preferred)
选项1:触发Enrichment管道(推荐方式)
Send an Inngest event. The function fans out across 7 sources (Slack, Roam, web/GitHub, Granola, recall memory, Typesense), synthesizes with LLM, and writes the Vault file.
contact-enrichbash
undefined发送一个Inngest事件。函数会从7个来源(Slack、Roam、网页/GitHub、Granola、记忆召回、Typesense)获取信息,通过LLM进行合成,然后写入Vault文件。
contact-enrichbash
undefinedVia curl (CLI has OTEL import bug under Bun v1.3.9)
Via curl (CLI has OTEL import bug under Bun v1.3.9)
curl -s -X POST http://localhost:8288/e/37aa349b89692d657d276a40e0e47a15
-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 }]'
-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 }]'
**Depth modes:**
- `full` (~60s, ~$0.05): All 7 sources + LLM synthesis. Use for new contacts or periodic refresh.
- `quick` (~10s, ~$0.01): Slack + memory only. Good for real-time VIP detection.
**Hints are optional but help:** Any known identifiers (Slack ID, GitHub, email, Twitter, website) seed the search and improve results.curl -s -X POST http://localhost:8288/e/37aa349b89692d657d276a40e0e47a15
-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 }]'
-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账号、网站)都能作为搜索种子,提升结果准确性。Option 2: Quick Manual Create
选项2:手动快速创建
For simple contacts where enrichment is overkill:
markdown
---
name: Person Name
aliases: []
role: Role
organizations: [Org]
vip: false
slack_user_id: null
website: null
github: null
twitter: null
email: null
tags: [tag1]
---适用于无需复杂信息丰富的简单联系人:
markdown
---
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
Person Name
Contact Channels
联系渠道
- ...
- ...
Key Context
关键背景
- ...
Write to `~/Vault/Contacts/Person Name.md` and add `[[Person Name]]` to `index.md`.- ...
将文件写入`~/Vault/Contacts/Person Name.md`,并在`index.md`中添加`[[Person Name]]`。Updating Contacts
更新联系人
Re-run enrichment with the existing vault path:
json
{
"name": "contact/enrich.requested",
"data": {
"name": "Person Name",
"vault_path": "Contacts/Person Name.md",
"depth": "full"
}
}The synthesizer merges new data with existing content — it won't discard existing facts unless contradicted.
通过指定现有Vault路径重新触发 enrichment 流程:
json
{
"name": "contact/enrich.requested",
"data": {
"name": "Person Name",
"vault_path": "Contacts/Person Name.md",
"depth": "full"
}
}合成器会将新数据与现有内容合并,除非存在矛盾信息,否则不会丢弃已有的事实。
VIP Contacts (ADR-0151)
VIP联系人(ADR-0151)
Mark in frontmatter. VIPs get deep enrichment + ongoing monitoring.
vip: true在前置元数据中标记。VIP联系人会获得深度信息丰富 + 持续监控服务。
vip: trueDeep Enrichment Playbook (one-time)
深度信息丰富流程(一次性)
Every VIP gets the full treatment. This is what we did for Kent C. Dodds (Feb 26, 2026):
| Step | Source | What to Capture |
|---|---|---|
| 1. Web presence | Web search | Bio, role, location, personal details |
| 2. Podcast/interviews | Web search | Appearance list, own podcasts, audiences |
| 3. Joel collaborations | Their website, appearances pages | Joint podcasts, co-organized events, shared projects |
| 4. Career timeline | Defuddle 2-3 key interview transcripts | Origin story, career arc, key decisions, values |
| 5. GitHub profile | GitHub API or web | Repos, followers, orgs, contribution patterns |
| 6. X/Twitter profile | X API v2 (use x-api skill) | Bio, followers, recent tweets, engagement |
| 7. Key relationships | Cross-reference transcripts + contacts | Who they work with, who they mention, who we know in common |
| 8. Content catalog | Website crawl (defuddle) | Courses, blog posts, open source projects |
| 9. Audience reach | Podcast counts, social followers | Conference circuit, community presence |
Index to Typesense after enrichment:
- Batch-import appearances/content to collection (NDJSON,
discoveries)action=upsert - Tag all docs with person's name slug (e.g. ) for filtering
kent-c-dodds - Fields: ,
id,title,url,summary,tags[]timestamp - Write a reference doc linking back to contact
Vault/Resources/{name}-media-appearances.md
Output sections in the vault note:
- Background & Story (origin, career timeline)
- Teaching/Work Philosophy (or equivalent for non-educators)
- Key Relationships (cross-linked to other contacts)
[[wikilinks]] - Audience & Reach
- Content/Products
- Podcast/Collaboration History with Joel
- Recent Activity (timestamped)
每个VIP联系人都会获得完整的信息处理。以下是2026年2月26日为Kent C. Dodds执行的流程:
| 步骤 | 来源 | 采集内容 |
|---|---|---|
| 1. 网络存在感 | 网页搜索 | 个人简介、职位、所在地、个人细节 |
| 2. 播客/访谈 | 网页搜索 | 参与节目列表、自有播客、受众群体 |
| 3. 与Joel的合作 | 个人网站、参与页面 | 联合播客、共同组织的活动、合作项目 |
| 4. 职业 timeline | 解析2-3份关键访谈记录 | 起源故事、职业发展轨迹、关键决策、价值观 |
| 5. GitHub档案 | GitHub API或网页 | 仓库、关注者、所属组织、贡献模式 |
| 6. X/Twitter档案 | X API v2(使用x-api skill) | 个人简介、关注者、近期推文、互动数据 |
| 7. 关键关系 | 交叉引用访谈记录 + 联系人列表 | 合作对象、提及的人、共同认识的人 |
| 8. 内容目录 | 网站爬取(defuddle) | 课程、博客文章、开源项目 |
| 9. 受众覆盖 | 播客订阅量、社交平台关注者 | 会议参与情况、社区影响力 |
信息丰富后导入Typesense:
- 将参与的节目/内容批量导入集合(NDJSON格式,
discoveries)action=upsert - 为所有文档添加联系人名称的短标识(如)以便筛选
kent-c-dodds - 字段:、
id、title、url、summary、tags[]timestamp - 创建参考文档,关联到对应的联系人
Vault/Resources/{name}-media-appearances.md
Vault笔记中的输出章节:
- 背景与经历(起源、职业 timeline)
- 教学/工作理念(非教育从业者可调整为对应内容)
- 关键关系(通过关联到其他联系人)
[[维基链接]] - 受众与覆盖范围
- 内容/产品
- 与Joel的播客/合作历史
- 近期活动(带时间戳)
Ongoing Monitoring (Phase 2-4 of ADR-0151)
持续监控(ADR-0151的第2-4阶段)
| Channel | Tool | Signal |
|---|---|---|
| Google Alerts | joelclawbot Google account | Name mentions in news, blogs, press |
| X/Twitter list | joelclaw X account | Tweets, engagement |
| GitHub activity | GitHub API (polling) | New repos, releases |
| Podcast RSS | Feed monitoring | New episodes |
| Website changes | Periodic defuddle + diff | Blog posts, launches, bio changes |
High-signal (immediate): course launches, role changes, mentions of Joel/egghead/Skill, fundraising.
Low-signal (daily/weekly digest): regular tweets, blog posts, OSS activity.
| 渠道 | 工具 | 信号 |
|---|---|---|
| Google Alerts | joelclawbot Google账号 | 新闻、博客、媒体中的姓名提及 |
| X/Twitter列表 | joelclaw X账号 | 推文、互动数据 |
| GitHub活动 | GitHub API(轮询) | 新仓库、新版本发布 |
| 播客RSS | 订阅源监控 | 新节目上线 |
| 网站变更 | 定期爬取(defuddle)+ 差异对比 | 博客文章、新功能上线、个人简介变更 |
高优先级信号(立即通知):课程发布、职位变更、提及Joel/egghead/Skill、融资信息。
低优先级信号(每日/每周汇总):常规推文、博客文章、开源项目活动。
Current VIPs
当前VIP联系人权益
- Get notified to Joel via gateway after enrichment
- Are refreshed weekly via scheduled cron
- Have priority in channel intelligence pipeline (ADR-0131, ADR-0132)
- Get ongoing monitoring when ADR-0151 Phase 2+ is implemented
- 信息丰富完成后通过网关通知Joel
- 每周通过定时任务自动刷新信息
- 在渠道智能管道中享有优先级(ADR-0131、ADR-0132)
- 当ADR-0151第2+阶段落地后,将获得持续监控服务
Roam Research Enrichment
Roam Research信息丰富
Joel's Roam archive () contains the full egghead-era graph (2019-2024). Many contacts have extensive history there.
~/Code/joelhooks/egghead-roam-research/Joel的Roam存档()包含2019-2024年egghead时期的完整图谱。许多联系人在其中有详细的历史记录。
~/Code/joelhooks/egghead-roam-research/Quick Search (Python regex)
快速搜索(Python正则表达式)
bash
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]}')
"bash
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]}')
"People Taxonomy
人员分类体系
People are tagged with relationship prefixes in Roam:
- — Strategic partners (Ian Jones, Alex Hillman)
[[collaborator/Name]] - — egghead instructors (Matt Pocock, Jacob Paris)
[[client/Name]] - — egghead team (Will Johnson, Daniel Miller, Maggie Appleton)
[[staff/Name]] - (no prefix) — Informal references (Zac is
[[name]])[[zac]]
在Roam中,人员通过关系前缀进行标记:
- — 战略合作伙伴(Ian Jones、Alex Hillman)
[[collaborator/Name]] - — egghead讲师(Matt Pocock、Jacob Paris)
[[client/Name]] - — egghead团队成员(Will Johnson、Daniel Miller、Maggie Appleton)
[[staff/Name]] - (无前缀) — 非正式提及(Zac标记为
[[name]])[[zac]]
Page Title Search
页面标题搜索
bash
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}')
"bash
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}')
"Adding to Contacts
添加到联系人系统
When extracting person data from Roam, add to frontmatter:
roam_tagyaml
roam_tag: "[[collaborator/Ian Jones]]"This enables future re-queries and cross-referencing.
从Roam提取人员数据时,在前置元数据中添加:
roam_tagyaml
roam_tag: "[[collaborator/Ian Jones]]"这将支持后续的重新查询和交叉引用。
Datalog Queries (advanced)
Datalog查询(进阶)
The EDN file is Datomic-style. Clojure scripts exist at for structured analysis. See the skill for full Datalog patterns.
scripts/roam-researchEDN文件采用Datomic风格。目录下有Clojure脚本用于结构化分析。完整的Datalog模式可参考 skill。
scripts/roam-researchResolving Unknown People
未知人员身份解析
When you encounter a Slack user ID ():
<@U0XXXXXXX>bash
undefined当遇到Slack用户ID()时:
<@U0XXXXXXX>bash
undefinedLease token and look up profile
获取临时令牌并查询用户资料
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
-H "Authorization: Bearer $SLACK_USER" | jq '.user.real_name, .user.profile.email' secrets revoke --all
Then fire enrichment with the resolved name and hints.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
-H "Authorization: Bearer $SLACK_USER" | jq '.user.real_name, .user.profile.email' secrets revoke --all
然后使用解析出的姓名和提示信息触发信息丰富流程。Inngest Function
Inngest函数
- Function: (
contact-enrich)packages/system-bus/src/inngest/functions/contact-enrich.ts - Event:
contact/enrich.requested - ADR:
~/Vault/docs/decisions/0133-contact-enrichment-pipeline.md - Concurrency: 3 max
- Sources: Slack, Slack Connect, Roam archive, GitHub/web, Granola meetings, recall memory, Typesense
- 函数:(
contact-enrich)packages/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会议、记忆召回、Typesense
Privacy
隐私说明
- Contact files are in Vault (private, not in public repos)
- Slack data stays private — never surface in public content
- Email/phone are stored for Joel's reference only
- 联系人文件存储在Vault中(私有,不提交到公开仓库)
- Slack数据保持私有,绝不会出现在公开内容中
- 邮箱/电话仅用于Joel的个人参考