pr-create by posit-dev/skills
npx skills add https://github.com/posit-dev/skills --skill pr-create将更改纳入 PR,监控 CI,修复任何失败,并在 PR 准备好审查时通知用户。
用户可能已经在功能分支上准备好了提交,或者可能有未提交的更改,或者两者都有。根据当前状态调整工作流程。
关键: 使用 Claude Code 的任务列表系统进行进度跟踪和会话恢复。在整个执行过程中使用 TaskCreate、TaskUpdate 和 TaskList 工具。
[主任务] "创建 PR: [分支名称]"
└── [CI 任务] "CI 运行 #1" (状态: 失败, 原因: lint)
└── [修复任务] "修复: lint"
└── [CI 任务] "CI 运行 #2" (状态: 失败, 原因: 测试失败)
└── [修复任务] "修复: 测试失败"
└── [CI 任务] "CI 运行 #3" (状态: 通过)
开始时,始终调用 TaskList 来检查现有的 PR 任务。 如果存在状态为 in_progress 的"创建 PR"任务,请使用下面的会话恢复部分恢复。
检查用户消息中是否有 --reviewer 参数。 如果存在,存储该值以备步骤 5 使用。它可能是 GitHub 句柄 (@username) 或姓名 (Jane Doe)。
创建主 PR 任务:
TaskCreate:
- subject: "创建 PR: [分支名称 或 'pending']"
- description: "从当前更改创建拉取请求。"
- activeForm: "正在检查 git 状态"
TaskUpdate:
- taskId: [pr 任务 ID]
- status: "in_progress"
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
确定基础分支和当前状态:
git status
git diff --stat
# 检测默认分支 (main, master, develop 等)
gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name'
git log --oneline <基础分支>..HEAD
gh pr view 2>/dev/null
确定起点:
| 状态 | 下一步 |
|---|---|
| 在基础分支上,有未提交的更改 | 步骤 2 (创建分支) |
| 在功能分支上,有未提交的更改 | 步骤 3 (提交) |
| 在功能分支上,有提交,没有未提交的更改 | 步骤 4 (同步) |
| 此分支已存在 PR | 通知用户,询问是更新还是监控 CI |
| 任何地方都没有更改 | 通知用户"未检测到更改。无事可做。"并停止 |
使用分支信息更新任务:
TaskUpdate:
- taskId: [pr 任务 ID]
- subject: "创建 PR: [实际分支名称]"
- metadata: {"branch": "[分支名称]", "baseBranch": "[基础分支]"}
如果当前在基础分支上:
git checkout -b <描述性分支名称>
如果项目在 CLAUDE.md 或 AGENTS.md 中记录了分支命名规范,则使用该规范。否则使用:
feat/简短描述 用于功能fix/简短描述 用于错误修复refactor/简短描述 用于重构docs/简短描述 用于文档如果没有任何未提交的更改,完全跳过此步骤。
暂存特定文件,而不是使用 git add -A:
git status
git add <文件1> <文件2> ...
git diff --cached --stat
git commit -m "$(cat <<'EOF'
<类型>: <简短摘要>
<可选的长描述>
EOF
)"
如果项目在 CLAUDE.md 或 AGENTS.md 中记录了提交规范,则遵循该规范。否则使用约定式提交:feat:、fix:、refactor:、docs:、test:、chore:。
如果由于预提交钩子导致提交失败:
git fetch origin
git log --oneline HEAD..origin/<基础分支> | head -20
如果是最新的(没有输出),则继续步骤 5。
如果落后,通知用户落后了多少次提交,并使用 AskUserQuestion 提供选项:
未经用户确认,请勿进行变基或合并。
如果出现冲突,通知用户并帮助解决。
现在获取用户对 PR 内容的批准,在运行预检检查之前。这使用户在专注于任务时保持参与。
5a. 收集上下文:
git log --oneline <基础分支>..HEAD
git diff <基础分支>...HEAD --stat
5b. 起草 PR 标题和正文:
如果项目在 CLAUDE.md 或 AGENTS.md 中记录了 PR 规范,则遵循该规范。否则:
标题: 少于 70 个字符,描述更改
正文: 第一行以问题引用开头(例如 Closes #45),然后是结构化描述:
[问题引用: Fixes #...]
<摘要>
<如何验证>
摘要:概述 PR 中的更改。目标受众是熟悉此代码库的经验丰富的开发者,他们需要了解设计或架构变更。突出关键决策、结构和模式。
验证:包含一个示例,演示目标受众看到或使用的 PR 中的更改。对于代码包,包含一个小的、可重现的示例。对于应用程序和界面,描述查看新行为所需的步骤。
5c. 预览并获取用户批准:
关键: 使用 AskUserQuestion 向用户显示提议的 PR 标题和正文。在同一交互中也包含审阅者问题:
--reviewer,解析并确认 GitHub 句柄(见下文),然后将其作为预览的一部分显示。AskUserQuestion 调用中询问他们是否希望请求任何人审阅(自由文本,可选)。按姓名解析审阅者(非句柄): 如果审阅者值看起来不像 GitHub 句柄(没有 @,不明确是用户名),则查找正确的句柄:
# 首先检查仓库中的近期贡献者
gh api repos/{owner}/{repo}/contributors --jq '.[].login' | head -20
# 如果在贡献者中未找到,则搜索 GitHub 用户
gh api search/users?q=<姓名>+in:name --jq '.items[] | "\(.login) \(.name // "")"' | head -10
在存储之前与用户确认解析后的句柄。
将确认的审阅者句柄存储在任务元数据中:
TaskUpdate:
- taskId: [pr 任务 ID]
- metadata: {"reviewer": "<github-句柄>"}
在 PR 预览的 AskUserQuestion 调用中直接包含批准选项。选项应为:
在用户选择其中一个选项之前,请勿创建 PR。
5d. 显示计划大纲(仅当用户选择选项 2 时):
在继续之前呈现以下内容:
以下是我接下来要做的事情:
- 运行本地检查(如果此项目可用)
- 推送分支到 origin
- 创建 PR 作为草稿,使用批准的标题和正文
- 监控 CI 并修复任何失败
- 发布 PR(移除草稿状态),一旦 CI 通过
- 请求审阅 来自
@<审阅者>(如果适用)
我会自动修复小问题(格式化、lint、类型错误、测试失败)。如果出现任何更大的问题,我会先与你确认。
显示大纲后,在继续到步骤 6 之前,再询问一次 AskUserQuestion 以确认。
此步骤在推送之前捕获大多数 CI 失败。
通过查阅以下内容确定项目的本地检查命令(按优先级顺序):
package.json (scripts)、Makefile、pyproject.toml、DESCRIPTION、Justfile、Taskfile.yml 等。.github/workflows/ 中的 CI 工作流文件,以了解 CI 将运行什么运行本地可用的检查。常见模式:
npm run lint、ruff check、air format、biome check 等。npm run build、pip install -e .、devtools::check() 等。npm run check-types、mypy、pyright 等。npm test、pytest、devtools::test()、cargo test 等。如果无法发现本地检查命令,则跳过此步骤并依赖 CI。
修复失败:
明显的、机械性的修复 — 自主修复:
git add -A)非明显的失败 — 使用 AskUserQuestion 呈现问题并提供解决选项
git push -u origin <分支名称>
将 PR 创建为草稿,以便在 CI 仍在运行时不会过早发送审阅。
GitHub 的 markdown 解析器逐字渲染每个换行符 — 不要在 PR 正文中换行长行。将每个段落写成单个不间断的行。
gh pr create --draft --title "<批准的标题>" --body "$(cat <<'EOF'
<批准的正文>
EOF
)"
捕获 PR URL 并存储在任务元数据中:
TaskUpdate:
- taskId: [pr 任务 ID]
- metadata: {"prUrl": "<url>", "prNumber": <N>, "prTitle": "<标题>", "commits": <计数>}
创建 CI 运行任务:
TaskCreate:
- subject: "CI 运行 #[N]: 监控中"
- description: "监控 PR #[编号] 的 CI 运行"
- activeForm: "正在监控 CI 运行 #[N]"
TaskUpdate:
- taskId: [ci 任务 ID]
- addBlockedBy: [pr 任务 ID]
- status: "in_progress"
等待 CI 启动,然后监控:
# 列出此 PR 的工作流运行
gh run list --branch <分支名称> --limit 5
# 静默监视特定运行直到完成
# --exit-status 在成功时返回退出代码 0,失败时返回非零
gh run watch <运行 ID> --exit-status > /dev/null 2>&1
echo "退出: $?"
# 或者在不阻塞的情况下检查状态
gh run view <运行 ID>
重要: 不要在没有重定向输出的情况下运行 gh run watch。它会生成数千行重复的状态更新。始终重定向到 /dev/null 并依赖退出代码。
将运行 ID 存储在任务中:
TaskUpdate:
- taskId: [ci 任务 ID]
- metadata: {"runId": "[运行 ID]", "status": "running"}
TaskUpdate:
- taskId: [ci 任务 ID]
- subject: "CI 运行 #[N]: 通过"
- status: "completed"
- metadata: {"status": "passed"}
发布 PR(移除草稿状态):
gh pr ready <pr-编号>
请求审阅(如果在任务元数据中存储了审阅者):
gh pr edit <pr-编号> --add-reviewer <github-句柄>
TaskUpdate:
- taskId: [ci 任务 ID]
- subject: "CI 运行 #[N]: 失败"
- status: "completed"
- metadata: {"status": "failed", "failureReason": "[简要原因]"}
--log-failed 可能产生数千行。使用有针对性的方法:
# 哪些作业/步骤失败的摘要
gh run view <运行 ID>
# 失败的日志,限制在最后 40 行(错误通常在此处)
gh run view <运行 ID> --log-failed 2>&1 | tail -40
# 如果需要,搜索特定错误
gh run view <运行 ID> --log-failed 2>&1 | grep -A 5 -B 5 "error\|Error\|FAIL\|failed"
从输出底部向上工作 — 实际错误几乎总是在末尾附近。
在本地重现 使用项目的本地检查命令(在步骤 6 中发现)。
创建修复任务:
TaskCreate:
- subject: "修复: [失败原因]"
- description: "修复来自运行 #[N] 的 CI 失败: [详细错误]"
- activeForm: "正在修复 [失败原因]"
TaskUpdate:
- taskId: [修复任务 ID]
- addBlockedBy: [ci 任务 ID]
- status: "in_progress"
修复问题,在本地验证,然后提交并推送:
git add <特定文件>
git commit -m "$(cat <<'EOF'
fix: <修复了什么>
EOF
)"
git push
标记修复任务为已完成:
TaskUpdate:
- taskId: [修复任务 ID]
- status: "completed"
返回步骤 9 — 监控新的 CI 运行(递增运行编号)
重复直到 CI 通过。
将主 PR 任务标记为已完成。
调用 TaskList 收集所有 CI 运行和修复任务,然后生成摘要:
## PR 已准备好审阅
**PR:** [#<编号> <标题>](<url>)
**分支:** `<分支名称>` -> `<基础分支>`
**提交:** <计数>
**CI 状态:** 所有检查通过
**审阅者:** @<句柄> (如果已请求)
### CI 运行
- 运行 #1: 失败 (lint) -> 在 [哈希] 中修复
- 运行 #2: 通过
**注意:** 此 PR 尚未合并。请手动审阅并合并。
如果从中断的会话恢复:
TaskList 显示:
├── PR 任务 in_progress,无 CI 任务
│ └── PR 已创建,开始监控 CI (步骤 9)
├── PR 任务 in_progress,CI 任务 in_progress
│ └── 从任务元数据 runId 恢复监控 CI 运行
├── PR 任务 in_progress,CI 任务失败,无修复任务
│ └── 分析失败并创建修复任务 (步骤 10)
├── PR 任务 in_progress,修复任务 in_progress
│ └── 继续修复,然后推送并监控新的 CI 运行
├── PR 任务 completed
│ └── PR 已完成,显示最终报告
└── 无任务存在
└── 全新开始 (步骤 1)
恢复时,使用 CI 任务元数据中的 gh run view <runId> 检查运行是否仍处于活动状态、已完成或被取代。在恢复之前通知用户当前状态。
git add -A 或 git add .gh pr create --draft;仅在 CI 通过后使用 gh pr ready 发布身份验证问题: 如果 gh 命令因身份验证错误而失败,通知用户运行 gh auth login。
分支冲突: 提供变基或合并选项。解决任何冲突,然后继续。
PR 已存在: 通知用户此分支已存在 PR。询问他们是否要更新它或监控其 CI。
预提交钩子失败: 阅读钩子错误输出,修复标记的问题,暂存修复,并创建新的提交。不要修改。
每周安装
89
仓库
GitHub 星标
205
首次出现
2026年2月17日
安全审计
安装于
opencode80
claude-code80
github-copilot80
codex79
amp78
kimi-cli78
Get changes into a PR, monitor CI, fix any failures, and notify the user when the PR is ready for review.
The user may already have commits ready on a feature branch, or may have uncommitted changes, or both. Adapt the workflow to the current state.
CRITICAL: Use Claude Code's task list system for progress tracking and session recovery. Use TaskCreate, TaskUpdate, and TaskList tools throughout execution.
[Main Task] "Create PR: [branch-name]"
└── [CI Task] "CI Run #1" (status: failed, reason: lint)
└── [Fix Task] "Fix: lint"
└── [CI Task] "CI Run #2" (status: failed, reason: test failures)
└── [Fix Task] "Fix: test failures"
└── [CI Task] "CI Run #3" (status: passed)
At the start, always call TaskList to check for existing PR tasks. If a "Create PR" task exists with status in_progress, resume using the Session Recovery section below.
Check for a--reviewer argument in the user's message. If present, store the value for use in Step 5. It may be a GitHub handle (@username) or a name (Jane Doe).
Create the main PR task:
TaskCreate:
- subject: "Create PR: [branch-name or 'pending']"
- description: "Create pull request from current changes."
- activeForm: "Checking git status"
TaskUpdate:
- taskId: [pr task ID]
- status: "in_progress"
Determine the base branch and current state:
git status
git diff --stat
# Detect the default branch (main, master, develop, etc.)
gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name'
git log --oneline <base-branch>..HEAD
gh pr view 2>/dev/null
Determine the starting point:
| State | Next Step |
|---|---|
| On base branch with uncommitted changes | Step 2 (create branch) |
| On feature branch with uncommitted changes | Step 3 (commit) |
| On feature branch with commits, nothing uncommitted | Step 4 (sync) |
| PR already exists for this branch | Inform user, ask whether to update or monitor CI |
| No changes anywhere | Inform user "No changes detected. Nothing to do." and stop |
Update task with branch info:
TaskUpdate:
- taskId: [pr task ID]
- subject: "Create PR: [actual-branch-name]"
- metadata: {"branch": "[branch-name]", "baseBranch": "[base-branch]"}
If currently on the base branch:
git checkout -b <descriptive-branch-name>
Use the project's branch naming conventions if documented in CLAUDE.md or AGENTS.md. Otherwise use:
feat/short-description for featuresfix/short-description for bug fixesrefactor/short-description for refactoringdocs/short-description for documentationSkip this step entirely if there are no uncommitted changes.
Stage specific files rather than using git add -A:
git status
git add <file1> <file2> ...
git diff --cached --stat
git commit -m "$(cat <<'EOF'
<type>: <short summary>
<optional longer description>
EOF
)"
Follow the project's commit conventions if documented in CLAUDE.md or AGENTS.md. Otherwise use conventional commits: feat:, fix:, refactor:, docs:, test:, chore:.
If the commit fails due to a pre-commit hook:
git fetch origin
git log --oneline HEAD..origin/<base-branch> | head -20
If up to date (no output), proceed to Step 5.
If behind , inform the user how many commits behind and offer options using AskUserQuestion:
Do NOT rebase or merge without user confirmation.
If conflicts arise, inform the user and help resolve them.
Get user approval on the PR content now , before running pre-flight checks. This keeps the user engaged while they're focused on the task.
5a. Gather context:
git log --oneline <base-branch>..HEAD
git diff <base-branch>...HEAD --stat
5b. Draft the PR title and body:
Follow the project's PR conventions if documented in CLAUDE.md or AGENTS.md. Otherwise:
Title: Under 70 characters, describes the change
Body: Start with issue references on the first line (e.g. Closes #45), then a structured description:
[issue references: Fixes #...]
Summary: Give an overview of the changes in the PR. The target audience is an experienced developer who works in this code base and needs to be informed about design or architectural changes. Highlight key decisions, structures and patterns.
Verification: include an example that demonstrates the changes in the PR as seen or used by the intended audience. For code packages, include a small, reproducible exmaple. For apps and interfaces, describe the steps required to see the new behavior.
5c. Preview and get user approval:
CRITICAL: Use AskUserQuestion to show the user the proposed PR title and body. Also include a reviewer question in this same interaction:
--reviewer was provided, resolve and confirm the GitHub handle (see below), then show it as part of the preview.AskUserQuestion call whether they want to request a review from anyone (free-text, optional).Resolving a reviewer by name (not handle): If the reviewer value doesn't look like a GitHub handle (no @, not clearly a username), look up the correct handle:
# Check recent contributors in the repo first
gh api repos/{owner}/{repo}/contributors --jq '.[].login' | head -20
# Search GitHub users if not found in contributors
gh api search/users?q=<name>+in:name --jq '.items[] | "\(.login) \(.name // "")"' | head -10
Confirm the resolved handle with the user before storing it.
Store the confirmed reviewer handle in task metadata:
TaskUpdate:
- taskId: [pr task ID]
- metadata: {"reviewer": "<github-handle>"}
Include approval options directly in the AskUserQuestion call for the PR preview. The options should be:
Do NOT create the PR until the user has selected one of these options.
5d. Show plan outline (only if user selected option 2):
Present the following before continuing:
Here's what I'll do next:
- Run local checks (if available for this project)
- Push the branch to origin
- Create the PR as a draft with the approved title and body
- Monitor CI and fix any failures
- Publish the PR (remove draft status) once CI passes
- Request a review from
@<reviewer>(if applicable)
I'll auto-fix small issues (formatting, lint, type errors, test failures). If anything bigger comes up, I'll check with you first.
After showing the outline, ask one more AskUserQuestion to confirm before proceeding to Step 6.
This step catches most CI failures before pushing.
Determine the project's local check commands by consulting (in priority order):
package.json (scripts), Makefile, pyproject.toml, DESCRIPTION, Justfile, Taskfile.yml, etc..github/workflows/ to understand what CI will runRun the checks that are available locally. Common patterns:
npm run lint, ruff check, air format, biome check, etc.npm run build, pip install -e ., devtools::check(), etc.npm run check-types, mypy, pyright, etc.If no local check commands are discoverable, skip this step and rely on CI.
Fixing failures:
Obvious, mechanical fixes — fix autonomously:
git add -A)Non-obvious failures — use AskUserQuestion to present the issue and offer resolution options
git push -u origin <branch-name>
Create the PR as a draft so it is not prematurely sent for review while CI is still running.
GitHub's markdown parser renders every newline literally — do not wrap long lines in the PR body. Write each paragraph as a single unbroken line.
gh pr create --draft --title "<approved-title>" --body "$(cat <<'EOF'
<approved-body>
EOF
)"
Capture the PR URL and store in task metadata:
TaskUpdate:
- taskId: [pr task ID]
- metadata: {"prUrl": "<url>", "prNumber": <N>, "prTitle": "<title>", "commits": <count>}
Create a CI run task:
TaskCreate:
- subject: "CI Run #[N]: monitoring"
- description: "Monitoring CI run for PR #[number]"
- activeForm: "Monitoring CI Run #[N]"
TaskUpdate:
- taskId: [ci task ID]
- addBlockedBy: [pr task ID]
- status: "in_progress"
Wait for CI to start, then monitor:
# List workflow runs for this PR
gh run list --branch <branch-name> --limit 5
# Watch a specific run silently until completion
# --exit-status returns exit code 0 on success, non-zero on failure
gh run watch <run-id> --exit-status > /dev/null 2>&1
echo "Exit: $?"
# Or check status without blocking
gh run view <run-id>
IMPORTANT: Do NOT run gh run watch without redirecting output. It generates thousands of lines of repeated status updates. Always redirect to /dev/null and rely on the exit code.
Store run ID in task:
TaskUpdate:
- taskId: [ci task ID]
- metadata: {"runId": "[run-id]", "status": "running"}
TaskUpdate:
- taskId: [ci task ID]
- subject: "CI Run #[N]: passed"
- status: "completed"
- metadata: {"status": "passed"}
Publish the PR (remove draft status):
gh pr ready <pr-number>
Request a review (if a reviewer was stored in task metadata):
gh pr edit <pr-number> --add-reviewer <github-handle>
TaskUpdate:
- taskId: [ci task ID]
- subject: "CI Run #[N]: failed"
- status: "completed"
- metadata: {"status": "failed", "failureReason": "[brief reason]"}
--log-failed can produce thousands of lines. Use a targeted approach:
# Summary of which jobs/steps failed
gh run view <run-id>
# Failed logs, limited to the last 40 lines (where the error usually is)
gh run view <run-id> --log-failed 2>&1 | tail -40
# Search for specific errors if needed
gh run view <run-id> --log-failed 2>&1 | grep -A 5 -B 5 "error\|Error\|FAIL\|failed"
Work from the bottom of the output upward — the actual error is almost always near the end.
Reproduce locally using the project's local check commands (discovered in Step 6).
Create a fix task:
TaskCreate:
- subject: "Fix: [failure reason]"
- description: "Fixing CI failure from Run #[N]: [detailed error]"
- activeForm: "Fixing [failure reason]"
TaskUpdate:
- taskId: [fix task ID]
- addBlockedBy: [ci task ID]
- status: "in_progress"
Fix the issue , verify locally, then commit and push:
git add <specific-files>
git commit -m "$(cat <<'EOF'
fix: <what was fixed>
EOF
)"
git push
Mark fix task completed:
TaskUpdate:
- taskId: [fix task ID]
- status: "completed"
Return to Step 9 — monitor the new CI run (increment run number)
Repeat until CI passes.
Mark main PR task as completed.
Call TaskList to gather all CI run and fix tasks, then generate the summary:
## PR Ready for Review
**PR:** [#<number> <title>](<url>)
**Branch:** `<branch-name>` -> `<base-branch>`
**Commits:** <count>
**CI Status:** All checks passed
**Reviewer:** @<handle> (if requested)
### CI Runs
- Run #1: Failed (lint) -> Fixed in [hash]
- Run #2: Passed
**Note:** This PR has NOT been merged. Please review and merge manually.
If resuming from an interrupted session:
TaskList shows:
├── PR task in_progress, no CI tasks
│ └── PR was created, start monitoring CI (Step 9)
├── PR task in_progress, CI task in_progress
│ └── Resume monitoring CI run from task metadata runId
├── PR task in_progress, CI task failed, no fix task
│ └── Analyze failure and create fix task (Step 10)
├── PR task in_progress, fix task in_progress
│ └── Continue fixing, then push and monitor new CI run
├── PR task completed
│ └── PR is done, show final report
└── No tasks exist
└── Fresh start (Step 1)
When resuming, use gh run view <runId> from CI task metadata to check if the run is still active, completed, or superseded. Inform the user of the current state before resuming.
git add -A or git add .gh pr create --draft; publish with gh pr ready only after CI passesAuthentication issues: If gh commands fail with auth errors, inform the user to run gh auth login.
Branch conflicts: Offer rebase or merge options. Resolve conflicts if any, then continue.
PR already exists: Inform user a PR already exists for this branch. Ask if they want to update it or monitor its CI.
Pre-commit hook failures: Read the hook error output, fix the flagged issues, stage the fixes, and create a new commit. Do NOT amend.
Weekly Installs
89
Repository
GitHub Stars
205
First Seen
Feb 17, 2026
Security Audits
Gen Agent Trust HubPassSocketWarnSnykWarn
Installed on
opencode80
claude-code80
github-copilot80
codex79
amp78
kimi-cli78
Azure Data Explorer (Kusto) 查询技能:KQL数据分析、日志遥测与时间序列处理
138,800 周安装
Cosmos 漏洞扫描器 - 9种关键漏洞模式,审计Cosmos SDK与CosmWasm智能合约安全
1,500 周安装
AddressSanitizer (ASan) 内存错误检测工具:模糊测试与C/C++调试指南
1,500 周安装
C++专家技能:现代C++20/23开发、高性能计算、零开销抽象编程指南
1,500 周安装
Linear 项目管理技能:AI 驱动的问题跟踪与团队协作自动化工作流
1,500 周安装
Vue Pinia最佳实践:状态管理常见陷阱与解决方案指南
1,500 周安装
React项目代码修复工具 - 自动格式化与检查,提升代码质量与CI通过率
1,400 周安装
npm test, pytest, devtools::test(), cargo test, etc.