[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"similar-ThePrimeagen--99":3,"tool-ThePrimeagen--99":61},[4,18,26,36,44,53],{"id":5,"name":6,"github_repo":7,"description_zh":8,"stars":9,"difficulty_score":10,"last_commit_at":11,"category_tags":12,"status":17},4358,"openclaw","openclaw\u002Fopenclaw","OpenClaw 是一款专为个人打造的本地化 AI 助手，旨在让你在自己的设备上拥有完全可控的智能伙伴。它打破了传统 AI 助手局限于特定网页或应用的束缚，能够直接接入你日常使用的各类通讯渠道，包括微信、WhatsApp、Telegram、Discord、iMessage 等数十种平台。无论你在哪个聊天软件中发送消息，OpenClaw 都能即时响应，甚至支持在 macOS、iOS 和 Android 设备上进行语音交互，并提供实时的画布渲染功能供你操控。\n\n这款工具主要解决了用户对数据隐私、响应速度以及“始终在线”体验的需求。通过将 AI 部署在本地，用户无需依赖云端服务即可享受快速、私密的智能辅助，真正实现了“你的数据，你做主”。其独特的技术亮点在于强大的网关架构，将控制平面与核心助手分离，确保跨平台通信的流畅性与扩展性。\n\nOpenClaw 非常适合希望构建个性化工作流的技术爱好者、开发者，以及注重隐私保护且不愿被单一生态绑定的普通用户。只要具备基础的终端操作能力（支持 macOS、Linux 及 Windows WSL2），即可通过简单的命令行引导完成部署。如果你渴望拥有一个懂你",349277,3,"2026-04-06T06:32:30",[13,14,15,16],"Agent","开发框架","图像","数据工具","ready",{"id":19,"name":20,"github_repo":21,"description_zh":22,"stars":23,"difficulty_score":10,"last_commit_at":24,"category_tags":25,"status":17},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,"2026-04-05T11:01:52",[14,15,13],{"id":27,"name":28,"github_repo":29,"description_zh":30,"stars":31,"difficulty_score":32,"last_commit_at":33,"category_tags":34,"status":17},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 真正成长为懂上",144730,2,"2026-04-07T23:26:32",[14,13,35],"语言模型",{"id":37,"name":38,"github_repo":39,"description_zh":40,"stars":41,"difficulty_score":32,"last_commit_at":42,"category_tags":43,"status":17},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 都能提供强大的支持。其独特的模块化架构允许社区不断扩展新功能，使其成为当前最灵活、生态最丰富的开源扩散模型工具之一，帮助用户将创意高效转化为现实。",107888,"2026-04-06T11:32:50",[14,15,13],{"id":45,"name":46,"github_repo":47,"description_zh":48,"stars":49,"difficulty_score":32,"last_commit_at":50,"category_tags":51,"status":17},4721,"markitdown","microsoft\u002Fmarkitdown","MarkItDown 是一款由微软 AutoGen 团队打造的轻量级 Python 工具，专为将各类文件高效转换为 Markdown 格式而设计。它支持 PDF、Word、Excel、PPT、图片（含 OCR）、音频（含语音转录）、HTML 乃至 YouTube 链接等多种格式的解析，能够精准提取文档中的标题、列表、表格和链接等关键结构信息。\n\n在人工智能应用日益普及的今天，大语言模型（LLM）虽擅长处理文本，却难以直接读取复杂的二进制办公文档。MarkItDown 恰好解决了这一痛点，它将非结构化或半结构化的文件转化为模型“原生理解”且 Token 效率极高的 Markdown 格式，成为连接本地文件与 AI 分析 pipeline 的理想桥梁。此外，它还提供了 MCP（模型上下文协议）服务器，可无缝集成到 Claude Desktop 等 LLM 应用中。\n\n这款工具特别适合开发者、数据科学家及 AI 研究人员使用，尤其是那些需要构建文档检索增强生成（RAG）系统、进行批量文本分析或希望让 AI 助手直接“阅读”本地文件的用户。虽然生成的内容也具备一定可读性，但其核心优势在于为机器",93400,"2026-04-06T19:52:38",[52,14],"插件",{"id":54,"name":55,"github_repo":56,"description_zh":57,"stars":58,"difficulty_score":10,"last_commit_at":59,"category_tags":60,"status":17},4487,"LLMs-from-scratch","rasbt\u002FLLMs-from-scratch","LLMs-from-scratch 是一个基于 PyTorch 的开源教育项目，旨在引导用户从零开始一步步构建一个类似 ChatGPT 的大型语言模型（LLM）。它不仅是同名技术著作的官方代码库，更提供了一套完整的实践方案，涵盖模型开发、预训练及微调的全过程。\n\n该项目主要解决了大模型领域“黑盒化”的学习痛点。许多开发者虽能调用现成模型，却难以深入理解其内部架构与训练机制。通过亲手编写每一行核心代码，用户能够透彻掌握 Transformer 架构、注意力机制等关键原理，从而真正理解大模型是如何“思考”的。此外，项目还包含了加载大型预训练权重进行微调的代码，帮助用户将理论知识延伸至实际应用。\n\nLLMs-from-scratch 特别适合希望深入底层原理的 AI 开发者、研究人员以及计算机专业的学生。对于不满足于仅使用 API，而是渴望探究模型构建细节的技术人员而言，这是极佳的学习资源。其独特的技术亮点在于“循序渐进”的教学设计：将复杂的系统工程拆解为清晰的步骤，配合详细的图表与示例，让构建一个虽小但功能完备的大模型变得触手可及。无论你是想夯实理论基础，还是为未来研发更大规模的模型做准备",90106,"2026-04-06T11:19:32",[35,15,13,14],{"id":62,"github_repo":63,"name":64,"description_en":65,"description_zh":66,"ai_summary_zh":66,"readme_en":67,"readme_zh":68,"quickstart_zh":69,"use_case_zh":70,"hero_image_url":71,"owner_login":72,"owner_name":72,"owner_avatar_url":73,"owner_bio":74,"owner_company":75,"owner_location":76,"owner_email":77,"owner_twitter":72,"owner_website":78,"owner_url":79,"languages":80,"stars":103,"forks":104,"last_commit_at":105,"license":74,"difficulty_score":32,"env_os":106,"env_gpu":107,"env_ram":107,"env_deps":108,"category_tags":114,"github_topics":74,"view_count":32,"oss_zip_url":74,"oss_zip_packed_at":74,"status":17,"created_at":115,"updated_at":116,"faqs":117,"releases":146},5436,"ThePrimeagen\u002F99","99","Neovim AI agent done right","99 是一款专为 Neovim 打造的 AI 智能体客户端，旨在将程序员的手写代码能力与大语言模型的强大算力完美融合。它并非要取代开发者，而是作为得力助手，通过增强而非替代的方式提升编码效率。\n\n99 主要解决了传统 AI 插件仅能片段式替换代码的局限，转而聚焦于更宏观的“搜索”与“工作流”代理模式。它能帮助开发者在复杂的代码库中快速定位信息、理解上下文，并执行连贯的开发任务，让 AI 真正融入日常编程习惯。\n\n这款工具特别适合热爱 Neovim、重视手写代码价值且愿意尝试前沿工作流的资深开发者。如果你希望在使用 AI 辅助的同时，依然保持对代码逻辑的完全掌控，99 是理想之选。\n\n其独特亮点在于高度可定制的规则系统（支持自定义 SKILL.md）和灵活的文件上下文发现机制，能够根据项目结构智能加载相关文档。此外，99 目前处于测试阶段，作者正积极探索\"AI+ 传统编码”的最佳实践，虽然 API 可能随版本迭代有所调整，但其核心理念始终是为那些享受编码乐趣的人提供最原生的 Neovim AI 体验。","# 99\nThe AI client that Neovim deserves, built by those that still enjoy to code.\n\n## IF YOU ARE HERE FROM [THE YT VIDEO](https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=ws9zR-UzwTE)\nSo many things have changed.  So please be careful!\n\n## WARNING :: API CHANGES RIGHT NOW\nIt will happen that apis will disapear or be changed.  Sorry, this is an BETA product.\n\n## Project Direction\nThis repo is meant to be my exploration grounds for using AI mixed with tradcoding.\n\nI believe that hand coding is still very important and the best products i know\nof today still do that (see opencode vs claude code)\n\n## Warning\n1. Prompts are temporary right now. they could be massively improved\n2. Officially in beta, but api can still change.  unlikely at this point\n\n# 99\nThe AI Neovim experience\n\n## _99\n99 is an agentic workflow that is meant to meld the current programmers ability\nwith the amazing powers of LLMs.  Instead of being a replacement, its meant to\naugment the programmer.\n\nAs of now, the direction of 99 is to progress into agentic programming and surfacing\nof information.  In the beginning and the original youtube video was about replacing\nspecific pieces of code.  The more i use 99 the more i realize the better use is\nthrough `search` and `work`\n\n### Basic Setup\n```lua\n\t{\n\t\t\"ThePrimeagen\u002F99\",\n\t\tconfig = function()\n\t\t\tlocal _99 = require(\"99\")\n\n            -- For logging that is to a file if you wish to trace through requests\n            -- for reporting bugs, i would not rely on this, but instead the provided\n            -- logging mechanisms within 99.  This is for more debugging purposes\n            local cwd = vim.uv.cwd()\n            local basename = vim.fs.basename(cwd)\n\t\t\t_99.setup({\n                -- provider = _99.Providers.ClaudeCodeProvider,  -- default: OpenCodeProvider\n\t\t\t\tlogger = {\n\t\t\t\t\tlevel = _99.DEBUG,\n\t\t\t\t\tpath = \"\u002Ftmp\u002F\" .. basename .. \".99.debug\",\n\t\t\t\t\tprint_on_error = true,\n\t\t\t\t},\n                -- When setting this to something that is not inside the CWD tools\n                -- such as claude code or opencode will have permission issues\n                -- and generation will fail refer to tool documentation to resolve\n                -- https:\u002F\u002Fopencode.ai\u002Fdocs\u002Fpermissions\u002F#external-directories\n                -- https:\u002F\u002Fcode.claude.com\u002Fdocs\u002Fen\u002Fpermissions#read-and-edit\n                tmp_dir = \".\u002Ftmp\",\n\n                --- Completions: #rules and @files in the prompt buffer\n                completion = {\n                    -- I am going to disable these until i understand the\n                    -- problem better.  Inside of cursor rules there is also\n                    -- application rules, which means i need to apply these\n                    -- differently\n                    -- cursor_rules = \"\u003Ccustom path to cursor rules>\"\n\n                    --- A list of folders where you have your own SKILL.md\n                    --- Expected format:\n                    --- \u002Fpath\u002Fto\u002Fdir\u002F\u003Cskill_name>\u002FSKILL.md\n                    ---\n                    --- Example:\n                    --- Input Path:\n                    --- \"scratch\u002Fcustom_rules\u002F\"\n                    ---\n                    --- Output Rules:\n                    --- {path = \"scratch\u002Fcustom_rules\u002Fvim\u002FSKILL.md\", name = \"vim\"},\n                    --- ... the other rules in that dir ...\n                    ---\n                    custom_rules = {\n                      \"scratch\u002Fcustom_rules\u002F\",\n                    },\n\n                    --- Configure @file completion (all fields optional, sensible defaults)\n                    files = {\n                        -- enabled = true,\n                        -- max_file_size = 102400,     -- bytes, skip files larger than this\n                        -- max_files = 5000,            -- cap on total discovered files\n                        -- exclude = { \".env\", \".env.*\", \"node_modules\", \".git\", ... },\n                    },\n                    --- File Discovery:\n                    --- - In git repos: Uses `git ls-files` which automatically respects .gitignore\n                    --- - Non-git repos: Falls back to filesystem scanning with manual excludes\n                    --- - Both methods apply the configured `exclude` list on top of gitignore\n\n                    --- What autocomplete engine to use. Defaults to native (built-in) if not specified.\n                    source = \"native\", -- \"native\" (default), \"cmp\", or \"blink\"\n                },\n\n                --- WARNING: if you change cwd then this is likely broken\n                --- ill likely fix this in a later change\n                ---\n                --- md_files is a list of files to look for and auto add based on the location\n                --- of the originating request.  That means if you are at \u002Ffoo\u002Fbar\u002Fbaz.lua\n                --- the system will automagically look for:\n                --- \u002Ffoo\u002Fbar\u002FAGENT.md\n                --- \u002Ffoo\u002FAGENT.md\n                --- assuming that \u002Ffoo is project root (based on cwd)\n\t\t\t\tmd_files = {\n\t\t\t\t\t\"AGENT.md\",\n\t\t\t\t},\n\t\t\t})\n\n            -- take extra note that i have visual selection only in v mode\n            -- technically whatever your last visual selection is, will be used\n            -- so i have this set to visual mode so i dont screw up and use an\n            -- old visual selection\n            --\n            -- likely ill add a mode check and assert on required visual mode\n            -- so just prepare for it now\n\t\t\tvim.keymap.set(\"v\", \"\u003Cleader>9v\", function()\n\t\t\t\t_99.visual()\n\t\t\tend)\n\n            --- if you have a request you dont want to make any changes, just cancel it\n\t\t\tvim.keymap.set(\"n\", \"\u003Cleader>9x\", function()\n\t\t\t\t_99.stop_all_requests()\n\t\t\tend)\n\n\t\t\tvim.keymap.set(\"n\", \"\u003Cleader>9s\", function()\n\t\t\t\t_99.search()\n\t\t\tend)\n\t\tend,\n\t},\n```\n\n### Usage\nI would highly recommend trying out `search` as its the direction the library is going\n\n```lua\n_99.search()\n```\n\nSee search for more details\n\n### Description\n| Name | Type | Default Value |\n| --- | --- | --- |\n| `setup` | `fun(opts?: _99.Options): nil` | - |\n| `search` | `fun(opts: _99.ops.SearchOpts): _99.TraceID` | - |\n| `vibe` | `fun(opts?: _99.ops.Opts): _99.TraceID \\| nil` | - |\n| `open` | `fun(): nil` | - |\n| `visual` | `fun(opts: _99.ops.Opts): _99.TraceID` | - |\n| `view_logs` | `fun(): nil` | - |\n| `stop_all_requests` | `fun(): nil` | - |\n| `clear_previous_requests` | `fun(): nil` | - |\n| `Extensions` | `_99.Extensions` | - |\n\n### API\n\n#### setup\nSets up _99.  Must be called for this library to work.  This is how we setup\nin flight request spinners, set default values, get completion to work the\nway you want it to.\n\n#### search\nPerforms a search across your project with the prompt you provide and return out a list of\nlocations with notes that will be put into your quick fix list.\n\n#### vibe\nNo description.\n\n#### open\nOpens a selection window for you to select the last interaction to open\nand display its contents in a way that makes sense for its type.  For\nsearch and vibe, it will open the qfix window.  For tutorial, it will open\nthe tutorial window.\n\n#### visual\ntakes your current selection and sends that along with the prompt provided and replaces\nyour visual selection with the results\n\n#### view_logs\nviews the most recent logs and setups the machine to view older and new logs\nthis is still pretty rough and will change in the near future\n\n#### stop_all_requests\nstops all in flight requests.  this means that the underlying process will\nbe killed (OpenCode) and any result will be discared\n\n#### clear_previous_requests\nclears all previous search and visual operations\n\n#### Extensions\ncheck out Worker for cool abstraction on search and vibe\n\n## _99.Extensions.Worker\nA persistent way to keep track of work.\n\nthis will likely be where the most change and focus goes into.  I would like\nto take this into worktree territory and be able to swap between stuff super\nslick.\n\nUntil then, it is going to be a single bit of work that you can provide\nthe description and then use search to find what is left that needs to be done.\n\n### Description\n| Name | Type | Default Value |\n| --- | --- | --- |\n| `set_work` | `fun(opts?: _99.WorkOpts): nil` | - |\n| `search` | `fun(): nil` | - |\n\n### API\n\n#### set_work\nwill set the work for the project.  If opts provide a description then no\ninput capture of work description will be required\n\n#### search\nwill use _99.search to find what is left to be done for this work item to be\nconsidered done\n\n## _99.Options\nNo description.\n\n### Description\n| Name | Type | Default Value |\n| --- | --- | --- |\n| `logger` | `_99.Logger.Options \\| nil` | - |\n| `model` | `string \\| nil` | - |\n| `in_flight_options` | `_99.InFlight.Opts \\| nil` | - |\n| `md_files` | `string[] \\| nil` | - |\n| `provider` | `_99.Providers.BaseProvider \\| nil` | - |\n| `display_errors` | `boolean \\| nil` | - |\n| `auto_add_skills` | `boolean \\| nil` | - |\n| `completion` | `_99.Completion \\| nil` | - |\n| `tmp_dir` | `string \\| nil` | - |\n\n### API\n\n#### logger\nNo description.\n\n#### model\nNo description.\n\n#### in_flight_options\nNo description.\n\n#### md_files\nNo description.\n\n#### provider\nNo description.\n\n#### display_errors\nNo description.\n\n#### auto_add_skills\nNo description.\n\n#### completion\nNo description.\n\n#### tmp_dir\nNo description.\n\n## _99.ops.Opts\nThe options that are used throughout all the interations with 99.  This\nincludes search, visual, and others\n\n### Description\n| Name | Type | Default Value |\n| --- | --- | --- |\n| `additional_prompt` | `string \\| nil` | - |\n| `additional_rules` | `_99.Agents.Rule[] \\| nil` | - |\n\n### API\n\n#### additional_prompt\nby providing `additional_prompt` you will not be required to provide a prompt.\nthis allows you to define actions based on remaps\n\n```lua\nremap(\"n\", \"\u003Cleader>9d\", function()\n  --- this function could be used to auto debug your project\n  _99.search({\n    additional_prompt = [[\nrun `make test` and debug the test failures and provide me a comprehensive set of steps where\nthe tests are breaking ]]\n  })\nend)\n```\n\nThis would kick off a search job that will run your tests in the background.\nthe resulting failures would be diagnosed and search results would be transfered\ninto a quick fix list.\n\n#### additional_rules\ncan be used to provide extra args.  If you have a skill called \"cloudflare\" you could\nprovide the rule for cloudflare and its context will be injected into your request\n\n## _99.ops.SearchOpts\nSee `_99.opts.Opts` for more information.\n\nThere are no properties yet.  But i would like to tweek some behavior based on opts\n\n### Description\n| Name | Type | Default Value |\n| --- | --- | --- |\n| - | - | - |\n\n### API\nNo properties.\n\n## _99.WorkOpts\nNo description.\n\n### Description\n| Name | Type | Default Value |\n| --- | --- | --- |\n| `description` | `string \\| nil` | - |\n\n### API\n\n#### description\nNo description.\n\n## _99.Completion\nNo description.\n\n### Description\n| Name | Type | Default Value |\n| --- | --- | --- |\n| `source` | `\"cmp\" \\| \"blink\" \\| nil` | - |\n| `custom_rules` | `string[]` | - |\n| `files` | `_99.Files.Config?` | - |\n\n### API\n\n#### source\nNo description.\n\n#### custom_rules\nNo description.\n\n#### files\nNo description.\n\n## _99.InFlight.Opts\nthis is pure a class for testing.   helps controls timings\n\n### Description\n| Name | Type | Default Value |\n| --- | --- | --- |\n| `throbber_opts` | `_99.Throbber.Opts \\| nil` | - |\n| `in_flight_interval` | `number \\| nil` | - |\n| `enable` | `boolean \\| nil` | - |\n\n### API\n\n#### throbber_opts\noptions for the throbber in the top left\n\n#### in_flight_interval\nfrequency in which the in-flight interval checks to see if it should be\ndisplayed \u002F removed\n\n#### enable\ndefaults to true\n\n## _99.Logger.Options\nNo description.\n\n### Description\n| Name | Type | Default Value |\n| --- | --- | --- |\n| `level` | `number?` | - |\n| `type` | `\"print\" \\| \"void\" \\| \"file\" \\| nil` | - |\n| `path` | `string?` | - |\n| `print_on_error` | `boolean \\| nil` | - |\n| `max_requests_cached` | `number \\| nil` | - |\n\n### API\n\n#### level\nNo description.\n\n#### type\nNo description.\n\n#### path\nNo description.\n\n#### print_on_error\nNo description.\n\n#### max_requests_cached\nNo description.\n\n## _99.Agents.Rule\nNo description.\n\n### Description\n| Name | Type | Default Value |\n| --- | --- | --- |\n| `name` | `string` | - |\n| `path` | `string` | - |\n| `absolute_path` | `string?` | - |\n\n### API\n\n#### name\nNo description.\n\n#### path\nNo description.\n\n#### absolute_path\nNo description.\n\n## Completions\n\nWhen prompting, you can reference rules and files to add context to your request.\n\n- `#` references rules — type `#` in the prompt to autocomplete rule files from your configured rule directories\n- `@` references files — type `@` to fuzzy-search project files. This will exclude files that are in .gitignore.\n\nReferenced content is automatically resolved and injected into the AI context. Native completions work by default. For nvim-cmp or blink.cmp, set `source = \"cmp\"` or `source = \"blink\"`.\n\n## Providers\n99 supports multiple AI CLI backends. Set `provider` in your setup to switch. If you don't set `model`, the provider's default is used.\n\n| Provider | CLI tool | Default model |\n|---|---|---|\n| `OpenCodeProvider` (default) | `opencode` | `opencode\u002Fclaude-sonnet-4-5` |\n| `ClaudeCodeProvider` | `claude` | `claude-sonnet-4-5` |\n| `CursorAgentProvider` | `cursor-agent` | `sonnet-4.5` |\n| `GeminiCLIProvider` | `gemini` | `auto` |\n\n```lua\n_99.setup({\n    provider = _99.Providers.ClaudeCodeProvider,\n    -- model is optional, overrides the provider's default\n    model = \"claude-sonnet-4-5\",\n})\n```\n\n## Extensions\n\n### Telescope Model Selector\n\nIf you have [telescope.nvim](https:\u002F\u002Fgithub.com\u002Fnvim-telescope\u002Ftelescope.nvim) installed, you can switch models on the fly via the Telescope picker:\n\n```lua\nvim.keymap.set(\"n\", \"\u003Cleader>9m\", function()\n  require(\"99.extensions.telescope\").select_model()\nend)\n```\n\nThe selected model is used for all subsequent requests in the current session.\n\n### Telescope Provider Selector\n\nSwitch between providers (OpenCode, Claude, Cursor, Kiro) without restarting Neovim. Switching provider also resets the model to that provider's default.\n\n```lua\nvim.keymap.set(\"n\", \"\u003Cleader>9p\", function()\n  require(\"99.extensions.telescope\").select_provider()\nend)\n```\n\n### fzf-lua\n\nIf you use [fzf-lua](https:\u002F\u002Fgithub.com\u002Fibhagwan\u002Ffzf-lua) instead of telescope, the same pickers are available:\n\n```lua\nvim.keymap.set(\"n\", \"\u003Cleader>9m\", function()\n  require(\"99.extensions.fzf_lua\").select_model()\nend)\n\nvim.keymap.set(\"n\", \"\u003Cleader>9p\", function()\n  require(\"99.extensions.fzf_lua\").select_provider()\nend)\n```\n\n## Reporting a bug\n\nTo report a bug, please provide the full running debug logs. This may require\na bit of back and forth.\n\nPlease do not request features. We will hold a public discussion on Twitch about\nfeatures, which will be a much better jumping point then a bunch of requests that i have to close down. If you do make a feature request ill just shut it down instantly.\n\n### The logs\nTo get the _last_ run's logs execute `:lua require(\"99\").view_logs()`.\n\n### Dont forget\nIf there are secrets or other information in the logs you want to be removed make\nsure that you delete the `query` printing. This will likely contain information you may not want to share.\n\n","# 99\nNeovim 应得的 AI 客户端，由那些依然热爱编码的人打造。\n\n## 如果你是从 [YouTube 视频](https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=ws9zR-UzwTE) 来的\n很多事情都发生了变化。所以请务必小心！\n\n## 警告 :: 当前 API 正在变化\nAPI 可能会消失或被更改。抱歉，这是一款 BETA 产品。\n\n## 项目方向\n这个仓库旨在成为我探索将 AI 与传统编程结合使用的试验场。\n\n我相信手工编码仍然非常重要，而当今我所知的最佳产品依然坚持这一点（参见 opencode 与 claude code）。\n\n## 警告\n1. 提示目前是临时的，未来可以大幅改进。\n2. 正式处于 Beta 阶段，但 API 仍可能发生变化。不过现在不太可能了。\n\n# 99\nAI 的 Neovim 使用体验\n\n## _99\n99 是一种代理式工作流，旨在将当前程序员的能力与大型语言模型的强大功能相结合。它并不是要取代程序员，而是用来增强程序员的工作。\n\n目前，99 的发展方向是推进代理式编程和信息的呈现。最初以及最初的 YouTube 视频中提到的是用 AI 替换特定的代码片段。然而，随着我对 99 的使用越来越深入，我逐渐意识到它更好的用途在于“搜索”和“工作”。\n\n### 基本设置\n```lua\n\t{\n\t\t\"ThePrimeagen\u002F99\",\n\t\tconfig = function()\n\t\t\tlocal _99 = require(\"99\")\n\n            -- 用于日志记录，如果希望追踪请求以报告 bug，建议不要依赖此方式，而是使用 99 内置的日志机制。此配置主要用于调试目的。\n            local cwd = vim.uv.cwd()\n            local basename = vim.fs.basename(cwd)\n\t\t\t_99.setup({\n                -- provider = _99.Providers.ClaudeCodeProvider,  -- 默认：OpenCodeProvider\n\t\t\t\tlogger = {\n\t\t\t\t\tlevel = _99.DEBUG,\n\t\t\t\t\tpath = \"\u002Ftmp\u002F\" .. basename .. \".99.debug\",\n\t\t\t\t\tprint_on_error = true,\n\t\t\t\t},\n                -- 当设置为非当前工作目录的路径时，例如 claude code 或 opencode，可能会出现权限问题，导致生成失败。请参考相关工具的文档来解决：\n                -- https:\u002F\u002Fopencode.ai\u002Fdocs\u002Fpermissions\u002F#external-directories\n                -- https:\u002F\u002Fcode.claude.com\u002Fdocs\u002Fen\u002Fpermissions#read-and-edit\n                tmp_dir = \".\u002Ftmp\",\n\n                --- 补全功能：提示缓冲区中的 #rules 和 @files\n                completion = {\n                    -- 我暂时禁用这些功能，直到更好地理解问题所在。光标规则中还包含应用规则，这意味着需要以不同的方式应用它们。\n                    -- cursor_rules = \"\u003C自定义光标规则路径>\"\n\n                    --- 包含您自己的 SKILL.md 文件的文件夹列表\n                    --- 预期格式：\n                    --- \u002Fpath\u002Fto\u002Fdir\u002F\u003Cskill_name>\u002FSKILL.md\n                    ---\n                    --- 示例：\n                    --- 输入路径：\n                    --- \"scratch\u002Fcustom_rules\u002F\"\n                    ---\n                    --- 输出规则：\n                    --- {path = \"scratch\u002Fcustom_rules\u002Fvim\u002FSKILL.md\", name = \"vim\"},\n                    --- ... 该目录下的其他规则 ...\n                    ---\n                    custom_rules = {\n                      \"scratch\u002Fcustom_rules\u002F\",\n                    },\n\n                    --- 配置 @file 补全（所有字段可选，有合理默认值）\n                    files = {\n                        -- enabled = true,\n                        -- max_file_size = 102400,     -- 字节，跳过大于此大小的文件\n                        -- max_files = 5000,            -- 总发现文件数上限\n                        -- exclude = { \".env\", \".env.*\", \"node_modules\", \".git\", ... },\n                    },\n                    --- 文件发现：\n                    --- - 在 Git 仓库中：使用 `git ls-files`，自动尊重 .gitignore 文件。\n                    --- - 非 Git 仓库：回退到文件系统扫描，并手动排除指定文件。\n                    --- - 两种方法都会在 .gitignore 的基础上应用配置的 `exclude` 列表。\n\n                    --- 使用哪种自动补全引擎。未指定时，默认使用原生（内置）引擎。\n                    source = \"native\", -- \"native\"（默认）、\"cmp\" 或 \"blink\"\n                },\n\n                --- 警告：如果更改当前工作目录，此功能很可能失效\n                --- 我可能会在后续更新中修复这个问题。\n                ---\n                --- md_files 是一个文件列表，系统会根据原始请求的位置自动查找并添加这些文件。也就是说，如果你位于 \u002Ffoo\u002Fbar\u002Fbaz.lua，\n                --- 系统会自动查找：\n                --- \u002Ffoo\u002Fbar\u002FAGENT.md\n                --- \u002Ffoo\u002FAGENT.md\n                --- 假设 \u002Ffoo 是项目根目录（基于当前工作目录）。\n\t\t\t\tmd_files = {\n\t\t\t\t\t\"AGENT.md\",\n\t\t\t\t},\n\t\t\t})\n\n            -- 请注意，我在视觉模式下才进行操作\n            -- 实际上，无论你上次选择的是什么内容，都会被使用\n            -- 因此我将其设置为视觉模式，以免误用之前的视觉选择。\n            --\n            -- 未来可能会增加模式检查，并断言必须处于视觉模式\n            -- 所以现在就做好准备吧。\n\t\t\tvim.keymap.set(\"v\", \"\u003Cleader>9v\", function()\n\t\t\t\t_99.visual()\n\t\t\tend)\n\n            --- 如果你有一个请求不想再继续，可以直接取消它。\n\t\t\tvim.keymap.set(\"n\", \"\u003Cleader>9x\", function()\n\t\t\t\t_99.stop_all_requests()\n\t\t\tend)\n\n\t\t\tvim.keymap.set(\"n\", \"\u003Cleader>9s\", function()\n\t\t\t\t_99.search()\n\t\t\tend)\n\t\tend,\n\t},\n```\n\n### 使用方法\n我强烈推荐尝试 `search` 功能，因为这是该库的发展方向。\n\n```lua\n_99.search()\n```\n\n更多详情请参阅搜索部分。\n\n### 描述\n| 名称 | 类型 | 默认值 |\n| --- | --- | --- |\n| `setup` | `fun(opts?: _99.Options): nil` | - |\n| `search` | `fun(opts: _99.ops.SearchOpts): _99.TraceID` | - |\n| `vibe` | `fun(opts?: _99.ops.Opts): _99.TraceID \\| nil` | - |\n| `open` | `fun(): nil` | - |\n| `visual` | `fun(opts: _99.ops.Opts): _99.TraceID` | - |\n| `view_logs` | `fun(): nil` | - |\n| `stop_all_requests` | `fun(): nil` | - |\n| `clear_previous_requests` | `fun(): nil` | - |\n| `Extensions` | `_99.Extensions` | - |\n\n### API\n\n#### setup\n设置 _99。必须调用此函数，库才能正常工作。通过它我们可以设置正在进行的请求加载动画、设定默认值，并使补全功能按你期望的方式运行。\n\n#### search\n根据你提供的提示，在你的项目中执行搜索，并返回一个包含注释的位置列表，这些位置将被添加到快速修复列表中。\n\n#### vibe\n无描述。\n\n#### open\n打开一个选择窗口，供你选择最近的一次交互进行打开，并以适合其类型的方式显示内容。对于 search 和 vibe，会打开 qfix 窗口；对于 tutorial，则会打开教程窗口。\n\n#### visual\n获取当前选中的内容并连同提供的提示一起发送，然后用结果替换当前的视觉选区。\n\n#### view_logs\n查看最近的日志，并配置机器以便查看更早和更新的日志。目前这部分还比较粗糙，未来会有较大改动。\n\n#### stop_all_requests\n停止所有正在进行的请求。这意味着底层进程（OpenCode）会被终止，任何已产生的结果都将被丢弃。\n\n#### clear_previous_requests\n清除所有之前的搜索和视觉操作记录。\n\n#### 扩展\n请查看 Worker，它为 search 和 vibe 提供了很酷的抽象层。\n\n## _99.Extensions.Worker\n一种持久化的工单跟踪方式。\n\n这很可能是未来开发的重点方向。我希望将其扩展到工作树的范畴，从而能够非常流畅地在不同任务之间切换。\n\n在此之前，它只是一个简单的工单系统：你可以提供任务描述，然后使用 search 来查找尚未完成的工作。\n\n### 描述\n| 名称 | 类型 | 默认值 |\n| --- | --- | --- |\n| `set_work` | `fun(opts?: _99.WorkOpts): nil` | - |\n| `search` | `fun(): nil` | - |\n\n### API\n\n#### set_work\n为项目设置工单。如果 opts 中提供了描述，则无需再次输入工单描述。\n\n#### search\n将使用 _99.search 来查找该工单中尚未完成的部分，直到工单被视为已完成。\n\n## _99.Options\n无描述。\n\n### 描述\n| 名称 | 类型 | 默认值 |\n| --- | --- | --- |\n| `logger` | `_99.Logger.Options \\| nil` | - |\n| `model` | `string \\| nil` | - |\n| `in_flight_options` | `_99.InFlight.Opts \\| nil` | - |\n| `md_files` | `string[] \\| nil` | - |\n| `provider` | `_99.Providers.BaseProvider \\| nil` | - |\n| `display_errors` | `boolean \\| nil` | - |\n| `auto_add_skills` | `boolean \\| nil` | - |\n| `completion` | `_99.Completion \\| nil` | - |\n| `tmp_dir` | `string \\| nil` | - |\n\n### API\n\n#### logger\n无描述。\n\n#### model\n无描述。\n\n#### in_flight_options\n无描述。\n\n#### md_files\n无描述。\n\n#### provider\n无描述。\n\n#### display_errors\n无描述。\n\n#### auto_add_skills\n无描述。\n\n#### completion\n无描述。\n\n#### tmp_dir\n无描述。\n\n## _99.ops.Opts\n这些选项用于与 99 进行的所有交互，包括 search、visual 等操作。\n\n### 描述\n| 名称 | 类型 | 默认值 |\n| --- | --- | --- |\n| `additional_prompt` | `string \\| nil` | - |\n| `additional_rules` | `_99.Agents.Rule[] \\| nil` | - |\n\n### API\n\n#### additional_prompt\n通过提供 `additional_prompt`，你就不需要再单独提供提示。这样可以根据 remap 定义不同的操作。\n\n```lua\nremap(\"n\", \"\u003Cleader>9d\", function()\n  --- 这个函数可以用来自动调试你的项目\n  _99.search({\n    additional_prompt = [[\n运行 `make test` 并调试测试失败的原因，然后向我提供一套完整的步骤，说明测试在哪里出错 ]]\n  })\nend)\n```\n\n这段代码会启动一个后台搜索任务，运行你的测试。一旦发现失败，就会进行诊断，并将结果转移到快速修复列表中。\n\n#### additional_rules\n可用于提供额外的参数。如果你有一个名为 “cloudflare” 的技能，就可以提供相应的规则，这些规则及其上下文将被注入到你的请求中。\n\n## _99.ops.SearchOpts\n更多信息请参阅 `_99.opts.Opts`。\n\n目前还没有具体属性。但我希望可以根据 opts 调整一些行为。\n\n### 描述\n| 名称 | 类型 | 默认值 |\n| --- | --- | --- |\n| - | - | - |\n\n### API\n无属性。\n\n## _99.WorkOpts\n无描述。\n\n### 描述\n| 名称 | 类型 | 默认值 |\n| --- | --- | --- |\n| `description` | `string \\| nil` | - |\n\n### API\n\n#### description\n无描述。\n\n## _99.Completion\n无描述。\n\n### 描述\n| 名称 | 类型 | 默认值 |\n| --- | --- | --- |\n| `source` | `\"cmp\" \\| \"blink\" \\| nil` | - |\n| `custom_rules` | `string[]` | - |\n| `files` | `_99.Files.Config?` | - |\n\n### API\n\n#### source\n无描述。\n\n#### custom_rules\n无描述。\n\n#### files\n无描述。\n\n## _99.InFlight.Opts\n这是一个纯粹用于测试的类，有助于控制时间间隔。\n\n### 描述\n| 名称 | 类型 | 默认值 |\n| --- | --- | --- |\n| `throbber_opts` | `_99.Throbber.Opts \\| nil` | - |\n| `in_flight_interval` | `number \\| nil` | - |\n| `enable` | `boolean \\| nil` | - |\n\n### API\n\n#### throbber_opts\n左上角加载动画的相关选项。\n\n#### in_flight_interval\n控制加载动画显示或隐藏的频率。\n\n#### enable\n默认为 true。\n\n## _99.Logger.Options\n无描述。\n\n### 描述\n| 名称 | 类型 | 默认值 |\n| --- | --- | --- |\n| `level` | `number?` | - |\n| `type` | `\"print\" \\| \"void\" \\| \"file\" \\| nil` | - |\n| `path` | `string?` | - |\n| `print_on_error` | `boolean \\| nil` | - |\n| `max_requests_cached` | `number \\| nil` | - |\n\n### API\n\n#### level\n无描述。\n\n#### type\n无描述。\n\n#### path\n无描述。\n\n#### print_on_error\n无描述。\n\n#### max_requests_cached\n无描述。\n\n## _99.Agents.Rule\n无描述。\n\n### 描述\n| 名称 | 类型 | 默认值 |\n| --- | --- | --- |\n| `name` | `string` | - |\n| `path` | `string` | - |\n| `absolute_path` | `string?` | - |\n\n### API\n\n#### name\n无描述。\n\n#### path\n无描述。\n\n#### absolute_path\n无描述。\n\n## 补全功能\n\n在输入提示时，你可以引用规则和文件来为你的请求增加上下文。\n\n- `#` 引用规则 — 在提示中输入 `#` 可以从你配置的规则目录中自动补全规则文件。\n- `@` 引用文件 — 输入 `@` 可以模糊搜索项目文件，但会排除 .gitignore 中列出的文件。\n\n引用的内容会自动解析并注入到 AI 上下文中。默认情况下使用原生补全功能。如果使用 nvim-cmp 或 blink.cmp，则需设置 `source = \"cmp\"` 或 `source = \"blink\"`。\n\n## 提供者\n99 支持多种 AI CLI 后端。在你的配置中设置 `provider` 即可切换。如果你没有设置 `model`，则会使用提供者的默认模型。\n\n| 提供者 | CLI 工具 | 默认模型 |\n|---|---|---|\n| `OpenCodeProvider`（默认） | `opencode` | `opencode\u002Fclaude-sonnet-4-5` |\n| `ClaudeCodeProvider` | `claude` | `claude-sonnet-4-5` |\n| `CursorAgentProvider` | `cursor-agent` | `sonnet-4.5` |\n| `GeminiCLIProvider` | `gemini` | `auto` |\n\n```lua\n_99.setup({\n    provider = _99.Providers.ClaudeCodeProvider,\n    -- model 是可选的，会覆盖提供者的默认值\n    model = \"claude-sonnet-4-5\",\n})\n```\n\n## 扩展\n\n### Telescope 模型选择器\n\n如果你安装了 [telescope.nvim](https:\u002F\u002Fgithub.com\u002Fnvim-telescope\u002Ftelescope.nvim)，可以通过 Telescope 选择器实时切换模型：\n\n```lua\nvim.keymap.set(\"n\", \"\u003Cleader>9m\", function()\n  require(\"99.extensions.telescope\").select_model()\nend)\n```\n\n所选模型将用于当前会话中的所有后续请求。\n\n### Telescope 提供者选择器\n\n无需重启 Neovim 即可在 OpenCode、Claude、Cursor 和 Kiro 之间切换提供者。切换提供者时，模型也会重置为该提供者的默认值。\n\n```lua\nvim.keymap.set(\"n\", \"\u003Cleader>9p\", function()\n  require(\"99.extensions.telescope\").select_provider()\nend)\n```\n\n### fzf-lua\n\n如果你使用 [fzf-lua](https:\u002F\u002Fgithub.com\u002Fibhagwan\u002Ffzf-lua) 而不是 telescope，同样可以使用这些选择器：\n\n```lua\nvim.keymap.set(\"n\", \"\u003Cleader>9m\", function()\n  require(\"99.extensions.fzf_lua\").select_model()\nend)\n\nvim.keymap.set(\"n\", \"\u003Cleader>9p\", function()\n  require(\"99.extensions.fzf_lua\").select_provider()\nend)\n```\n\n## 报告 bug\n\n要报告 bug，请提供完整的运行调试日志。这可能需要多次沟通确认。\n\n请勿提出功能需求。我们将在 Twitch 上公开讨论功能需求，这将比你单独提交大量请求后再被关闭要高效得多。如果你仍然提交功能请求，我将会立即关闭它。\n\n### 日志\n要查看上次运行的日志，请执行 `:lua require(\"99\").view_logs()`。\n\n### 请注意\n如果日志中包含敏感信息或其他需要删除的内容，请务必删除 `query` 的打印部分。这部分内容很可能包含你不希望公开的信息。","# 99 Neovim AI 助手快速上手指南\n\n99 是一款专为 Neovim 打造的 AI 客户端插件，旨在通过代理工作流（Agentic Workflow）增强开发者的编码能力，而非替代手写代码。它深度集成了搜索（Search）和视觉选择处理（Visual）功能，帮助开发者更高效地利用大语言模型。\n\n> **注意**：本项目目前处于 **Beta** 阶段，API 可能会发生变化。\n\n## 环境准备\n\n在开始之前，请确保满足以下要求：\n\n*   **Neovim**: 建议使用最新稳定版（v0.10+），需支持 `vim.uv` 和 `vim.fs`。\n*   **AI 后端依赖**: 99 本身是客户端，需要本地或远程运行支持的 AI 工具作为后端。目前主要支持：\n    *   [OpenCode](https:\u002F\u002Fopencode.ai\u002F) (默认)\n    *   [Claude Code](https:\u002F\u002Fcode.claude.com\u002F)\n    *   请根据官方文档安装并配置好相应的后端工具，确保其在终端中可正常运行。\n*   **Git**: 部分文件发现功能依赖 Git。\n\n## 安装步骤\n\n推荐使用 `lazy.nvim` 进行安装和管理。\n\n1.  在你的 Neovim 插件配置文件中（例如 `lua\u002Fplugins\u002F99.lua`），添加以下配置：\n\n```lua\n{\n    \"ThePrimeagen\u002F99\",\n    config = function()\n        local _99 = require(\"99\")\n\n        -- 获取当前项目目录名称用于日志命名\n        local cwd = vim.uv.cwd()\n        local basename = vim.fs.basename(cwd)\n\n        _99.setup({\n            -- 可选：指定 provider，默认为 OpenCodeProvider\n            -- provider = _99.Providers.ClaudeCodeProvider,\n\n            -- 日志配置（调试用）\n            logger = {\n                level = _99.DEBUG,\n                path = \"\u002Ftmp\u002F\" .. basename .. \".99.debug\",\n                print_on_error = true,\n            },\n\n            -- 临时目录配置\n            -- 注意：如果设置为 CWD 外部目录，OpenCode\u002FClaude Code 可能会有权限问题\n            tmp_dir = \".\u002Ftmp\",\n\n            -- 自动加载的上下文文件（如 AGENT.md）\n            md_files = {\n                \"AGENT.md\",\n            },\n\n            -- 补全功能配置\n            completion = {\n                -- 自定义技能规则路径 (SKILL.md)\n                custom_rules = {\n                  \"scratch\u002Fcustom_rules\u002F\",\n                },\n                -- 补全引擎来源: \"native\" (默认), \"cmp\", 或 \"blink\"\n                source = \"native\",\n                \n                -- 文件补全配置\n                files = {\n                    enabled = true,\n                    max_file_size = 102400, -- 跳过大于此字节数的文件\n                    exclude = { \".env\", \".env.*\", \"node_modules\", \".git\" },\n                },\n            },\n        })\n\n        -- 键位映射\n        \n        -- 可视模式下选中代码进行处理 (\u003Cleader>9v)\n        vim.keymap.set(\"v\", \"\u003Cleader>9v\", function()\n            _99.visual()\n        end)\n\n        -- 普通模式下停止所有正在进行的请求 (\u003Cleader>9x)\n        vim.keymap.set(\"n\", \"\u003Cleader>9x\", function()\n            _99.stop_all_requests()\n        end)\n\n        -- 普通模式下启动项目搜索 (\u003Cleader>9s) - 推荐核心功能\n        vim.keymap.set(\"n\", \"\u003Cleader>9s\", function()\n            _99.search()\n        end)\n    end,\n},\n```\n\n2.  保存配置并重启 Neovim，或执行 `:Lazy sync` 安装插件。\n3.  确保你的项目中已正确安装并初始化了后端的 AI 工具（如 `opencode` 或 `claude-code`）。\n\n## 基本使用\n\n99 的核心设计理念是通过 **搜索 (Search)** 来驱动开发工作流。\n\n### 1. 项目智能搜索 (`search`)\n这是最推荐的使用方式。它会基于你的提示词在整个项目中进行搜索、分析，并将结果（包含文件位置和修改建议）输出到快速修复列表（Quickfix List）中。\n\n*   **操作**: 在普通模式下按下 `\u003Cleader>9s`。\n*   **流程**:\n    1.  输入你的自然语言提示（例如：“查找所有未处理的错误”或“重构用户认证模块”）。\n    2.  99 调用后端 AI 分析项目。\n    3.  结果展示在 Quickfix 窗口，你可以直接跳转查看。\n\n**高级用法（预设提示词）**:\n你可以在按键映射中预设提示词，实现一键自动化任务：\n\n```lua\nvim.keymap.set(\"n\", \"\u003Cleader>9d\", function()\n  _99.search({\n    additional_prompt = [[\nrun `make test` and debug the test failures and provide me a comprehensive set of steps where\nthe tests are breaking ]]\n  })\nend)\n```\n\n### 2. 可视区域代码处理 (`visual`)\n对选中的代码块进行重构、解释或修改。\n\n*   **操作**:\n    1.  进入可视模式 (`v`, `V`, 或 `Ctrl+v`) 选中代码。\n    2.  按下 `\u003Cleader>9v`。\n    3.  输入指令（例如：“添加注释”或“优化性能”）。\n    4.  AI 生成的代码将直接替换选中的内容。\n\n### 3. 查看历史与日志\n*   **打开最近交互**: 使用 `_99.open()` 查看最近的搜索结果或教程窗口。\n*   **查看日志**: 使用 `_99.view_logs()` 调试插件运行状态。\n*   **停止任务**: 如果任务运行时间过长，按 `\u003Cleader>9x` 强制停止所有后台进程。\n\n### 4. 工作流管理 (Worker)\n99 提供了简单的任务追踪功能，可以设定一个工作目标，然后让 AI 搜索还需要完成哪些内容。\n\n```lua\n-- 设置当前工作任务描述\n_99.Extensions.Worker.set_work({ description = \"完成用户登录功能的 API 集成\" })\n\n-- 搜索该项目中还剩下什么没做\n_99.Extensions.Worker.search()\n```","一位资深后端工程师正在 Neovim 中重构一个遗留的 Python 微服务模块，需要理解复杂的调用链并安全地替换过时的异步逻辑。\n\n### 没有 99 时\n- **上下文切换频繁**：为了理清函数依赖关系，不得不频繁离开编辑器去查阅文档或在终端运行 grep 搜索，打断心流。\n- **手动整合困难**：从 AI 网页端复制代码片段后，需手动调整缩进和变量名以适应现有项目规范，容易引入格式错误。\n- **缺乏项目感知**：通用 AI 助手不了解项目特有的目录结构和自定义工具类，生成的代码往往无法直接运行，需要大量二次修改。\n- **调试成本高**：遇到生成代码报错时，需人工逐行比对差异，难以快速定位是逻辑错误还是环境权限问题。\n\n### 使用 99 后\n- **沉浸式代理工作流**：99 直接在 Neovim 内通过 `search` 和 `work` 命令分析整个代码库，自动梳理调用链并在缓冲区呈现结果，无需切换窗口。\n- **智能代码融合**：基于项目内的 `SKILL.md` 自定义规则，99 生成的代码自动符合团队规范，并利用 `@files` 补全功能精准引用相关模块。\n- **深度项目感知**：99 理解当前 Git 仓库结构及外部工具权限配置，生成的重构方案能直接调用项目内部的工具类，大幅减少适配工作。\n- **实时追踪与反馈**：内置的日志机制将请求追踪写入本地文件，出现错误时可立即回溯 Agent 的决策过程，快速修复权限或逻辑问题。\n\n99 将 AI 从“外部聊天机器人”转变为 Neovim 内的“结对编程代理”，在保留手写代码控制权的同时，极大提升了复杂重构任务的效率与准确性。","https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002FThePrimeagen_99_50eceb34.png","ThePrimeagen","https:\u002F\u002Foss.gittoolsai.com\u002Favatars\u002FThePrimeagen_5001ae1a.jpg",null,"CEO Of TheStartup","9th Ring, Vim","the.primeagen@gmail.com","http:\u002F\u002Ftwitch.tv\u002FThePrimeagen","https:\u002F\u002Fgithub.com\u002FThePrimeagen",[81,85,88,92,96,100],{"name":82,"color":83,"percentage":84},"Lua","#000080",96.8,{"name":86,"color":87,"percentage":32},"Tree-sitter Query","#8ea64c",{"name":89,"color":90,"percentage":91},"Shell","#89e051",0.5,{"name":93,"color":94,"percentage":95},"Vim Script","#199f4b",0.3,{"name":97,"color":98,"percentage":99},"Makefile","#427819",0.2,{"name":101,"color":102,"percentage":99},"TypeScript","#3178c6",4496,228,"2026-04-07T21:58:54","Linux, macOS, Windows","未说明",{"notes":109,"python":107,"dependencies":110},"该工具是 Neovim 的 Lua 插件，而非独立的 Python AI 模型。运行核心需求是安装 Neovim 编辑器。它本身不消耗大量本地算力，而是作为代理工作流客户端，调用外部的 AI 编码工具（如 OpenCode 或 Claude Code）来执行任务。因此，具体的 GPU、内存和 Python 环境需求取决于你所选择连接的后端 AI 服务或本地运行的外部工具，而非此插件本身。配置中涉及临时目录权限问题，需参考相关外部工具的文档进行设置。",[111,112,113],"Neovim","OpenCode (外部工具)","Claude Code (外部工具)",[13,52],"2026-03-27T02:49:30.150509","2026-04-08T17:32:15.281564",[118,123,128,133,137,142],{"id":119,"question_zh":120,"answer_zh":121,"source_url":122},24659,"为什么按下快捷键后没有弹出提示框，或者视觉选择功能不起作用？","默认情况下，插件不会自动绑定视觉选择（visual prompt）的快捷键。你需要手动在配置文件中添加键位映射。例如，在 Lua 配置中添加：\nvim.keymap.set(\"v\", \"\u003Cleader>9\", require(\"99\").visual, { desc = \"visual selection with prompt\" })\n其中 \"v\" 代表视觉模式，\"\u003Cleader>9\" 是你想要的快捷键。维护者明确表示倾向于让用户自行设置快捷键，因此文档中可能未包含此默认绑定。","https:\u002F\u002Fgithub.com\u002FThePrimeagen\u002F99\u002Fissues\u002F91",{"id":124,"question_zh":125,"answer_zh":126,"source_url":127},24660,"当 AI 返回空结果时，选中的代码被删除了怎么办？","这是一个已知问题，通常发生在本地模型（如 Ollama）未能正确触发文件写入工具而只输出了空内容时。维护者已确认将修复此行为：未来当没有收到输出时，插件将不再替换（删除）选中内容，而是打印一条消息提示“no output received, skipped”（未收到输出，已跳过）。在此之前，如果发生这种情况，请使用撤销操作恢复代码。","https:\u002F\u002Fgithub.com\u002FThePrimeagen\u002F99\u002Fissues\u002F122",{"id":129,"question_zh":130,"answer_zh":131,"source_url":132},24661,"99 插件是否会支持 LSP 协议或扩展到 Neovim 以外的编辑器？","目前不会。维护者明确表示该插件将仅限 Vim\u002FNeovim 使用，并且不会将其转换为 LSP 客户端。这是因为该项目是维护者的业余侧项目，时间有限，无法投入资源去开发通用的 LSP 客户端或支持其他编辑器。其设计初衷是利用 Vim 的原生 API 进行深度集成，而非通过标准的 LSP 协议。","https:\u002F\u002Fgithub.com\u002FThePrimeagen\u002F99\u002Fissues\u002F37",{"id":134,"question_zh":135,"answer_zh":136,"source_url":127},24662,"如何在 Windows 上配置 99 以避免路径错误或权限问题？","在 Windows 上使用 99（特别是配合 opencode 和 ollama 时）可能会遇到混合斜杠路径或权限问题。建议在配置中显式设置环境变量以允许编辑权限。例如，在 `99.lua` 的配置函数中加入：\nvim.fn.setenv(\"OPENCODE_PERMISSION\", '{\"edit\": \"allow\"}')\n此外，注意 Windows 路径分隔符可能导致某些工具解析失败，若遇到文件读取错误，请检查临时文件路径是否正确生成。",{"id":138,"question_zh":139,"answer_zh":140,"source_url":141},24663,"为什么插件在某些机器上完全无法工作（如函数填充功能无响应）？","如果日志显示请求已发送但无后续动作，可能是由于 Treesitter 解析失败或临时文件写入权限问题。首先确保已安装对应语言的 Treesitter 解析器。其次，检查 `\u002Ftmp` 目录（Linux\u002FMac）或临时文件夹（Windows）是否有写入权限。如果问题依旧，这可能与特定的 LLM 提供商配置有关，建议查看日志中是否有 \"failed to read file\" 或类似的错误信息，并尝试重启 Neovim 或更新插件到最新版本。","https:\u002F\u002Fgithub.com\u002FThePrimeagen\u002F99\u002Fissues\u002F59",{"id":143,"question_zh":144,"answer_zh":145,"source_url":127},24664,"99 插件的核心设计理念是什么？它主要擅长做什么？","根据维护者的反馈，99 插件最强大的功能是“搜索”（search）和代码导航，而不是单纯的代码生成。其设计理念是让用户在保持控制权的前提下，利用 AI 辅助修改特定代码块（如视觉选择区域或当前函数），而不是让 AI 接管整个项目。维护者更倾向于将其作为一个增强编辑体验的工具，而非全自动的代码编写机器人。",[]]