[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"similar-antiwork--shortest":3,"tool-antiwork--shortest":64},[4,17,27,35,43,56],{"id":5,"name":6,"github_repo":7,"description_zh":8,"stars":9,"difficulty_score":10,"last_commit_at":11,"category_tags":12,"status":16},3808,"stable-diffusion-webui","AUTOMATIC1111\u002Fstable-diffusion-webui","stable-diffusion-webui 是一个基于 Gradio 构建的网页版操作界面，旨在让用户能够轻松地在本地运行和使用强大的 Stable Diffusion 图像生成模型。它解决了原始模型依赖命令行、操作门槛高且功能分散的痛点，将复杂的 AI 绘图流程整合进一个直观易用的图形化平台。\n\n无论是希望快速上手的普通创作者、需要精细控制画面细节的设计师，还是想要深入探索模型潜力的开发者与研究人员，都能从中获益。其核心亮点在于极高的功能丰富度：不仅支持文生图、图生图、局部重绘（Inpainting）和外绘（Outpainting）等基础模式，还独创了注意力机制调整、提示词矩阵、负向提示词以及“高清修复”等高级功能。此外，它内置了 GFPGAN 和 CodeFormer 等人脸修复工具，支持多种神经网络放大算法，并允许用户通过插件系统无限扩展能力。即使是显存有限的设备，stable-diffusion-webui 也提供了相应的优化选项，让高质量的 AI 艺术创作变得触手可及。",162132,3,"2026-04-05T11:01:52",[13,14,15],"开发框架","图像","Agent","ready",{"id":18,"name":19,"github_repo":20,"description_zh":21,"stars":22,"difficulty_score":23,"last_commit_at":24,"category_tags":25,"status":16},1381,"everything-claude-code","affaan-m\u002Feverything-claude-code","everything-claude-code 是一套专为 AI 编程助手（如 Claude Code、Codex、Cursor 等）打造的高性能优化系统。它不仅仅是一组配置文件，而是一个经过长期实战打磨的完整框架，旨在解决 AI 代理在实际开发中面临的效率低下、记忆丢失、安全隐患及缺乏持续学习能力等核心痛点。\n\n通过引入技能模块化、直觉增强、记忆持久化机制以及内置的安全扫描功能，everything-claude-code 能显著提升 AI 在复杂任务中的表现，帮助开发者构建更稳定、更智能的生产级 AI 代理。其独特的“研究优先”开发理念和针对 Token 消耗的优化策略，使得模型响应更快、成本更低，同时有效防御潜在的攻击向量。\n\n这套工具特别适合软件开发者、AI 研究人员以及希望深度定制 AI 工作流的技术团队使用。无论您是在构建大型代码库，还是需要 AI 协助进行安全审计与自动化测试，everything-claude-code 都能提供强大的底层支持。作为一个曾荣获 Anthropic 黑客大奖的开源项目，它融合了多语言支持与丰富的实战钩子（hooks），让 AI 真正成长为懂上",138956,2,"2026-04-05T11:33:21",[13,15,26],"语言模型",{"id":28,"name":29,"github_repo":30,"description_zh":31,"stars":32,"difficulty_score":23,"last_commit_at":33,"category_tags":34,"status":16},2271,"ComfyUI","Comfy-Org\u002FComfyUI","ComfyUI 是一款功能强大且高度模块化的视觉 AI 引擎，专为设计和执行复杂的 Stable Diffusion 图像生成流程而打造。它摒弃了传统的代码编写模式，采用直观的节点式流程图界面，让用户通过连接不同的功能模块即可构建个性化的生成管线。\n\n这一设计巧妙解决了高级 AI 绘图工作流配置复杂、灵活性不足的痛点。用户无需具备编程背景，也能自由组合模型、调整参数并实时预览效果，轻松实现从基础文生图到多步骤高清修复等各类复杂任务。ComfyUI 拥有极佳的兼容性，不仅支持 Windows、macOS 和 Linux 全平台，还广泛适配 NVIDIA、AMD、Intel 及苹果 Silicon 等多种硬件架构，并率先支持 SDXL、Flux、SD3 等前沿模型。\n\n无论是希望深入探索算法潜力的研究人员和开发者，还是追求极致创作自由度的设计师与资深 AI 绘画爱好者，ComfyUI 都能提供强大的支持。其独特的模块化架构允许社区不断扩展新功能，使其成为当前最灵活、生态最丰富的开源扩散模型工具之一，帮助用户将创意高效转化为现实。",107662,"2026-04-03T11:11:01",[13,14,15],{"id":36,"name":37,"github_repo":38,"description_zh":39,"stars":40,"difficulty_score":23,"last_commit_at":41,"category_tags":42,"status":16},3704,"NextChat","ChatGPTNextWeb\u002FNextChat","NextChat 是一款轻量且极速的 AI 助手，旨在为用户提供流畅、跨平台的大模型交互体验。它完美解决了用户在多设备间切换时难以保持对话连续性，以及面对众多 AI 模型不知如何统一管理的痛点。无论是日常办公、学习辅助还是创意激发，NextChat 都能让用户随时随地通过网页、iOS、Android、Windows、MacOS 或 Linux 端无缝接入智能服务。\n\n这款工具非常适合普通用户、学生、职场人士以及需要私有化部署的企业团队使用。对于开发者而言，它也提供了便捷的自托管方案，支持一键部署到 Vercel 或 Zeabur 等平台。\n\nNextChat 的核心亮点在于其广泛的模型兼容性，原生支持 Claude、DeepSeek、GPT-4 及 Gemini Pro 等主流大模型，让用户在一个界面即可自由切换不同 AI 能力。此外，它还率先支持 MCP（Model Context Protocol）协议，增强了上下文处理能力。针对企业用户，NextChat 提供专业版解决方案，具备品牌定制、细粒度权限控制、内部知识库整合及安全审计等功能，满足公司对数据隐私和个性化管理的高标准要求。",87618,"2026-04-05T07:20:52",[13,26],{"id":44,"name":45,"github_repo":46,"description_zh":47,"stars":48,"difficulty_score":23,"last_commit_at":49,"category_tags":50,"status":16},2268,"ML-For-Beginners","microsoft\u002FML-For-Beginners","ML-For-Beginners 是由微软推出的一套系统化机器学习入门课程，旨在帮助零基础用户轻松掌握经典机器学习知识。这套课程将学习路径规划为 12 周，包含 26 节精炼课程和 52 道配套测验，内容涵盖从基础概念到实际应用的完整流程，有效解决了初学者面对庞大知识体系时无从下手、缺乏结构化指导的痛点。\n\n无论是希望转型的开发者、需要补充算法背景的研究人员，还是对人工智能充满好奇的普通爱好者，都能从中受益。课程不仅提供了清晰的理论讲解，还强调动手实践，让用户在循序渐进中建立扎实的技能基础。其独特的亮点在于强大的多语言支持，通过自动化机制提供了包括简体中文在内的 50 多种语言版本，极大地降低了全球不同背景用户的学习门槛。此外，项目采用开源协作模式，社区活跃且内容持续更新，确保学习者能获取前沿且准确的技术资讯。如果你正寻找一条清晰、友好且专业的机器学习入门之路，ML-For-Beginners 将是理想的起点。",84991,"2026-04-05T10:45:23",[14,51,52,53,15,54,26,13,55],"数据工具","视频","插件","其他","音频",{"id":57,"name":58,"github_repo":59,"description_zh":60,"stars":61,"difficulty_score":10,"last_commit_at":62,"category_tags":63,"status":16},3128,"ragflow","infiniflow\u002Fragflow","RAGFlow 是一款领先的开源检索增强生成（RAG）引擎，旨在为大语言模型构建更精准、可靠的上下文层。它巧妙地将前沿的 RAG 技术与智能体（Agent）能力相结合，不仅支持从各类文档中高效提取知识，还能让模型基于这些知识进行逻辑推理和任务执行。\n\n在大模型应用中，幻觉问题和知识滞后是常见痛点。RAGFlow 通过深度解析复杂文档结构（如表格、图表及混合排版），显著提升了信息检索的准确度，从而有效减少模型“胡编乱造”的现象，确保回答既有据可依又具备时效性。其内置的智能体机制更进一步，使系统不仅能回答问题，还能自主规划步骤解决复杂问题。\n\n这款工具特别适合开发者、企业技术团队以及 AI 研究人员使用。无论是希望快速搭建私有知识库问答系统，还是致力于探索大模型在垂直领域落地的创新者，都能从中受益。RAGFlow 提供了可视化的工作流编排界面和灵活的 API 接口，既降低了非算法背景用户的上手门槛，也满足了专业开发者对系统深度定制的需求。作为基于 Apache 2.0 协议开源的项目，它正成为连接通用大模型与行业专有知识之间的重要桥梁。",77062,"2026-04-04T04:44:48",[15,14,13,26,54],{"id":65,"github_repo":66,"name":67,"description_en":68,"description_zh":69,"ai_summary_zh":70,"readme_en":71,"readme_zh":72,"quickstart_zh":73,"use_case_zh":74,"hero_image_url":75,"owner_login":76,"owner_name":77,"owner_avatar_url":78,"owner_bio":79,"owner_company":80,"owner_location":80,"owner_email":81,"owner_twitter":76,"owner_website":82,"owner_url":83,"languages":84,"stars":100,"forks":101,"last_commit_at":102,"license":103,"difficulty_score":23,"env_os":104,"env_gpu":105,"env_ram":105,"env_deps":106,"category_tags":118,"github_topics":119,"view_count":23,"oss_zip_url":80,"oss_zip_packed_at":80,"status":16,"created_at":132,"updated_at":133,"faqs":134,"releases":135},2438,"antiwork\u002Fshortest","shortest","QA via natural language AI tests","Shortest 是一款基于人工智能的端到端（E2E）测试框架，旨在革新传统的软件质量保证流程。它允许开发者直接使用自然语言来编写测试用例，无需掌握复杂的自动化测试脚本语法。例如，只需输入“使用邮箱和密码登录应用”，Shortest 即可自动理解意图并执行相应的浏览器操作。\n\n这一工具主要解决了传统 E2E 测试编写成本高、维护难度大以及代码脆弱易断的问题。在传统模式下，前端界面的微小变动往往导致大量测试脚本失效，需要频繁人工修复。Shortest 通过引入 AI 智能体，能够像真实用户一样感知页面元素并动态调整操作路径，从而显著提升了测试的稳定性和开发效率。此外，它还支持在测试执行后结合回调函数进行数据库校验等复杂断言，兼顾了灵活性与严谨性。\n\nShortest 特别适合前端开发者、全栈工程师以及追求高效交付的研发团队使用。对于希望快速构建可靠测试套件但又不愿深陷底层细节的技术人员而言，它是一个极佳的辅助伙伴。\n\n在技术实现上，Shortest 建立在成熟的 Playwright 之上，确保了浏览器自动化的可靠性；核心智能则由 Anthropic Claude API 驱动，赋予其强","Shortest 是一款基于人工智能的端到端（E2E）测试框架，旨在革新传统的软件质量保证流程。它允许开发者直接使用自然语言来编写测试用例，无需掌握复杂的自动化测试脚本语法。例如，只需输入“使用邮箱和密码登录应用”，Shortest 即可自动理解意图并执行相应的浏览器操作。\n\n这一工具主要解决了传统 E2E 测试编写成本高、维护难度大以及代码脆弱易断的问题。在传统模式下，前端界面的微小变动往往导致大量测试脚本失效，需要频繁人工修复。Shortest 通过引入 AI 智能体，能够像真实用户一样感知页面元素并动态调整操作路径，从而显著提升了测试的稳定性和开发效率。此外，它还支持在测试执行后结合回调函数进行数据库校验等复杂断言，兼顾了灵活性与严谨性。\n\nShortest 特别适合前端开发者、全栈工程师以及追求高效交付的研发团队使用。对于希望快速构建可靠测试套件但又不愿深陷底层细节的技术人员而言，它是一个极佳的辅助伙伴。\n\n在技术实现上，Shortest 建立在成熟的 Playwright 之上，确保了浏览器自动化的可靠性；核心智能则由 Anthropic Claude API 驱动，赋予其强大的语义理解和决策能力。同时，它还原生集成了 GitHub 双因素认证（2FA）处理和 Mailosaur 邮件验证功能，轻松应对现代 Web 应用中常见的复杂交互场景。通过简单的初始化命令，即可快速集成到现有项目中，让 AI 协助你更轻松地守护代码质量。","\u003Cp align=\"center\">\n  \u003Cimg src=\"https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fantiwork_shortest_readme_3beb26c60c6d.png\" alt=\"Shortest logo\" width=\"128\" \u002F>\n\u003C\u002Fp>\n\n# Shortest\n\nAI-powered natural language end-to-end testing framework.\n\n\u003Cvideo src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002Fd443279e-7364-452b-9f50-0c8dd0cf55fc\" controls autoplay loop muted>\nYour browser does not support the video tag.\n\u003C\u002Fvideo>\n\n## Features\n\n- Natural language E2E testing framework\n- AI-powered test execution using Anthropic Claude API\n- Built on Playwright\n- GitHub integration with 2FA support\n- Email validation with Mailosaur\n\n## Using Shortest in your project\n\nIf helpful, [here's a short video](https:\u002F\u002Fgithub.com\u002Fantiwork\u002Fshortest\u002Fissues\u002F143#issuecomment-2564488173)!\n\n### Installation\n\nUse the `shortest init` command to streamline the setup process in a new or existing project.\n\nThe `shortest init` command will:\n\n```sh\nnpx @antiwork\u002Fshortest init\n```\n\nThis will:\n\n- Automatically install the `@antiwork\u002Fshortest` package as a dev dependency if it is not already installed\n- Create a default `shortest.config.ts` file with boilerplate configuration\n- Generate a `.env.local` file (unless present) with placeholders for required environment variables, such as `ANTHROPIC_API_KEY`\n- Add `.env.local` and `.shortest\u002F` to `.gitignore`\n\n### Quick start\n\n1. Determine your test entry and add your Anthropic API key in config file: `shortest.config.ts`\n\n```typescript\nimport type { ShortestConfig } from \"@antiwork\u002Fshortest\";\n\nexport default {\n  headless: false,\n  baseUrl: \"http:\u002F\u002Flocalhost:3000\",\n  browser: {\n    contextOptions: {\n      ignoreHTTPSErrors: true\n    },\n  },\n  testPattern: \"**\u002F*.test.ts\",\n  ai: {\n    provider: \"anthropic\",\n  },\n} satisfies ShortestConfig;\n```\nThe Anthropic API key defaults to `SHORTEST_ANTHROPIC_API_KEY` \u002F `ANTHROPIC_API_KEY` environment variables. Can be overwritten via `ai.config.apiKey`.\n\nOptionally, you can configure browser behavior using the `browser.contextOptions` property in your configuration file. This allows you to pass custom [Playwright browser context options](https:\u002F\u002Fplaywright.dev\u002Fdocs\u002Fapi\u002Fclass-browser#browser-new-context).\n\n2. Create test files using the pattern specified in the config: `app\u002Flogin.test.ts`\n\n```typescript\nimport { shortest } from \"@antiwork\u002Fshortest\";\n\nshortest(\"Login to the app using email and password\", {\n  username: process.env.GITHUB_USERNAME,\n  password: process.env.GITHUB_PASSWORD,\n});\n```\n\n### Using callback functions\n\nYou can also use callback functions to add additional assertions and other logic. AI will execute the callback function after the test\nexecution in browser is completed.\n\n```typescript\nimport { shortest } from \"@antiwork\u002Fshortest\";\nimport { db } from \"@\u002Flib\u002Fdb\u002Fdrizzle\";\nimport { users } from \"@\u002Flib\u002Fdb\u002Fschema\";\nimport { eq } from \"drizzle-orm\";\n\nshortest(\"Login to the app using username and password\", {\n  username: process.env.USERNAME,\n  password: process.env.PASSWORD,\n}).after(async ({ page }) => {\n  \u002F\u002F Get current user's clerk ID from the page\n  const clerkId = await page.evaluate(() => {\n    return window.localStorage.getItem(\"clerk-user\");\n  });\n\n  if (!clerkId) {\n    throw new Error(\"User not found in database\");\n  }\n\n  \u002F\u002F Query the database\n  const [user] = await db\n    .select()\n    .from(users)\n    .where(eq(users.clerkId, clerkId))\n    .limit(1);\n\n  expect(user).toBeDefined();\n});\n```\n\n### Lifecycle hooks\n\nYou can use lifecycle hooks to run code before and after the test.\n\n```typescript\nimport { shortest } from \"@antiwork\u002Fshortest\";\n\nshortest.beforeAll(async ({ page }) => {\n  await clerkSetup({\n    frontendApiUrl:\n      process.env.PLAYWRIGHT_TEST_BASE_URL ?? \"http:\u002F\u002Flocalhost:3000\",\n  });\n});\n\nshortest.beforeEach(async ({ page }) => {\n  await clerk.signIn({\n    page,\n    signInParams: {\n      strategy: \"email_code\",\n      identifier: \"iffy+clerk_test@example.com\",\n    },\n  });\n});\n\nshortest.afterEach(async ({ page }) => {\n  await page.close();\n});\n\nshortest.afterAll(async ({ page }) => {\n  await clerk.signOut({ page });\n});\n```\n\n### Chaining tests\n\nShortest supports flexible test chaining patterns:\n\n```typescript\n\u002F\u002F Sequential test chain\nshortest([\n  \"user can login with email and password\",\n  \"user can modify their account-level refund policy\",\n]);\n\n\u002F\u002F Reusable test flows\nconst loginAsLawyer = \"login as lawyer with valid credentials\";\nconst loginAsContractor = \"login as contractor with valid credentials\";\nconst allAppActions = [\"send invoice to company\", \"view invoices\"];\n\n\u002F\u002F Combine flows with spread operator\nshortest([loginAsLawyer, ...allAppActions]);\nshortest([loginAsContractor, ...allAppActions]);\n```\n\n### API testing\n\nTest API endpoints using natural language\n\n```typescript\nconst req = new APIRequest({\n  baseURL: API_BASE_URI,\n});\n\nshortest(\n  \"Ensure the response contains only active users\",\n  req.fetch({\n    url: \"\u002Fusers\",\n    method: \"GET\",\n    params: new URLSearchParams({\n      active: true,\n    }),\n  }),\n);\n```\n\nOr simply:\n\n```typescript\nshortest(`\n  Test the API GET endpoint ${API_BASE_URI}\u002Fusers with query parameter { \"active\": true }\n  Expect the response to contain only active users\n`);\n```\n\n### Running tests\n\n```bash\npnpm shortest                   # Run all tests\npnpm shortest login.test.ts     # Run specific tests from a file\npnpm shortest login.test.ts:23  # Run specific test from a file using a line number\npnpm shortest --headless        # Run in headless mode using\n```\n\nYou can find example tests in the [`examples`](.\u002Fexamples) directory.\n\n### CI setup\n\nYou can run Shortest in your CI\u002FCD pipeline by running tests in headless mode. Make sure to add your Anthropic API key to your CI\u002FCD pipeline secrets.\n\n[See example here](https:\u002F\u002Fgithub.com\u002Fantiwork\u002Fshortest\u002Fblob\u002Fmain\u002F.github\u002Fworkflows\u002Fshortest.yml)\n\n### GitHub 2FA login setup\n\nShortest supports login using GitHub 2FA. For GitHub authentication tests:\n\n1. Go to your repository settings\n2. Navigate to \"Password and Authentication\"\n3. Click on \"Authenticator App\"\n4. Select \"Use your authenticator app\"\n5. Click \"Setup key\" to obtain the OTP secret\n6. Add the OTP secret to your `.env.local` file or use the Shortest CLI to add it\n7. Enter the 2FA code displayed in your terminal into Github's Authenticator setup page to complete the process\n\n```bash\nshortest --github-code --secret=\u003COTP_SECRET>\n```\n\n### Environment setup\n\nRequired in `.env.local`:\n\n```bash\nANTHROPIC_API_KEY=your_api_key\nGITHUB_TOTP_SECRET=your_secret  # Only for GitHub auth tests\n```\n\n## Shortest CLI development\n\nThe [NPM package](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@antiwork\u002Fshortest) is located in [`packages\u002Fshortest\u002F`](.\u002Fpackages\u002Fshortest). See [CONTRIBUTING](.\u002Fpackages\u002Fshortest\u002FCONTRIBUTING.md) guide.\n\n## Web app development\n\nThis guide will help you set up the Shortest web app for local development.\n\n### Prerequisites\n\n- React >=19.0.0 (if using with Next.js 14+ or Server Actions)\n- Next.js >=14.0.0 (if using Server Components\u002FActions)\n\n> [!WARNING]\n> Using this package with React 18 in Next.js 14+ projects may cause type conflicts with Server Actions and `useFormStatus`\n>\n> If you encounter type errors with form actions or React hooks, ensure you're using React 19\n\n### Getting started\n\n1. Clone the repository:\n\n```bash\ngit clone https:\u002F\u002Fgithub.com\u002Fantiwork\u002Fshortest.git\ncd shortest\n```\n\n2. Install dependencies:\n\n```bash\nnpm install -g pnpm\npnpm install\n```\n\n### Environment setup\n\n#### For Antiwork team members\n\nPull Vercel env vars:\n\n```bash\npnpm i -g vercel\nvercel link\nvercel env pull\n```\n\n#### For other contributors\n\n1. Run `pnpm run setup` to configure the environment variables.\n2. The setup wizard will ask you for information. Refer to \"Services Configuration\" section below for more details.\n\n### Set up the database\n\n```bash\npnpm drizzle-kit generate\npnpm db:migrate\npnpm db:seed # creates stripe products, currently unused\n```\n\n### Services configuration\n\nYou'll need to set up the following services for local development. If you're not an Antiwork Vercel team member, you'll need to either run the setup wizard `pnpm run setup` or manually configure each of these services and add the corresponding environment variables to your `.env.local` file:\n\n\u003Cdetails>\n\u003Csummary>Clerk\u003C\u002Fsummary>\n\n1. Go to [clerk.com](https:\u002F\u002Fclerk.com) and create a new app.\n2. Name it whatever you like and **disable all login methods except GitHub**.\n   ![Clerk App Login](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fantiwork_shortest_readme_8311085ead3f.png)\n3. Once created, copy the environment variables to your `.env.local` file.\n   ![Clerk Env Variables](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fantiwork_shortest_readme_03176f377810.png)\n4. In the Clerk dashboard, disable the \"Require the same device and browser\" setting to ensure tests with Mailosaur work properly.\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>Vercel Postgres\u003C\u002Fsummary>\n\n1. Go to your dashboard at [vercel.com](https:\u002F\u002Fvercel.com).\n2. Navigate to the Storage tab and click the `Create Database` button.\n   ![Vercel Create Database](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fantiwork_shortest_readme_c3d7abf6f4f1.png)\n3. Choose `Postgres` from the `Browse Storage` menu.\n   ![Neon Postgres](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fantiwork_shortest_readme_e942042a25df.png)\n4. Copy your environment variables from the `Quickstart` `.env.local` tab.\n   ![Vercel Postgres .env.local](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fantiwork_shortest_readme_c90206272442.png)\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>Anthropic\u003C\u002Fsummary>\n\n1. Go to your dashboard at [anthropic.com](https:\u002F\u002Fanthropic.com) and grab your API Key.\n   - Note: If you've never done this before, you will need to answer some questions and likely load your account with a balance. Not much is needed to test the app.\n     ![Anthropic API Key](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fantiwork_shortest_readme_fbd2639e968d.png)\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>Stripe\u003C\u002Fsummary>\n\n1. Go to your `Developers` dashboard at [stripe.com](https:\u002F\u002Fstripe.com).\n2. Turn on `Test mode`.\n3. Go to the `API Keys` tab and copy your `Secret key`.\n   ![Stripe Secret Key](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fantiwork_shortest_readme_2f11fd5638d7.png)\n4. Go to the terminal of your project and type `pnpm run stripe:webhooks`. It will prompt you to login with a code then give you your `STRIPE_WEBHOOK_SECRET`.\n   ![Stripe Webhook Secret](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fantiwork_shortest_readme_4ed34a2bdb33.png)\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>GitHub OAuth\u003C\u002Fsummary>\n\n1. Create a GitHub OAuth App:\n\n   - Go to your GitHub account settings.\n   - Navigate to `Developer settings` > `OAuth Apps` > `New OAuth App`.\n   - Fill in the application details:\n     - **Application name**: Choose any name for your app\n     - **Homepage URL**: Set to `http:\u002F\u002Flocalhost:3000` for local development\n     - **Authorization callback URL**: Use the Clerk-provided callback URL (found in below image)\n       ![Github OAuth App](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fantiwork_shortest_readme_956cc4c5a14d.png)\n\n2. Configure Clerk with GitHub OAuth:\n   - Go to your Clerk dashboard.\n   - Navigate to `Configure` > `SSO Connections` > `GitHub`.\n   - Select `Use custom credentials`\n   - Enter your `Client ID` and `Client Secret` from the GitHub OAuth app you just created.\n   - Add `repo` to the `Scopes`\n     ![Clerk Custom Credentials](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fantiwork_shortest_readme_55e55fda8bf4.png)\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>Mailosaur\u003C\u002Fsummary>\n\n1. [Sign up](https:\u002F\u002Fmailosaur.com\u002Fapp\u002Fsignup) for an account with Mailosaur.\n2. Create a new Inbox\u002FServer.\n3. Go to [API Keys](https:\u002F\u002Fmailosaur.com\u002Fapp\u002Fkeys) and create a standard key.\n4. Update the environment variables:\n   - `MAILOSAUR_API_KEY`: Your API key\n   - `MAILOSAUR_SERVER_ID`: Your server ID\n\nThe email used to test the login flow will have the format `shortest@\u003CMAILOSAUR_SERVER_ID>.mailosaur.net`, where\n`MAILOSAUR_SERVER_ID` is your server ID.\nMake sure to add the email as a new user under the Clerk app.\n\n\u003C\u002Fdetails>\n\n### Running locally\n\nRun the development server:\n\n```bash\npnpm dev\n```\n\nOpen [http:\u002F\u002Flocalhost:3000](http:\u002F\u002Flocalhost:3000) in your browser to see the app in action.\n","\u003Cp align=\"center\">\n  \u003Cimg src=\"https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fantiwork_shortest_readme_3beb26c60c6d.png\" alt=\"Shortest logo\" width=\"128\" \u002F>\n\u003C\u002Fp>\n\n# Shortest\n\n基于 AI 的自然语言端到端测试框架。\n\n\u003Cvideo src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002Fd443279e-7364-452b-9f50-0c8dd0cf55fc\" controls autoplay loop muted>\n您的浏览器不支持 video 标签。\n\u003C\u002Fvideo>\n\n## 特性\n\n- 自然语言端到端测试框架\n- 使用 Anthropic Claude API 进行 AI 驱动的测试执行\n- 基于 Playwright 构建\n- 支持双因素认证的 GitHub 集成\n- 使用 Mailosaur 进行邮件验证\n\n## 在您的项目中使用 Shortest\n\n如果对您有帮助，[这里有一段简短的视频](https:\u002F\u002Fgithub.com\u002Fantiwork\u002Fshortest\u002Fissues\u002F143#issuecomment-2564488173)！\n\n### 安装\n\n使用 `shortest init` 命令可以在新项目或现有项目中简化设置流程。\n\n`shortest init` 命令会：\n\n```sh\nnpx @antiwork\u002Fshortest init\n```\n\n这将：\n\n- 如果尚未安装，自动将 `@antiwork\u002Fshortest` 包作为开发依赖项安装\n- 创建一个包含样板配置的默认 `shortest.config.ts` 文件\n- 生成一个 `.env.local` 文件（如果不存在），其中包含所需环境变量的占位符，例如 `ANTHROPIC_API_KEY`\n- 将 `.env.local` 和 `.shortest\u002F` 添加到 `.gitignore`\n\n### 快速入门\n\n1. 确定您的测试入口，并在配置文件 `shortest.config.ts` 中添加您的 Anthropic API 密钥。\n\n```typescript\nimport type { ShortestConfig } from \"@antiwork\u002Fshortest\";\n\nexport default {\n  headless: false,\n  baseUrl: \"http:\u002F\u002Flocalhost:3000\",\n  browser: {\n    contextOptions: {\n      ignoreHTTPSErrors: true\n    },\n  },\n  testPattern: \"**\u002F*.test.ts\",\n  ai: {\n    provider: \"anthropic\",\n  },\n} satisfies ShortestConfig;\n```\n\nAnthropic API 密钥默认为 `SHORTEST_ANTHROPIC_API_KEY` 或 `ANTHROPIC_API_KEY` 环境变量。可以通过 `ai.config.apiKey` 覆盖。\n\n可选地，您还可以在配置文件中使用 `browser.contextOptions` 属性来配置浏览器行为。这允许您传递自定义的 [Playwright 浏览器上下文选项](https:\u002F\u002Fplaywright.dev\u002Fdocs\u002Fapi\u002Fclass-browser#browser-new-context)。\n\n2. 使用配置中指定的模式创建测试文件：`app\u002Flogin.test.ts`\n\n```typescript\nimport { shortest } from \"@antiwork\u002Fshortest\";\n\nshortest(\"使用邮箱和密码登录应用\", {\n  username: process.env.GITHUB_USERNAME,\n  password: process.env.GITHUB_PASSWORD,\n});\n```\n\n### 使用回调函数\n\n您也可以使用回调函数来添加额外的断言和其他逻辑。AI 会在浏览器中的测试执行完成后执行该回调函数。\n\n```typescript\nimport { shortest } from \"@antiwork\u002Fshortest\";\nimport { db } from \"@\u002Flib\u002Fdb\u002Fdrizzle\";\nimport { users } from \"@\u002Flib\u002Fdb\u002Fschema\";\nimport { eq } from \"drizzle-orm\";\n\nshortest(\"使用用户名和密码登录应用\", {\n  username: process.env.USERNAME,\n  password: process.env.PASSWORD,\n}).after(async ({ page }) => {\n  \u002F\u002F 从页面获取当前用户的 Clerk ID\n  const clerkId = await page.evaluate(() => {\n    return window.localStorage.getItem(\"clerk-user\");\n  });\n\n  if (!clerkId) {\n    throw new Error(\"数据库中未找到用户\");\n  }\n\n  \u002F\u002F 查询数据库\n  const [user] = await db\n    .select()\n    .from(users)\n    .where(eq(users.clerkId, clerkId))\n    .limit(1);\n\n  expect(user).toBeDefined();\n});\n```\n\n### 生命周期钩子\n\n您可以使用生命周期钩子在测试前后运行代码。\n\n```typescript\nimport { shortest } from \"@antiwork\u002Fshortest\";\n\nshortest.beforeAll(async ({ page }) => {\n  await clerkSetup({\n    frontendApiUrl:\n      process.env.PLAYWRIGHT_TEST_BASE_URL ?? \"http:\u002F\u002Flocalhost:3000\",\n  });\n});\n\nshortest.beforeEach(async ({ page }) => {\n  await clerk.signIn({\n    page,\n    signInParams: {\n      strategy: \"email_code\",\n      identifier: \"iffy+clerk_test@example.com\",\n    },\n  });\n});\n\nshortest.afterEach(async ({ page }) => {\n  await page.close();\n});\n\nshortest.afterAll(async ({ page }) => {\n  await clerk.signOut({ page });\n});\n```\n\n### 测试链式调用\n\nShortest 支持灵活的测试链式调用模式：\n\n```typescript\n\u002F\u002F 顺序测试链\nshortest([\n  \"用户可以使用邮箱和密码登录\",\n  \"用户可以修改其账户级别的退款政策\",\n]);\n\n\u002F\u002F 可复用的测试流程\nconst loginAsLawyer = \"使用有效凭证登录律师账号\";\nconst loginAsContractor = \"使用有效凭证登录承包商账号\";\nconst allAppActions = [\"向公司发送发票\", \"查看发票\"];\n\n\u002F\u002F 使用展开运算符组合流程\nshortest([loginAsLawyer, ...allAppActions]);\nshortest([loginAsContractor, ...allAppActions]);\n```\n\n### API 测试\n\n使用自然语言测试 API 端点\n\n```typescript\nconst req = new APIRequest({\n  baseURL: API_BASE_URI,\n});\n\nshortest(\n  \"确保响应仅包含活跃用户\",\n  req.fetch({\n    url: \"\u002Fusers\",\n    method: \"GET\",\n    params: new URLSearchParams({\n      active: true,\n    }),\n  }),\n);\n```\n\n或者更简单地：\n\n```typescript\nshortest(`\n  测试 API GET 端点 ${API_BASE_URI}\u002Fusers，查询参数为 { \"active\": true }\n  预期响应应仅包含活跃用户\n`);\n```\n\n### 运行测试\n\n```bash\npnpm shortest                   # 运行所有测试\npnpm shortest login.test.ts     # 运行文件中的特定测试\npnpm shortest login.test.ts:23  # 使用行号运行文件中的特定测试\npnpm shortest --headless        # 以无头模式运行\n```\n\n您可以在 [`examples`](.\u002Fexamples) 目录中找到示例测试。\n\n### CI 设置\n\n您可以通过在无头模式下运行测试，在 CI\u002FCD 流水线中运行 Shortest。请确保将您的 Anthropic API 密钥添加到 CI\u002FCD 流水线的密钥中。\n\n[在此处查看示例](https:\u002F\u002Fgithub.com\u002Fantiwork\u002Fshortest\u002Fblob\u002Fmain\u002F.github\u002Fworkflows\u002Fshortest.yml)\n\n### GitHub 2FA 登录设置\n\nShortest 支持使用 GitHub 2FA 登录。对于 GitHub 身份验证测试：\n\n1. 前往您的仓库设置\n2. 导航到“密码和身份验证”\n3. 单击“身份验证器应用”\n4. 选择“使用身份验证器应用”\n5. 单击“设置密钥”以获取 OTP 密钥\n6. 将 OTP 密钥添加到您的 `.env.local` 文件中，或使用 Shortest CLI 添加\n7. 将终端中显示的 2FA 代码输入到 GitHub 的身份验证器设置页面中，以完成设置过程\n\n```bash\nshortest --github-code --secret=\u003COTP_SECRET>\n```\n\n### 环境设置\n\n`.env.local` 中需要以下内容：\n\n```bash\nANTHROPIC_API_KEY=your_api_key\nGITHUB_TOTP_SECRET=your_secret  # 仅用于 GitHub 身份验证测试\n```\n\n## Shortest CLI 开发\n\n[NPM 包](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@antiwork\u002Fshortest)位于 [`packages\u002Fshortest\u002F`](.\u002Fpackages\u002Fshortest)。请参阅 [CONTRIBUTING](.\u002Fpackages\u002Fshortest\u002FCONTRIBUTING.md) 指南。\n\n## Web 应用开发\n\n本指南将帮助您为本地开发设置 Shortest Web 应用程序。\n\n### 前置条件\n\n- React >=19.0.0（若与 Next.js 14+ 或 Server Actions 搭配使用）\n- Next.js >=14.0.0（若使用 Server Components\u002FActions）\n\n> [!警告]\n> 在 Next.js 14+ 项目中将此包与 React 18 一起使用，可能会导致与 Server Actions 和 `useFormStatus` 的类型冲突。\n>\n> 如果遇到表单操作或 React 钩子相关的类型错误，请确保使用 React 19。\n\n### 开始使用\n\n1. 克隆仓库：\n\n```bash\ngit clone https:\u002F\u002Fgithub.com\u002Fantiwork\u002Fshortest.git\ncd shortest\n```\n\n2. 安装依赖：\n\n```bash\nnpm install -g pnpm\npnpm install\n```\n\n### 环境设置\n\n#### 对于 Antiwork 团队成员\n\n拉取 Vercel 环境变量：\n\n```bash\npnpm i -g vercel\nvercel link\nvercel env pull\n```\n\n#### 对于其他贡献者\n\n1. 运行 `pnpm run setup` 来配置环境变量。\n2. 设置向导会提示您输入相关信息。更多详情请参阅下方的“服务配置”部分。\n\n### 设置数据库\n\n```bash\npnpm drizzle-kit generate\npnpm db:migrate\npnpm db:seed # 创建 Stripe 产品，目前未使用\n```\n\n### 服务配置\n\n您需要为本地开发设置以下服务。如果您不是 Antiwork Vercel 团队成员，则需要运行设置向导 `pnpm run setup`，或者手动配置这些服务，并将相应的环境变量添加到您的 `.env.local` 文件中：\n\n\u003Cdetails>\n\u003Csummary>Clerk\u003C\u002Fsummary>\n\n1. 访问 [clerk.com](https:\u002F\u002Fclerk.com)，创建一个新的应用。\n2. 为应用命名，然后**仅保留 GitHub 登录方式**，禁用其他所有登录方法。\n   ![Clerk 应用登录](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fantiwork_shortest_readme_8311085ead3f.png)\n3. 创建完成后，将环境变量复制到您的 `.env.local` 文件中。\n   ![Clerk 环境变量](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fantiwork_shortest_readme_03176f377810.png)\n4. 在 Clerk 控制台中，关闭“要求使用同一设备和浏览器”的设置，以确保与 Mailosaur 的测试能够正常工作。\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>Vercel Postgres\u003C\u002Fsummary>\n\n1. 登录 [vercel.com](https:\u002F\u002Fvercel.com) 的仪表板。\n2. 转到“存储”选项卡，点击“创建数据库”按钮。\n   ![Vercel 创建数据库](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fantiwork_shortest_readme_c3d7abf6f4f1.png)\n3. 在“浏览存储”菜单中选择 `Postgres`。\n   ![Neon Postgres](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fantiwork_shortest_readme_e942042a25df.png)\n4. 从“快速入门”的 `.env.local` 选项卡中复制您的环境变量。\n   ![Vercel Postgres .env.local](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fantiwork_shortest_readme_c90206272442.png)\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>Anthropic\u003C\u002Fsummary>\n\n1. 登录 [anthropic.com](https:\u002F\u002Fanthropic.com) 的仪表板，获取您的 API 密钥。\n   - 注意：如果您之前从未进行过此操作，可能需要回答一些问题，并为账户充值。测试应用程序并不需要太多资金。\n     ![Anthropic API 密钥](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fantiwork_shortest_readme_fbd2639e968d.png)\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>Stripe\u003C\u002Fsummary>\n\n1. 登录 [stripe.com](https:\u002F\u002Fstripe.com) 的“开发者”仪表板。\n2. 打开“测试模式”。\n3. 转到“API 密钥”选项卡，复制您的“密钥”。\n   ![Stripe 密钥](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fantiwork_shortest_readme_2f11fd5638d7.png)\n4. 打开项目的终端，输入 `pnpm run stripe:webhooks`。系统会提示您使用验证码登录，随后生成您的 `STRIPE_WEBHOOK_SECRET`。\n   ![Stripe Webhook Secret](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fantiwork_shortest_readme_4ed34a2bdb33.png)\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>GitHub OAuth\u003C\u002Fsummary>\n\n1. 创建 GitHub OAuth 应用程序：\n\n   - 前往您的 GitHub 账户设置。\n   - 导航至“开发者设置” > “OAuth 应用程序” > “新建 OAuth 应用程序”。\n   - 填写应用详细信息：\n     - **应用名称**：任意选择一个名称\n     - **主页 URL**：设置为 `http:\u002F\u002Flocalhost:3000`，用于本地开发\n     - **授权回调 URL**：使用 Clerk 提供的回调 URL（见下图）\n       ![Github OAuth 应用](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fantiwork_shortest_readme_956cc4c5a14d.png)\n\n2. 在 Clerk 中配置 GitHub OAuth：\n   - 前往您的 Clerk 控制台。\n   - 导航至“配置” > “SSO 连接” > “GitHub”。\n   - 选择“使用自定义凭据”。\n   - 输入您刚刚创建的 GitHub OAuth 应用程序中的“客户端 ID”和“客户端密钥”。\n   - 添加 `repo` 到“作用域”中。\n     ![Clerk 自定义凭据](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fantiwork_shortest_readme_55e55fda8bf4.png)\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>Mailosaur\u003C\u002Fsummary>\n\n1. 在 [mailosaur.com](https:\u002F\u002Fmailosaur.com\u002Fapp\u002Fsignup) 注册一个 Mailosaur 账户。\n2. 创建一个新的收件箱\u002F服务器。\n3. 转到“API 密钥”页面，创建一个标准密钥。\n4. 更新环境变量：\n   - `MAILOSAUR_API_KEY`：您的 API 密钥\n   - `MAILOSAUR_SERVER_ID`：您的服务器 ID\n\n用于测试登录流程的电子邮件格式为 `shortest@\u003CMAILOSAUR_SERVER_ID>.mailosaur.net`，其中 `\u003CMAILOSAUR_SERVER_ID>` 是您的服务器 ID。请务必将该邮箱作为新用户添加到 Clerk 应用中。\n\n\u003C\u002Fdetails>\n\n### 本地运行\n\n启动开发服务器：\n\n```bash\npnpm dev\n```\n\n在浏览器中打开 [http:\u002F\u002Flocalhost:3000](http:\u002F\u002Flocalhost:3000)，即可查看应用运行效果。","# Shortest 快速上手指南\n\nShortest 是一个基于 AI 的自然语言端到端（E2E）测试框架。它利用 Anthropic Claude API 理解自然语言指令，并基于 Playwright 执行浏览器自动化测试，支持 GitHub 2FA 登录和 Mailosaur 邮件验证。\n\n## 环境准备\n\n*   **Node.js**：建议最新 LTS 版本。\n*   **包管理器**：推荐使用 `pnpm` 或 `npm`。\n*   **API Key**：你需要一个 Anthropic API Key (`ANTHROPIC_API_KEY`)。\n*   **前置知识**：了解基本的 TypeScript 和 Playwright 概念会有所帮助。\n\n> **注意**：如果你计划在 Next.js 14+ 项目中使用 Server Actions，请确保使用 React >=19.0.0 以避免类型冲突。\n\n## 安装步骤\n\n在现有或新建的项目根目录下，运行以下初始化命令。该命令会自动安装依赖、生成配置文件和环境变量模板。\n\n```sh\nnpx @antiwork\u002Fshortest init\n```\n\n执行后，项目将发生以下变化：\n1. 安装 `@antiwork\u002Fshortest` 为开发依赖。\n2. 创建默认配置文件 `shortest.config.ts`。\n3. 生成 `.env.local` 文件（若不存在），其中包含 `ANTHROPIC_API_KEY` 等变量的占位符。\n4. 自动将 `.env.local` 和 `.shortest\u002F` 添加到 `.gitignore`。\n\n**配置环境变量：**\n编辑 `.env.local` 文件，填入你的 Anthropic API Key：\n\n```bash\nANTHROPIC_API_KEY=your_api_key\n```\n\n## 基本使用\n\n### 1. 配置测试入口\n\n编辑 `shortest.config.ts`，设置基础 URL 和测试文件匹配模式：\n\n```typescript\nimport type { ShortestConfig } from \"@antiwork\u002Fshortest\";\n\nexport default {\n  headless: false, \u002F\u002F 设置为 true 可在无头模式下运行\n  baseUrl: \"http:\u002F\u002Flocalhost:3000\",\n  browser: {\n    contextOptions: {\n      ignoreHTTPSErrors: true\n    },\n  },\n  testPattern: \"**\u002F*.test.ts\",\n  ai: {\n    provider: \"anthropic\",\n  },\n} satisfies ShortestConfig;\n```\n\n### 2. 编写测试用例\n\nShortest 允许你使用自然语言描述测试步骤。创建测试文件（如 `app\u002Flogin.test.ts`）：\n\n```typescript\nimport { shortest } from \"@antiwork\u002Fshortest\";\n\nshortest(\"Login to the app using email and password\", {\n  username: process.env.GITHUB_USERNAME,\n  password: process.env.GITHUB_PASSWORD,\n});\n```\n\nAI 会自动解析该描述，并在浏览器中执行相应的登录操作。\n\n### 3. 运行测试\n\n使用以下命令运行测试：\n\n```bash\n# 运行所有测试\npnpm shortest\n\n# 运行指定文件的测试\npnpm shortest login.test.ts\n\n# 无头模式运行（适用于 CI\u002FCD）\npnpm shortest --headless\n```\n\n### 高级用法：添加断言与回调\n\n如果需要更严格的验证，可以使用 `.after()` 回调函数。AI 执行完浏览器操作后，会运行此回调：\n\n```typescript\nimport { shortest } from \"@antiwork\u002Fshortest\";\nimport { db } from \"@\u002Flib\u002Fdb\u002Fdrizzle\";\nimport { users } from \"@\u002Flib\u002Fdb\u002Fschema\";\nimport { eq } from \"drizzle-orm\";\n\nshortest(\"Login to the app using username and password\", {\n  username: process.env.USERNAME,\n  password: process.env.PASSWORD,\n}).after(async ({ page }) => {\n  \u002F\u002F 获取页面中的用户 ID\n  const clerkId = await page.evaluate(() => {\n    return window.localStorage.getItem(\"clerk-user\");\n  });\n\n  if (!clerkId) {\n    throw new Error(\"User not found in database\");\n  }\n\n  \u002F\u002F 数据库断言\n  const [user] = await db\n    .select()\n    .from(users)\n    .where(eq(users.clerkId, clerkId))\n    .limit(1);\n\n  expect(user).toBeDefined();\n});\n```","某电商初创团队的后端工程师正在重构用户结账流程，需要确保从“购物车结算”到“支付成功页”的完整链路在 UI 调整后依然稳定运行。\n\n### 没有 shortest 时\n- **脚本维护成本极高**：传统 Playwright 测试依赖精确的 CSS 选择器或 XPath。前端每次微调按钮类名或 DOM 结构，测试脚本就会报错，工程师需花费大量时间修复“脆弱”的选择器，而非关注业务逻辑。\n- **编写门槛高且耗时**：为了覆盖“使用优惠券并支付”的场景，开发者需手动编写数十行代码来模拟点击、等待加载、输入文本及断言，开发一个复杂的 E2E 测试用例往往需要半天时间。\n- **动态内容验证困难**：面对邮件发送验证码或第三方登录（如 GitHub OAuth）等涉及外部服务的场景，传统方案需要额外搭建 Mock 服务或复杂的环境配置，调试过程极其痛苦。\n- **测试覆盖率低**：由于编写和维护成本高昂，团队往往只敢对核心路径做少量测试，大量边缘场景（如异常输入、网络波动）被忽略，导致线上故障频发。\n\n### 使用 shortest 后\n- **自然语言驱动，零维护焦虑**：工程师只需用英语写下“将商品加入购物车，应用折扣码并完成支付”，shortest 基于 AI 自动识别页面元素并执行操作。即使前端 DOM 结构变化，AI 也能智能定位元素，彻底告别选择器失效问题。\n- **极速构建复杂场景**：借助 Anthropic Claude 的能力，原本需要半天编写的复杂交互逻辑，现在只需几行声明式代码即可生成。结合 `shortest init` 一键初始化，新成员也能在几分钟内上手编写高质量测试。\n- **原生支持复杂集成**：shortest 内置了 GitHub 2FA 和 Mailosaur 邮件验证支持。在处理“邮箱验证注册”或“双重认证登录”时，无需额外 Mock，直接通过配置即可打通全流程，大幅简化环境搭建。\n- **灵活的后置断言**：通过 `.after()` 回调，工程师可以在 AI 完成 UI 操作后，直接查询数据库验证订单状态。这种“UI 自动化 + 数据强一致性校验”的组合，确保了测试不仅“看起来通过了”，而且“数据真正正确”。\n\nshortest 将端到端测试从繁琐的代码实现中解放出来，让团队能以自然语言快速构建高鲁棒性的质量防线，显著降低维护成本并提升交付信心。","https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fantiwork_shortest_47ea60be.png","antiwork","Antiwork","https:\u002F\u002Foss.gittoolsai.com\u002Favatars\u002Fantiwork_521c4bff.png","",null,"hi@antiwork.com","https:\u002F\u002Fantiwork.com","https:\u002F\u002Fgithub.com\u002Fantiwork",[85,89,92,96],{"name":86,"color":87,"percentage":88},"TypeScript","#3178c6",97.3,{"name":90,"color":91,"percentage":23},"JavaScript","#f1e05a",{"name":93,"color":94,"percentage":95},"Ruby","#701516",0.4,{"name":97,"color":98,"percentage":99},"CSS","#663399",0.3,5554,328,"2026-04-02T17:00:31","MIT","Linux, macOS, Windows","未说明",{"notes":107,"python":105,"dependencies":108},"该工具基于 Node.js 环境运行，非 Python 项目。核心依赖包括 Playwright（浏览器自动化）和 Anthropic Claude API（AI 驱动）。开发环境需配置 Clerk（认证）、Vercel Postgres（数据库）、Stripe（支付）、GitHub OAuth 和 Mailosaur（邮件测试）等服务的环境变量。建议使用 pnpm 进行包管理。若使用 Next.js 14+，建议配合 React 19 以避免类型冲突。",[109,110,111,112,113,114,115,116,117],"@antiwork\u002Fshortest","playwright","react>=19.0.0","next.js>=14.0.0","pnpm","drizzle-orm","clerk","stripe","mailosaur",[15,13],[120,121,122,123,124,125,126,127,110,128,129,130,131],"anthropic","automation","chromium","e2e-testing","e2e-tests","end-to-end-testing","javascript","nextjs","test-automation","testing","testing-framework","testing-tool","2026-03-27T02:49:30.150509","2026-04-06T05:36:43.683473",[],[136,141,146,151,156,161,166,171,176,181,186,191],{"id":137,"version":138,"summary_zh":139,"released_at":140},61676,"v0.4.9","## 变更内容\n* 繁琐工作(cli)：由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fantiwork\u002Fshortest\u002Fpull\u002F405 中发布 v0.4.8 版本\n* 功能：新增 analyze 命令，由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fantiwork\u002Fshortest\u002Fpull\u002F402 中实现\n* 功能：新增 plan 命令，由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fantiwork\u002Fshortest\u002Fpull\u002F407 中实现\n* 功能：改进 init 体验，由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fantiwork\u002Fshortest\u002Fpull\u002F412 中完成\n* 功能：新增 generate 命令，由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fantiwork\u002Fshortest\u002Fpull\u002F410 中实现\n* 功能：在 init 命令中添加示例测试文件生成功能，由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fantiwork\u002Fshortest\u002Fpull\u002F411 中实现\n* 修复：更新保存 SHORTEST_LOGIN_PASSWORD 的任务标题，由 @devin-ai-integration 在 https:\u002F\u002Fgithub.com\u002Fantiwork\u002Fshortest\u002Fpull\u002F414 中完成\n* 更新 README 文本：将“Anthropic API 密钥默认为”改为“Anthropic API 密钥默认是”，由 @devin-ai-integration 在 https:\u002F\u002Fgithub.com\u002Fantiwork\u002Fshortest\u002Fpull\u002F415 中完成\n* 繁琐工作：将 json.test.ts 文件从 tests\u002Funit\u002Fai\u002Futils 目录移动到 src\u002Fai\u002Futils 目录，由 @devin-ai-integration 在 https:\u002F\u002Fgithub.com\u002Fantiwork\u002Fshortest\u002Fpull\u002F417 中完成\n* 繁琐工作：新增 get-git-info.test.ts 测试文件，由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fantiwork\u002Fshortest\u002Fpull\u002F416 中完成\n* 繁琐工作：为 createHash 工具函数添加单元测试，由 @devin-ai-integration 在 https:\u002F\u002Fgithub.com\u002Fantiwork\u002Fshortest\u002Fpull\u002F418 中完成\n\n\n**完整变更日志**：https:\u002F\u002Fgithub.com\u002Fantiwork\u002Fshortest\u002Fcompare\u002Fv0.4.8...v0.4.9","2025-04-01T00:51:11",{"id":142,"version":143,"summary_zh":144,"released_at":145},61677,"v0.4.8","## 变更内容\n* chore(cli)：由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fantiwork\u002Fshortest\u002Fpull\u002F397 中发布 v0.4.7 版本\n* feat：由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fantiwork\u002Fshortest\u002Fpull\u002F400 中优化 CLI 逻辑\n* feat：由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fantiwork\u002Fshortest\u002Fpull\u002F401 中添加 detect-framework 命令\n* fix：由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fantiwork\u002Fshortest\u002Fpull\u002F404 中使测试运行使用现有缓存\n\n\n**完整变更日志**：https:\u002F\u002Fgithub.com\u002Fantiwork\u002Fshortest\u002Fcompare\u002Fv0.4.7...v0.4.8","2025-03-25T03:12:13",{"id":147,"version":148,"summary_zh":149,"released_at":150},61678,"v0.4.7","## 变更内容\n* chore(cli)：由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fantiwork\u002Fshortest\u002Fpull\u002F386 中发布 v0.4.6 版本\n* 更新 GitHub 组织名称，将 anti-work 更改为 antiwork，由 @devin-ai-integration 在 https:\u002F\u002Fgithub.com\u002Fantiwork\u002Fshortest\u002Fpull\u002F391 中完成\n* chore(cli)：由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fantiwork\u002Fshortest\u002Fpull\u002F393 中将 TestResult 替换为 TestRun\n* fix(tools)：由 @devsargam 在 https:\u002F\u002Fgithub.com\u002Fantiwork\u002Fshortest\u002Fpull\u002F387 中更改截图的缓存方式\n* chore：由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fantiwork\u002Fshortest\u002Fpull\u002F394 中添加 typescript-eslint\u002Fmember-ordering 规则\n\n## 新贡献者\n* @devsargam 在 https:\u002F\u002Fgithub.com\u002Fantiwork\u002Fshortest\u002Fpull\u002F387 中完成了首次贡献\n\n**完整变更日志**：https:\u002F\u002Fgithub.com\u002Fantiwork\u002Fshortest\u002Fcompare\u002Fv0.4.6...v0.4.7","2025-03-16T16:21:08",{"id":152,"version":153,"summary_zh":154,"released_at":155},61679,"v0.4.6","## 变更内容\n* chore(cli)：由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F374 中发布 v0.4.5 版本\n* docs：由 @devin-ai-integration 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F378 中更新 README，添加浏览器配置选项\n* fix(cli)：由 @khalatevarun 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F382 中实现带行号功能的测试执行\n* feat：由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F369 中添加 claude-3-7-sonnet-20250219 模型\n\n\n**完整变更日志**：https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fcompare\u002Fv0.4.5...v0.4.6","2025-03-09T03:40:59",{"id":157,"version":158,"summary_zh":159,"released_at":160},61680,"v0.4.5","## 变更内容\n* 修复：由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F365 中修复清理过程中缺失缓存文件夹的问题。\n* 修复：由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F366 中实现 `dirname` 的 ES 模块兼容性。\n* 文档：由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F368 中更新 CONTRIBUTING 文件。\n* 功能：由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F367 中改进错误处理。\n* 功能（CLI）：由 @khalatevarun 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F338 中实现从测试文件中执行单个测试的功能。\n* 重构：由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F372 中添加 `ToolRegistry`。\n* 功能：由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F373 中添加 `config.browser` 配置选项。\n* 杂项：由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F370 中添加 `TestCase`。\n\n\n**完整变更日志**：https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fcompare\u002Fv0.4.4...v0.4.5","2025-03-02T06:44:15",{"id":162,"version":163,"summary_zh":164,"released_at":165},61681,"v0.4.4","## 变更内容\n* chore(cli): 添加单元测试工作流，由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F304 中完成\n* chore(cli): 更新依赖项，由 @devin-ai-integration 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F306 中完成\n* chore: 更新依赖项，由 @devin-ai-integration 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F317 中完成\n* chore(refactor): 将 Logger 重命名为 TestReporter，由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F319 中完成\n* fix: 使用 'add' 命令进行 Yarn 初始化，由 @devin-ai-integration 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F322 中完成\n* fix: 累积来自所有 AI 响应的 token 数量，由 @devin-ai-integration 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F323 中完成\n* refactor: 将 commands 目录移至 cli，由 @devin-ai-integration 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F324 中完成\n* refactor: 准备 TestReporter，由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F328 中完成\n* feat(cli): 引入 Log 功能，由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F320 中完成\n* docs(cli): 改进开发说明，由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F330 中完成\n* refactor: 更新导入路径，使用 @ 别名引用 shortest 包中的模块，由 @devin-ai-integration 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F329 中完成\n* fix: 暴露 runner 的错误信息，由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F336 中完成\n* fix: 改进日志错误处理，由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F337 中完成\n* chore: 更新依赖项，由 @devin-ai-integration 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F343 中完成\n* feat(ai): 引入 Vercel AI SDK 支持，由 @gladyshcodes 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F316 中完成\n* chore: 更新导入语句，由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F345 中完成\n* chore(eslint): 强制使用函数表达式，由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F344 中完成\n* chore(eslint): 添加 arrow-body-style ESLint 规则，由 @devin-ai-integration 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F347 中完成\n* chore: 添加 eqeqeq ESLint 规则，由 @devin-ai-integration 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F348 中完成\n* chore: 重命名 cache.ts 文件，由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F350 中完成\n* chore: 添加 logical-assignment-operators ESLint 规则，由 @devin-ai-integration 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F349 中完成\n* chore(eslint): 添加 no-alert ESLint 规则，由 @devin-ai-integration 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F352 中完成\n* chore(eslint): 添加 no-else-return ESLint 规则，由 @devin-ai-integration 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F353 中完成\n* chore(eslint): 添加 no-empty ESLint 规则，由 @devin-ai-integration 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F354 中完成\n* chore(eslint): 添加 no-lone-blocks ESLint 规则，由 @devin-ai-integration 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F355 中完成\n* chore(eslint): 添加 no-lonely-if ESLint 规则，由 @devin-ai-integration 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F356 中完成\n* feat(eslint): 强制执行 Zod 模式类型检查，由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fanti-work","2025-02-23T07:49:51",{"id":167,"version":168,"summary_zh":169,"released_at":170},61682,"v0.4.3","## 变更内容\n* chore(cli): 移除 `cli:test:src` 脚本，由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F277 中完成\n* docs: 更新《快速入门》步骤，由 @khalatevarun 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F299 中完成\n* fix(cli): 处理浏览器初始化失败问题，由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F298 中完成\n* fix(cli): 针对特定状态码阻止 AI API 重试，由 @khalatevarun 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F301 中完成\n* feat(cli): 添加 `shortest init` 命令，由 @khalatevarun 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F297 中完成\n* chore(cli): 改进配置解析与验证，由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F302 中完成\n\n\n**完整变更日志**: https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fcompare\u002Fv0.4.1...v0.4.3","2025-01-31T07:47:20",{"id":172,"version":173,"summary_zh":174,"released_at":175},61683,"v0.4.2","## 变更内容\n* 修复：@khalatevarun 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F267 中修正的拼写错误\n* 构建优化（CLI）：@rmarescu 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F266 中改进了测试执行错误的处理\n* 构建优化（CLI）：@gladyshcodes 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F216 中新增了包监听模式的暴露\n* 修复（CLI）：@PedroAVJ 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F256 中使 Shortest 兼容 Windows 系统\n* 构建优化（CLI）：@rmarescu 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F270 中改进了 Mailosaur API 错误的调试流程\n* 构建优化：@rmarescu 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F273 中在 CI 中针对本地构建运行测试\n* 构建优化（CLI）：@rmarescu 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F272 中将 `pkg` 前缀重命名为 `cli`，并改进了文档\n* 修复（CLI）：@rmarescu 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F274 中传播了 AI 响应解析相关的失败信息\n\n\n**完整变更日志**：https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fcompare\u002Fv0.4.1...v0.4.2","2025-01-16T19:52:09",{"id":177,"version":178,"summary_zh":179,"released_at":180},61684,"v0.4.1","## 变更内容\n* 重构 TestRunner：将 AI 处理逻辑移至更合适的 l…，由 @PedroAVJ 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F248 中完成\n* 文档：更新测试命令示例，加入目录路径，由 @devin-ai-integration 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F250 中完成\n* 功能：在 BrowserManager 上下文中添加 baseURL 配置，由 @PedroAVJ 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F252 中完成\n* 日志功能：在摘要中添加令牌使用详情，由 @khalatevarun 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F255 中完成\n* 文档：添加示例测试及面向非工程师的介绍文案，由 @devin-ai-integration 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F259 中完成\n* 改进 AI 对新打开标签页的使用，由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F254 中完成\n* 更新 README，加入 CLI 示例，由 @Aldian1 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F263 中完成\n* 发布 v0.4.1，由 @rmarescu 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F264 中完成\n\n## 新贡献者\n* @PedroAVJ 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F248 中完成了首次贡献\n* @Aldian1 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F263 中完成了首次贡献\n\n**完整变更日志**：https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fcompare\u002Fv0.4.0...v0.4.1","2025-01-08T05:39:15",{"id":182,"version":183,"summary_zh":184,"released_at":185},61685,"v0.4.0","## 变更内容\n\n### 新增\n* 由 @crabest 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F136 中添加链式测试\n* 由 @slavingia 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F224 中添加 'before' 函数\n* 由 @gladyshcodes 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F233 中添加 Bash 工具\n\n\n### 修改\n* 由 @slavingia 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F222 中更新 README.md\n* 由 @crabest 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F232 中调整提示信息，使其预期测试成功\n* 由 @crabest 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F235 中将版权年份从 2024 年更新为 2025 年\n* 由 @khalatevarun 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F194 中重构配置：更新配置以检测 test.ts 文件，而非 test 目录下的文件\n* 由 @amk-dev 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F231 中改进 index.d.ts 的生成\n* 由 @slavingia 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F239 中更新 shortest.config.ts\n* 由 @m2rads 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F245 中更新 npm 说明文档\n* 由 @m2rads 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F246 中发布版本 0.4.0\n\n### 移除\n* 由 @m2rads 在 https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F242 中移除对 Yarn 的支持\n\n**完整变更日志**: https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fcompare\u002Fv0.3.0...v0.4.0","2025-01-02T20:13:17",{"id":187,"version":188,"summary_zh":189,"released_at":190},61686,"v0.3.0","## What's Changed\r\n* Add caching by @gladyshcodes in https:\u002F\u002Fgithub.com\u002Fanti-work\u002Fshortest\u002Fpull\u002F179\r\n","2024-12-31T03:10:10",{"id":192,"version":193,"summary_zh":194,"released_at":195},61687,"v0.2.1","# What's Changed: \r\n\r\n- Mailosaur integration for email validation via AI #183 \r\n- Enhance browser installation based on users package manager #173  \r\n- Fix postinstall script for Windows compatibility #169 \r\n\r\n\r\n# Contributors\r\n[![m2rads](https:\u002F\u002Fimages.weserv.nl\u002F?url=https:\u002F\u002Fgithub.com\u002Fm2rads.png&h=30&w=30&fit=cover&mask=circle&maxage=7d)](https:\u002F\u002Fgithub.com\u002Fm2rads) [![amk-dev](https:\u002F\u002Fimages.weserv.nl\u002F?url=https:\u002F\u002Fgithub.com\u002Famk-dev.png&h=30&w=30&fit=cover&mask=circle&maxage=7d)](https:\u002F\u002Fgithub.com\u002Famk-dev) [![cutsin](https:\u002F\u002Fimages.weserv.nl\u002F?url=https:\u002F\u002Fgithub.com\u002Fcutsin.png&h=30&w=30&fit=cover&mask=circle&maxage=7d)](https:\u002F\u002Fgithub.com\u002Fcutsin)","2024-12-30T07:42:17"]