关于 ttctl
TTCtl 是面向 Toptal Talent 人员的非官方命令行工具和 MCP 服务,用于管理个人资料。它提供个人资料、申请、职位、工时表、项目、可用时间、合同、付款、调查和身份验证功能,并排除批量自动化操作。
主要功能
- 01查看和更新个人资料
- 02查看申请与面试信息
- 03浏览职位并管理职位信号
- 04管理工时表与项目休假
- 05查看可用时间、合同和付款
- 06管理调查与身份验证
适用场景
- 01检查申请动态和面试详情
- 02查看职位机会及已保存信号
- 03更新个人资料和工作时间
- 04查看付款并提交工时表
MCP 相关
MCP 服务向 AI 助手提供个人 Toptal Talent 资料和工作流操作。其 MCP 工具包含职位申请操作及相关的建议答案查询。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
TTCtl
面向个人效率的命令行工具和 MCP 服务,适用于你自己的 Toptal Talent 个人资料。
⚠️ 非官方 — 仅供个人使用
TTCtl 与 Toptal LLC 无关联,也未获得其认可或支持。 它是一款面向个人效率的工具,通过你自己的会话与 Toptal Talent 的网页/移动界面交互,仅用于处理你自己个人资料的数据。
此工具旨在实现合理使用,并分享给可能也需要类似工具来管理自己个人资料的其他 Toptal 人才。不得将其用于:
- 向招聘人员/客户发送垃圾信息或未经请求的联系
- 批量自动化职位申请、个人资料更新或消息发送
- 操纵互动信号、海投申请、抓取招聘人员信息
- 操作非你本人所有的个人资料
- 任何违反 Toptal 服务条款或给平台造成负担的行为
如果你发现有人滥用 TTCtl,请参阅 SECURITY.md 中的滥用行为报告。
代码库中的架构限制(顺序速率限制、单凭据设计,以及容易被用于自动化的端点不支持批量并行操作)是有意设置的。请勿移除。
“Toptal” 是 Toptal LLC 的商标。本项目描述中仅以指称性合理使用的方式使用该名称——TTCtl 并非 Toptal 品牌。
功能介绍
TTCtl 可让你及 AI 助手通过 MCP 以编程方式访问你自己的 Toptal 人才档案:
- 个人档案 — 查看和更新人才档案(基本信息、技能、工作经历、教育经历、证书、行业、作品集、签证、简历、外部链接、评价、照片)
- 申请 — 查看活动项目(申请、可用时间请求、面试、合作意向信号);通过
applications stats按状态组统计数量;通过applications confirm/applications reject确认 / 拒绝待处理的合作意向请求;通过applications interview show <id>获取面试详情(面试官及其 TopChat 话题句柄、客户端联系人、预定时段、议程链接、准备指南引用);通过applications interview notes show <jobId>查看面试准备笔记;通过applications availability-request show <id>获取可用时间请求详情(状态、类型、招聘人员固定费率、备注、生命周期时间戳、职位) - 合作项目 — 查看当前和过去的合作项目;管理合作项目休息时间;通过
engagements stats按状态统计数量 - 职位 — 浏览机会(包括算法生成的
jobs recommended推荐信息流、每个职位的jobs match-quality匹配分数明细,以及每个职位的jobs rate-insight费率分析面板);管理已保存 / 已查看 / 不感兴趣信号;配置搜索订阅;通过jobs apply <id> --consent直接申请(必须通过法律合规检查)。添加--suggest-answers可获取你过去对类似问题的回答,作为辅助自动补全建议(需主动选择,不在关键申请流程中;即使失败也可正常继续)。MCP 工具ttctl_jobs_apply_similar_answers向 Agent 提供相同功能。 - 工时表 — 列出、查看、更新和提交工时表计费周期
- 可用时间 — 查看和更新工作时间及每周分配的工时
- 合同 — 查看人才层级的合同(Toptal Direct、MSA 等)
- 付款 — 查看付款历史、付款总额汇总(
payments summary)和付款方式;通过payments rate current(轻量级)或统一的payments rate show投影查看当前小时费率;提交费率变更请求 - 调查问卷 — 列出待完成的调查问卷、提交结构化回答,并针对面试后 / NPS 提示添加自由文本反馈;提交回答和反馈后无法撤销,且需取得同意
- 身份验证 — 初始化配置、登录、检查状态、退出登录
这些功能仅限于以读取为主的个人用途。刻意不提供可能用于针对平台进行大规模自动化的操作。
不在范围内
以下 Toptal Talent 功能有意不纳入范围——它们可能导致滥用(批量自动化或垃圾信息),需要 TTCtl 不依赖的第三方 SDK,面向客户入驻而非人才侧工作流,属于员工侧或人才招募侧工作流,或者是一次性/仅限移动端的界面功能,没有持续使用命令行的价值:
- 通知偏好设置 —
UpdateJobAlertSettings、UpdateSmsNotificationsSettings、UpdateTimesheetReminderSettings、UpdateNotificationSetting(防止滥用——静默提醒是其他滥用行为的前兆) - 社区/Slack 互动 — 活动、频道、消息、RSVP(需要第三方 SDK——参与社区属于人工操作,而非命令行操作)
- 推荐流程 — 发送推荐、领取奖励、跟踪推荐人(防止滥用——以编程方式生成推荐属于垃圾信息途径)
- 成为客户/咨询/辅导/零工 — 买家侧工作流(客户入驻——不是人才侧资料管理)
- 发布雇用我页面 — 公开营销页面(一次性操作——不是持续维护的资料状态)
- 视频推介/Zendesk 集成 — 基于 Ziggeo/CameraTag 和 Zendesk 的功能(需要第三方 SDK——不属于 TTCtl 面向的 GraphQL 功能范围)
- TopChat 消息功能 — 消息和文件下载仍不在范围内;只有每位面试官的发现标识通过
applications interview show提供(完整功能范围见 #23) - 仅限移动端的小组件 — Story、MobileTopTip、MarketCondition(仅限移动端的界面——没有对应的命令行价值)
- 测验/问卷 — 入驻流程中的终端表单(一次性操作——不是持续维护的资料状态)
- 员工侧工作流 —
SEND_CONTRACTS、发布推荐信、快照历史(员工侧——面向 Toptal 员工,而非人才) - 人才信号招募 —
CreateTalentSignal、GetTalentSignalSetup(人才招募侧——招聘人员/员工识别人才,而非人才侧)
注意:
scheduler.toptal.com功能(面试安排)目前尚未实现,并非有意排除——待逆向工程研究完成后再行处理。
有关纳入范围的内容,请参阅上文的功能介绍。
前置条件
- Node.js >= 22.19.0
- Toptal Talent 资料(使用此工具必须是 Toptal 人才;其他人无法从中受益)
- 推荐:使用 1Password CLI(
op)解析凭据
支持的平台
TTCtl 在受 Cloudflare 保护的功能(资料编辑)中使用
node-wreq 模拟 Chrome
TLS 指纹。该传输模块以预编译原生二进制文件的形式提供,支持以下平台:
| OS | 架构 | libc | 支持状态 |
|---|---|---|---|
| macOS | x64(Intel) | — | ✅ |
| macOS | arm64(Apple Silicon) | — | ✅ |
| Linux | x64 | glibc | ✅ |
| Linux | x64 | musl(Alpine) | ✅ |
| Linux | arm64 | glibc | ✅ |
| Linux | arm64 | musl(Alpine) | ❌ 尚未支持 |
| Windows | x64 | — | ✅ |
| Windows | arm64(Windows on ARM) | — | ❌ 尚未支持 |
在不受支持的平台上,npm install -g ttctl 仍会成功(原生二进制文件属于可选依赖),移动网关命令也能继续使用——但任何受 Cloudflare 保护的命令(所有会编辑资料的命令)都会失败,并显示清晰的 NATIVE_MODULE_UNAVAILABLE 错误,指出你的平台和受支持的平台列表。如果你需要使用这两个尚未支持的平台之一,请提交问题。
安装
npm install -g ttctl
或者使用 npx 直接运行:
npx ttctl --help
加固安装(推荐)
为最大限度保障供应链安全,请在禁用 postinstall 钩子的情况下安装:
npm install -g --ignore-scripts ttctl
--ignore-scripts 会在安装时阻止整个依赖树中的 preinstall / postinstall / prepare 钩子。这可以防止受损的传递依赖(PhantomRaven、Shai-Hulud 等)在安装期间于你的计算机上执行代码,从而堵住针对包管理器用户、利用最频繁的供应链攻击途径。
TTCtl 本身不提供任何安装时钩子。禁用这些钩子纯粹是为了防范你无法直接控制的依赖项中的恶意行为。请参阅 SECURITY § 用户安装的供应链加固。
快速开始
# 1. Install
npm install -g ttctl
# 2. Bootstrap a config interactively (recommended)
# Walks you through Form A (1Password reference; vault + item picker
# when the `op` CLI is installed) or Form B (literal credentials,
# explicit warning). Output: ~/.ttctl.yaml at mode 0600.
ttctl auth init
# 3. Sign in (captures the bearer back into ~/.ttctl.yaml under auth.token)
ttctl auth signin
# 4. Verify
ttctl auth status
# 5. View your profile
ttctl profile show
ttctl auth init会以交互方式生成新的~/.ttctl.yaml。选择 Form A(1Password 引用,推荐)或 Form B(字面凭据,不推荐——会显示明确警告)。在 Form A 下,如果已安装opCLI,则会运行保险库选择器和 LOGIN 类别项目选择器。如果没有op或 JSON 结构格式不正确,提示会回退为自由输入的op://VAULT/ITEM引用。输出文件会以原子方式写入,权限模式为0600;除非传入--force,否则不会覆盖现有文件。此命令仅支持交互式运行——通过管道传入 stdin 或在非 TTY 环境中运行时,会退出并返回非零状态,同时显示清晰的消息。
ttctl auth signin会运行EmailPasswordSignInGraphQL mutation,获取会话 bearer,并将其写回同一个~/.ttctl.yaml文件中的auth.token(原子写入;保留注释;权限模式为0600)。此后,每个 GraphQL 请求都会通过Authorization: Token token=<X>重放该令牌。仅在 signin 时调用opCLI 来解析你的凭据。没有单独的令牌文件——配置和当前会话都存储在同一个 YAML 文件中。
手动编写配置也可以(在
~/.ttctl.yaml创建 YAML 文件,并运行chmod 600);下方的配置部分介绍了四种有效的auth结构。建议从ttctl auth init开始。
配置
TTCtl 使用单个配置文件——不支持配置档案。配置文件路径按确定性顺序解析(优先级最高者优先):
--config <path>标志 — 显式覆盖(单次调用有效)。TTCTL_CONFIG_FILE环境变量 — 进程级设置(CI、direnv)。~/.ttctl.yaml— POSIX 主目录点文件(仅作回退)。
不会自动发现 XDG 路径($XDG_CONFIG_HOME/ttctl/config.yaml、~/.config/ttctl/config.yaml)和当前工作目录中的 ./.ttctl.yaml。如需使用项目本地配置,请通过 direnv 将 TTCTL_CONFIG_FILE 指向该文件:
# .envrc in your project root (requires `direnv` installed and `direnv allow` run)
export TTCTL_CONFIG_FILE="$PWD/.ttctl.yaml"
排除同步根目录
如果配置文件位于已知的云同步路径前缀下,TTCtl 会拒绝持久化获取到的 bearer:
| 路径前缀 | 服务 |
|---|---|
~/Library/Mobile Documents/ | macOS iCloud Drive |
~/Dropbox/ | Dropbox |
~/iCloud Drive/ | iCloud(备用名称) |
~/OneDrive/ | OneDrive |
~/Google Drive/ | Google Drive |
~/Box/、~/Box Sync/ | Box |
在这些目录下持久化 bearer 会在不知情的情况下将其同步到本机之外。如果需要项目本地配置,请将其放在这些目录之外,并通过 TTCTL_CONFIG_FILE 指定(参见上面的 direnv 示例)。同级目录名称防护可避免误报——~/DropboxOther/ 不受影响。
auth — 四种有效的生命周期状态
auth 块采用结构化形式,包含可选的 credentials 和 token 字段。四种有效结构对应四种生命周期状态:
表单 A — 通过 1Password 引用提供凭据(推荐,signin 会填充 auth.token)
# Single 1Password account (or relying on `OP_ACCOUNT` env / op default)
auth:
credentials: "op://Personal/ttctl"
# Multiple 1Password accounts — pin one explicitly
auth:
credentials: "op://my-account/Personal/ttctl"
TTCtl 会解析 op://[ACCOUNT/]VAULT/ITEM,并运行 op item get ITEM --vault VAULT [--account ACCOUNT] --format json,然后通过匹配 purpose: USERNAME 和 purpose: PASSWORD 字段来解析凭据——这是 1Password 为 LOGIN 类别项目自动设置的规范语义标识符(包括由浏览器自动保存的登录信息,此类项目的字段标签是 HTML 表单输入名称,例如 user[email])。
仅当配置了多个 op 账户时(op account list),才需要可选的 ACCOUNT 段。单账户配置可以省略它。ACCOUNT 可以是账户 UUID、通过 op account add 设置的简写,或登录邮箱;TTCtl 会将该值原样传递给 op 进行验证。
表单 A2 — 按字段提供 1Password 引用(signin 会填充 auth.token)
# username and password each resolve from their own field-level op:// ref
auth:
credentials:
username: "op://Personal/ttctl/username"
password: "op://Personal/ttctl/password"
# account prefix works on field refs too (parity with Form A)
auth:
credentials:
username: "op://my-account/Personal/ttctl/username"
password: "op://my-account/Personal/ttctl/password"
当 credentials 是一个包含两个 op:// 字段引用的对象时,TTCtl 会针对每个字段运行一次 op read --no-newline [--account ACCOUNT] op://VAULT/ITEM/FIELD。op read 会通过 id 或标签解析字段,因此即使是浏览器自动保存的 LOGIN 项目,也可以使用规范的 username / password 字段 id。可选的前置 ACCOUNT 会被拆分出来并作为 --account 传递,以与表单 A 保持一致。
4 段式字段引用始终按带账户前缀的形式读取(
op://account/vault/item/field)。因此,1Password 的分区引用(op://vault/item/section/field,同样有 4 段)不受支持——分区会被误认为账户。请将凭据字段存储在项目顶层(LOGIN 项目默认如此)。
路由依据容器形状,而非段数(op://a/b/c 作为裸字符串时表示 account/vault/item,作为对象值时则表示 vault/item/field)。credentials 的裸字符串值始终表示单项目(表单 A),且仅限项目级。对象值在其值为 op:// 引用时表示按字段提供(本表单);在其值为邮箱/密码对时表示字面值(表单 B)。
表单 B — 字面凭据(仅用于开发/测试)
auth:
credentials:
username: "[email protected]" # value is your Toptal email; field name matches 1P USERNAME purpose
password: "hunter2"
不建议日常使用。配置文件中的明文凭据可能会通过备份、同步客户端和意外提交泄露。你需要的是表单 A。
项目级(表单 A)与按字段提供(表单 A2)。 表单 A 会从同一个 LOGIN 项目中读取 USERNAME 和 PASSWORD;表单 A2 则分别将每项凭据指向各自的字段。带有
/field后缀的裸字符串引用会被拒绝——按字段提供必须使用对象结构(一个字符串无法包含两个引用)。
表单 C — 仅令牌(带外引导)
auth:
token: "user_<24hex>_<20alnum>"
直接提供 bearer。ttctl auth signin 不适用(会因 NO_CREDENTIALS 而拒绝)。适用于 E2E 沙盒,以及通过旁路渠道引导令牌的部署。
表单 D — 凭据 + 令牌(表单 A 或 B signin 后)
auth:
credentials: "op://Personal/ttctl"
token: "user_<24hex>_<20alnum>"
针对表单 A 或 B 配置成功运行 ttctl auth signin 后,磁盘上的结构。两个字段会同时存在;signout 会移除 token 字段(恢复为表单 A 或 B),但不会改动 credentials。
分页
TTCtl 会按服务展示 wire 实际采用的分页模型。Toptal Talent 平台同时采用多种分页方式,没有统一的格式,而且 wire 会拒绝混用不同方式的请求(PR #383 通过实测证实了这一点:尝试在仅接受 limit 的字段中添加 offset 后,8 项端到端测试均因 HTTP 400 失败)。
ttctl 不会臆造一个统一的转换层,谎称 wire 接受某种格式,而是让标志名称对应 wire 参数名称,类型也与 wire 参数接受的类型一致。这样可以确保 AI / 脚本调用者遵循实际规则:标志名称与 wire 参数一一对应(有一项已记录的转换,见第 2 行)。
| 服务 | CLI 标志 | MCP 键 | Wire 方式 |
|---|---|---|---|
jobs list、applications list、engagements list | --page / --per-page | {page, perPage} | 偏移列表 (page, pageSize) |
payments payouts list | --page / --per-page(已转换) | {page, perPage}(已转换) | 偏移分页包装 (offsetPagination: {offset, limit}) |
timesheet pending (#374 后重新验证) | --limit | {limit} | 仅 limit 包装 (pagination: {limit}) |
| (未来的 engagements-payments) | --limit + --after <id> | {limit, after} | limit + 正向游标包装 (pagination: {limit, after}) |
| (未来的 performed-actions) | --before / --after / --limit | {before, after, limit} | 裸双向游标 (before, after, limit) |
这种异构设计是有意为之的 Sage 做法:统一的 --cursor <token> 层会让偏移分页服务无法通过整数组合页码进行脚本化;将动词拆分为 show-all 和 list 则会让命令树翻倍,却无法提供标志类型本身已能实现的区分。针对各服务的具体标志格式,请以相应的 --help 为准。
这 5 行语法已在 ADR-007 — 分页标志语法 中锁定。
申请职位
TTCtl 可通过 ttctl jobs apply <job-id> 直接申请职位。这是一项破坏性 wire 操作,会在 Toptal 一侧创建 JobApplication 记录,而且 TTCtl 没有 withdraw 操作(参见 ADR-008 § 我们不解决的问题)。建议先使用 --dry-run 预览 wire 负载。
同意门槛
必须提供 --consent——这表示你明确接受 Toptal 的申请条款(法律合规声明)。该标志没有默认值;根据 ADR-008 § 决策第 4 部分,禁止代为自动填写。若未提供,将引发 CONSENT_REQUIRED,且不会发出 wire 调用。
ttctl jobs apply <job-id> --consent
预览问题清单
大多数职位都要求先回答匹配问题/专业能力问题,apply 变更才会接受请求。--show-questions 会获取问题清单,但不会发出 apply 变更(只读路径;无需 --consent):
ttctl jobs apply <job-id> --show-questions
输出会列出每个问题的标识符、提示文本和应用前上下文(canApply、suggestedRate、rateValidation)。根据恢复的 SDL(#438),标识符在两个答案数组中的映射方式不同:匹配问题的答案使用 id;专业能力问题的答案使用 questionId(请参阅下方的 JSON 结构)。ttctl jobs show <job-id> --with-questions 是相关的只读操作,会将相同的问题清单内联到职位的完整详情视图中。
通过 --answers-file 提供答案
传入包含各问题答案的 JSON 文件。文件结构遵循 ADR-008 § Decision Part 2 的语法(与 applications confirm 用于 Interest Requests 的结构相同)。根据恢复的 SDL(#438),匹配问题和专业能力问题的答案使用不同的键结构:匹配问题的答案通过 id 携带问题标识符;专业能力问题的答案通过 questionId 携带标识符,并且还接受 other/subjectId(两者均可为 null):
{
"matcherAnswers": [
{ "id": "<matcher-question-id>", "answer": "<your-answer>" },
{ "id": "<matcher-question-id>", "answer": "<your-answer>" }
],
"expertiseAnswers": [
{ "questionId": "<expertise-question-id>", "other": null, "subjectId": null },
{ "questionId": "<expertise-question-id>", "other": "free-text-context", "subjectId": "<subject-id>" }
]
}
然后:
ttctl jobs apply <job-id> --consent --answers-file ./apply.json
传入 - 而不是路径,即可从 stdin 读取 JSON。封装结构和内部条目都会在任何线路调用之前根据恢复的 Zod 模式(根据 #438)进行验证——JSON 格式错误或包含未知键时,会返回 VALIDATION_ERROR 信封,且不会发出任何变更。
--pitch-file <path>(或使用 - 从 stdin 读取)会在答案旁附加一个 PitchInput 载荷;每次调用只能有一个标志使用 stdin。
试运行预览
--dry-run 会输出完整的应用预览信封(操作名称、接口、传输方式、GraphQL 变量),但不会发出线路变更。提交破坏性调用前,可用它验证载荷结构:
ttctl jobs apply <job-id> --consent --dry-run
--dry-run 模式下仍会执行 --consent 门控——即使只是预览,也必须提供法律合规声明(该门控是 CLI 层面的拒绝,而非线路层面的拒绝)。
Interest Requests
招聘人员通过 Toptal 的 Availability Request(AR)流程对你的个人资料表示兴趣时,你可以通过 applications confirm/applications reject 作出回应。确认 AR 是破坏性操作——它会将 AR 转换为 AVAILABILITY_REQUEST_CONFIRMED,并创建一个 JobApplication。没有撤回操作;建议先使用 --dry-run 预览线路载荷。
查找 AR id
<id> 参数指的是 AvailabilityRequest id,而不是活动项 id。检查活动行即可找到它:
ttctl applications show <activityId>
……并在输出中查找 Availability request: <id> 这一行。
确认 Interest Request
ttctl applications confirm <ar-id>
如果省略 --rate 和 --kind,服务会预先获取 AR 元数据并自动填入:
kind取自metadata.__typenamerate取自metadata.offeredHourlyRate(仅限 Fixed-kind)
Flexible-kind AR 没有招聘人员指定的费率;对于 FLEXIBLE/MARKETPLACE_FLEXIBLE AR,调用者必须传入 --rate <decimal>。
可选的 --answers-file/--pitch-file
如果 AR 包含匹配问题/专业能力问题或提示词,请使用与 jobs apply 相同的 JSON 文件语法提供答案:
ttctl applications confirm <ar-id> \
--answers-file ./answers.json \
--pitch-file ./pitch.json
两个标志都接受 -,用于从 stdin 读取(每次调用最多只能有一个标志使用 stdin)。答案文件结构与上文申请职位所示的结构相同。Pitch 载荷会根据恢复的 PitchInput Zod 模式(根据 #438)进行验证;额外的未知键会导致字段路径错误。
拒绝 Interest Request
ttctl applications reject <ar-id> --reason <key>
<key> 来自服务器本地化的 ttctl applications reject-reasons 清单。部分键需要同时提供 --comment <text>——拒绝原因清单会标明哪些键需要评论。
MCP 集成
TTCtl 实现了 Model Context Protocol(MCP),让 AI 助手能够通过自然语言与您的 Toptal Talent 个人资料交互。运行 ttctl mcp 可通过 stdio 启动 MCP 服务。
MCP 客户端配置
Claude Desktop
将以下内容添加到 claude_desktop_config.json:
{
"mcpServers": {
"ttctl": {
"command": "npx",
"args": ["ttctl", "mcp"]
}
}
}
Claude Code
claude mcp add ttctl -- npx ttctl mcp
Cursor
将以下内容添加到项目根目录中的 .cursor/mcp.json:
{
"mcpServers": {
"ttctl": {
"command": "npx",
"args": ["ttctl", "mcp"]
}
}
}
信任模型:任何能够启动
ttctl mcp的进程,都可以通过您保存的身份验证令牌,完全访问您的 Toptal Talent 个人资料。不要向不受信任的 AI Agent 授予 MCP 访问权限。请参阅 SECURITY.md。
数据处理——MCP 工具会将哪些内容返回到助手的上下文中
当 AI 助手调用 TTCtl MCP 工具时,工具的响应载荷——您的个人资料、合作项目、付款和合同——会进入助手的上下文窗口。从此刻起,您的 AI 助手宿主决定这些数据会如何处理:是否保留在聊天记录中、是否编入向量数据库索引、是否呈现给同一会话中加载的其他工具,或是否作为遥测数据的一部分上传。
TTCtl 无法限制宿主的行为。防护措施取决于您的使用选择。以下是三条具体建议:
- 选择符合您隐私要求的宿主。 当前宿主的默认设置(截至 2026-05;预计会发生变化)——Claude Code:按会话处理,跨会话持久化需选择启用;Claude Desktop:默认启用本地聊天记录持久化;Cursor:默认启用本地持久化,并默认将工具输出编入向量数据库索引;Windsurf:与 Cursor 类似;ChatGPT 桌面版:由供应商管理,应假定数据会持久化。具有向量索引功能的宿主(Cursor / Windsurf)可能会在未来不相关的对话中,因语义查询匹配而重新呈现您的 Toptal 数据——这是持久化目标中最难控制的特性。
- 在使用会返回第三方自由文本的 TTCtl 工具时,使用私密 / 临时聊天模式——这些文本包括合作项目评论、申请消息、职位描述、合同条款和评价评论。经常通过助手浏览职位或阅读合作项目备注的操作人员,应考虑在宿主端建立专用于 TTCtl 任务的工作区(Cursor:单独的工作区;Claude Code:按项目限定范围)。
- 不要将 TTCtl 与您无法控制的外发工具一同加载。 网页获取工具、任意文件系统写入工具,或具有自身应用路径的同级 MCP 服务,会使跨工具数据泄露成为现实威胁:嵌入 Toptal 合作项目备注中的恶意指令可能会调用同级工具的应用路径,且没有
dryRun防护。缓解措施应在会话层面实施——仅在加载工具均受操作人员信任的会话中使用 TTCtl。
完整的威胁模型——包括逐工具审计、严重性评级标准、缓解措施权衡分析和剩余风险登记表——请参阅 docs/security/mcp-leakage-threat-model.md。《SECURITY.md § MCP Trust Model》中的配套章节介绍了输入侧防护措施(通过 dryRun 缓解状态变更、文件上传沙箱)。
故障排查
auth signin / auth signout 的调试日志
如果登录后写回 ~/.ttctl.yaml 时出现异常情况,例如静默覆盖、因 mtime 漂移而拒绝写入、锁竞争,或神秘的“拒绝写入”消息,请启用结构化调试日志,以查看具体触发了哪项不变量,以及文件在每个步骤中的状态:
TTCTL_DEBUG_CONFIG=1 ttctl auth signin
每行会在 stderr 上输出一个 JSON 对象(因此 -o json 模式下的 stdout 保持干净)。绝不会记录 bearer token。可通过 jq 管道查看:
TTCTL_DEBUG_CONFIG=1 ttctl auth signin 2> debug.log
jq -c '.' debug.log
每条记录都包含 ts(ISO-8601)、op(persist 或 clear)、path 和 event。事件专属字段会说明发生了什么:
| 事件 | 含义 | 有用的字段 |
|---|---|---|
prewrite_checks | 符号链接/同步根目录检查已通过 | symlink_ok、syncroot_ok、perm_ok |
lock_acquired | 已获取跨进程写锁 | wait_ms(是否发生竞争?) |
stat_baseline | 已捕获写入前的文件状态 | mtime_ms、mode_octal |
tempfile_written | 临时文件已刷新到磁盘 | temp_path、size_bytes |
final_state | 重命名前已将模式应用到临时文件 | mode_applied |
mtime_drift_check | 与基线进行并发重新检查 | delta_ms、pass(false ⇒ 另一个写入者与你发生竞争) |
rename_completed | 已原子重命名到规范路径 | — |
lock_released | 已在 finally 中释放锁 | duration_ms(总持有时长) |
error | 锁定区域内发生异常 | error_class、error_message、lock_held_at_error |
如果看到 error 事件后没有 lock_released 事件,说明可能发生了锁泄漏——请提交问题报告。错误路径始终会发出 lock_released(释放操作位于 finally 中,无论触发了哪项不变量都会运行)。
当未设置 TTCTL_DEBUG_CONFIG(或其值不是字面量 1——0、true、空字符串都视为“关闭”)时,日志记录器保持静默,且每次调用的开销为零。
远程熔断开关(线缆断裂防护)
TTCtl 是通过逆向工程 Toptal 的 APK 得出的;线缆格式可能随时更改,恕不另行通知。作为纵深防御信号,CLI 会在启动时从 https://raw.githubusercontent.com/alexey-pelykh/ttctl/main/status/known-broken.json 获取一个小型 JSON 清单;如果正在运行的版本被列为已知故障版本,则发出警告(或拒绝运行)。MCP 服务也会在 buildServer 时执行相同检查,并每隔约 24 小时重新获取一次,但始终只发出警告,不会拒绝运行(拒绝运行会中断长期运行的服务中正在进行的工具调用)。
-
延迟开销:同步获取,超时时间为 3 s。访问 raw.githubusercontent.com 的典型延迟为 50–200 ms;最坏情况下,操作运行前会等待 3 s。
-
隐私:获取请求只发送 Node
fetch的默认请求头——不包含版本、账号标识符或遥测数据。安装量跟踪已刻意推迟。 -
静默失败:所有错误路径(网络、超时、404、清单格式错误)都会被忽略。当维护者的仓库短暂无法访问时,熔断开关绝不会因此导致拒绝服务。
-
覆盖 — 使用以下设置完全禁用检查:
export TTCTL_DISABLE_KILL_SWITCH=1在模块加载时捕获(与
TTCTL_DEBUG_CONFIG/TTCTL_DEBUG_MCP/TTCTL_MCP_FILE_UPLOAD_ALLOW_ANY的约定一致)。其他任何值(空字符串、0、true)都会保持检查启用。
检测来源、严重性等级、响应节奏以及 C&D / 法律立场记录在 docs/operations/wire-breakage-runbook.md 中。清单架构和更新流程见 status/README.md。
TTCtl 的底层工作原理
Toptal Talent 平台提供三个 GraphQL 端点:
https://www.toptal.com/gateway/graphql/talent/graphql— 供移动应用使用;接受普通 HTTPS + 会话 Cookiehttps://www.toptal.com/api/talent_profile/graphql— 供网页个人资料编辑器使用;受 Cloudflare 保护(需要模拟浏览器 TLS 指纹)https://scheduler.toptal.com/api/graphql— 供调度器使用;位于独立的 Cloudflare 区域
TTCtl 使用两种传输方式:
身份验证基于 Bearer 令牌(依据私有 ttctl/research 仓库中的 ADR-005):TTCtl 以持久化查询模式 POST EmailPasswordSignIn(使用从已捕获的操作目录中取得的 SHA-256 哈希),捕获返回的会话令牌,将其原子写入同一个 ~/.ttctl.yaml 配置中的 auth.token(权限模式为 0600),并在后续每次 GraphQL 请求中将其作为 Authorization: Token token=<X> 重放。不使用 Cookie;仅通过 Chrome TLS 模拟即可通过受保护站点的 Cloudflare 检查。
逆向工程产物(已解码的 APK、GraphQL 操作目录、架构推导、ADR)存放在单独的私有仓库(ttctl/research)中,不可再分发。
免责声明
TTCtl 是一个独立的个人效率项目,与 Toptal、Toptal LLC 或任何 Toptal 实体均无关联、未获其认可,也未与其建立官方联系。
本软件提供给你这位 Toptal 人才,作为更高效地管理你自己的个人资料数据的工具。使用它与非本人资料互动、以超出人工操作能力的规模开展联系、操纵平台端指标,或提取其他各方的数据,都违背公平使用的精神以及 Toptal 的服务条款。
维护者不提供任何保证,也不对违反平台条款的使用承担责任。如果 Toptal LLC 对 TTCtl 的存在提出异议并善意联系维护者,维护者将与其合作解决相关问题。
“Toptal” 是 Toptal LLC 的商标。本项目描述中对该名称的使用仅属于指称性合理使用——用于标识 TTCtl 所交互的第三方平台。
如需详细了解本项目对商标使用、服务条款、选择 AGPL 以及此类工具所遵循的合理使用传统的立场,请参阅 docs/legitimacy.md。
支持
TTCtl 是通过逆向工程 Toptal 的 APK 实现的;通信格式可能在不另行通知的情况下发生变化,而维护者唯一能得知变化的途径就是你的报告。没有遥测、没有错误报告端点,也不跟踪安装次数——下方渠道就是全部反馈途径。
通信协议对你失效了——ttctl <command> 运行失败
如果 TTCtl 命令报错或返回意外响应(404、难以理解的 GraphQL 错误、WIRE_SHAPE_ERROR 信封等),请提交 通信协议对我失效了问题。模板会收集 ttctl --version、失败的命令、错误文本,以及 ttctl auth status 是否仍能成功——这些信息足以让维护者对照 status/known-broken.json 中的熔断清单和通信协议故障处理手册进行分类处理。
提交前,请检查熔断清单:https://raw.githubusercontent.com/alexey-pelykh/ttctl/main/status/known-broken.json——如果其中列出了你的版本,维护者已经知晓。
MCP 宿主无法调用工具
如果 MCP 宿主(Claude Desktop、Claude Code、Cursor、Windsurf 等)无法显示或调用 TTCtl 工具——问题出在宿主 ↔ 服务边界,而非 Toptal 通信协议——请提交 MCP 宿主无法调用工具问题。模板会收集宿主产品及版本、失败的工具名称、宿主显示的错误,以及可选的 TTCTL_DEBUG_MCP=1 服务端跟踪信息。
问题、想法、“这是预期行为吗?”
问题、使用帮助、想法,或“其他人也遇到这个情况了吗?”请使用 Discussions;问题跟踪器仅用于确认的故障和功能请求。
安全漏洞
安全漏洞请勿公开提交问题。有关协调披露渠道,请参阅 SECURITY.md § 报告漏洞。
滥用行为举报
如果你发现 TTCtl 被用于违反 Toptal 服务条款的行为(大规模自动化、抓取招聘人员信息、操纵互动信号等),请参阅 SECURITY.md § 滥用行为举报。
举报时的隐私保护
~/.ttctl.yaml 包含你捕获的 bearer 令牌(auth.token,格式为 user_<24hex>_<20alnum>)。**切勿将其粘贴到公开问题或 Discussions 帖子中。**TTCtl 的调试输出器(TTCTL_DEBUG_CONFIG、TTCTL_DEBUG_MCP)设计为绝不打印 bearer 值,但你的 shell 会话记录中可能包含这些值——粘贴前请检查并将其编辑为 <REDACTED>。
行为准则
本项目采用 Contributor Covenant 行为准则(3.0 版)。该准则适用于所有项目空间,以及所有与项目互动的人——包括问题跟踪器、拉取请求、MCP 服务交互及其他任何渠道。
如需报告问题,请发送邮件至 [email protected]。我们接受使用化名的报告;完全匿名的报告无法受理(维护者会直接查看收件箱)。我们会尽力在 7 天内回复。
许可证
AGPL 对你的意义
- 将
ttctl用作命令行工具或 MCP 服务不会使你的代码受 AGPL 许可约束。运行该工具、围绕它编写脚本,或将它连接到你的应用程序,都属于正常使用——不会产生许可义务。 - 将
@ttctl/core用作库(在你的代码中导入它)意味着你的组合著作受 AGPL-3.0 约束。如果你分发该组合著作,必须以兼容 AGPL 的条款提供其源代码。 - 修改并分发 TTCtl 本身要求你依据 AGPL-3.0 分享所做的更改。
- 目前不提供商业许可。TTCtl 是个人效率项目,并非产品。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。