只管往里扔。它替你消化,并催你复习。
AI First 的学习伴侣:收集(资料)→ 消化(卡片)→ 复盘(复习)。
你负责扔进去;Agent 负责切卡、出题、排每日队列、维护知识地图。
inwit.aimo.plus · 理念 · 截图 · Agent · 快速开始 · 编码 Agent · 贡献
Inwit 是 AI First,同时追求 纸上学习。打开后先看到今天该回忆什么,而不是文件夹和标签;Agent 在后台切卡、出题、画地图,提议开题要你点头才落地。
学习收成四个动作,不多不少:输入 → 消化 → 记住 → 贯通。
- 一个闭环,而不是一堆工具。 笔记、问号、截图先丢进资料;消化 Agent 切成原子卡片并出题;复习按遗忘曲线推到今天的队列;三档反馈再驱动换讲法、拆卡和周报。编码 Agent 也可以当投喂口,但不另起一套笔记。
- 你只做输入。 不要求分类、打标签、选文件夹。主题不是文件夹,是 Agent 替你维护的知识地图;空白节点可以让 AI 补一张入门卡。
- 回忆必须是你自己的。 切卡和出题可以交给模型;翻面之前先想,三档反馈才写进 SM-2。偷看作对,下次只会隔得更远。
- 基础层不依赖 AI。 卡片 + 间隔重复在没有模型时也能跑。AI 只做增强:换讲法、拆小、对比专题、周报。密钥按需配置(BYOK),用量在任务页可见。
视觉主题为 纸上学习:宣纸底、暖墨字、朱批红。浅色是白日书桌,深色是灯下夜读。docs/design-system.md 是 v1 历史基线,不是现行样式。
| 他们在做的 | Inwit 在做的 | |
|---|---|---|
| Notion / Obsidian | 打开驱动,手动整理 | 输入驱动,Agent 整理 |
| Anki | 手动制卡,机械重复 | AI 制卡,推送驱动的复习闭环 |
| 聊天机器人 | 回答完就散 | 回答落成卡片,进入复习队列 |
| 编码 Agent 自己记笔记 | 再做一个第二大脑 | 只负责投喂,消化和复习仍在 Inwit |
主题不是文件夹。资料按时间流入主题或未归属池;Agent 维护一张概念大纲树。空白节点可以让 AI 补——这是复习之外的第二个学习驱动。
一篇文章和它的脑图放在一起读。章节是文本节点,下面挂能点回原文的划线,再挂从这些句子挖出的卡片。点划线,正文滚到那一句;点卡片,能看到概念和复习间隔。
黄底是卡片锚点,下划线是划线。右侧脑图按章节展开。
禅模式收起导航和文档列表,只留正文和脑图。选中一个节点时,对应的句子留在视口里,其余分支让开。
在对话里 @ 这篇文档,让 Agent 按章节搭脑图:划线必须是原文里的句子,卡片归进对应的章。写入之后,脑图和这一轮的结果都留在页面上。
复习把同一句再问一遍。正面挖掉关键词,翻开后是原文里的那一句,再按忘了、模糊、想起来了打分。间隔由这次结果决定。
这几篇资料收在同一个主题里。图谱按概念分栏:已经有卡片的标成已覆盖,还只有资料的节点可以让 AI 补。
Inwit 把 Agent 当成产品的一部分,而不是外挂聊天窗。配置好模型(设置 → 模型配置,用户 BYOK;系统可走百炼兜底)之后,后台 Agent 持续工作:
| 能力 | 做什么 | 何时跑 |
|---|---|---|
| 消化 | 把长内容切成原子卡片(概念 + 例子 + 易混点),出题,挂到知识地图 | 资料入库后 |
| 问答 | 直接提问,中文回答落成文档,并自动转卡片 | 以问号结尾发送 |
| 对话 | 对着当前文档搭脑图:拆章节、划线点回原句、把卡片归进对应的章 | 你在对话里 @ 这篇文档 |
| 主题 | 整理 / 补全知识地图,未归属资料聚成一类时提议开题 | 你点「整理地图」,或后台建议 |
| 进化 | 反复忘的换讲法、拆小、出混淆对比 | 复习反馈触发 |
| 周报 | 回忆成功率、建议重学的概念 | 按周自动 |
| 提取 / 识别 | 从原件抽文本,识别扫描页 | 导入 PDF 等 |
切卡会直接写入,开题要你点头。三档反馈(忘了 / 模糊 / 想起来了)才改间隔。对话里对脑图的修改记在这篇文档的历史里,可以自行恢复。任务页能看见 Agent 在跑什么、失败了什么、用了多少 token。
你在用的编码 Agent(Claude、Codex、Cursor……)也可以接入同一份数据:投喂笔记、提问制卡、看今日队列——装一个 skill 即可,见 编码 Agent。对内 Agent 和对外 skill 操作的是同一份数据:你在网页里扔的,Claude 看得到;Claude 投喂的笔记,首页和文档列表立刻出现。
四个实体,对应四个动作:
| 实体 | 动作 | 说明 |
|---|---|---|
| 资料(Document) | 输入 | 课件、草稿、剪藏、截图、AI 回答。全部是文档 |
| 卡片(Card) | 消化 | 原子知识:一条概念 + 一个例子 + 一个易混点,带出处锚点 |
| 主题(Topic) | 贯通的方向 | 你给自己开的一门课:有目标、有资料、有卡片、有知识地图 |
| 关联(Link) | 贯通的结构 | 卡片↔卡片、卡片↔资料(锚点)、资料/卡片↔主题(归属) |
复习不是实体,是卡片上的 SM-2 状态。未归属的资料可以由消化 Agent 软归属,你只有确认权,没有整理义务。
直接使用托管版:inwit.aimo.plus。要自己部署,需要 Node 22+ 和 pnpm 10,数据库与检索的连接写在 apps/server/.env(不入库,清单见环境变量)。
pnpm install
pnpm --filter @inwit/server migrate
pnpm dev # server :3020 + web :5190
pnpm --filter @inwit/server worker # 另开一个终端:消化 / 问答 / 进化 / 周报浏览器打开 http://localhost:5190。没有 worker,文档会停在「消化中…」。
需要 Rust 与系统 WebView:
pnpm --filter @inwit/desktop dev # 打开 http://localhost:5190,会话走 cookie生产安装包的窗口打开 https://inwit.aimo.plus,不再内嵌一份前端。
macOS 点红灯会藏到菜单栏,并不退出;「退出 Inwit」才退出。全局快捷键 ⌘⇧2 / Ctrl+Shift+2 区域截图(macOS 需「屏幕录制」权限)。
Android APK 把 EXPO_PUBLIC_API_BASE_URL(以及 Expo extra.apiBaseUrl)打进客户端。由仓库变量 / workflow 输入 INWIT_API_URL 注入,默认 https://inwit.aimo.plus。桌面壳不再烘焙 VITE_TAURI_API_URL,页面地址是 tauri.conf.json 的 frontendDist。
GitHub Release 打 v*.*.* tag 后,Actions「Build Desktop and Android」会把 macOS / Windows / Linux 安装包和 Android APK 挂到该 Release。Server 镜像推 ghcr.io/ximing/inwit-server(同一镜像 node dist/worker.js 跑 worker)。
docker compose -f docker-compose.prod.yml run --rm migrate
docker compose -f docker-compose.prod.yml up -d生产 compose 需 .env,见 .env.production.example。
Inwit 在 skills/ 下内置 Agent Skills,教编程 Agent 通过 HTTP API 操作同一份数据。技能本体是纯 SKILL.md(外加按域拆开的 references/),同一份文件适用于各编程工具。安装方式因工具而异——多个工具同时使用时,需要分别为每个工具安装。
外部 Agent 只负责投喂和读取:把笔记、问号送进来,看今天的队列。消化、SM-2、知识地图仍在服务端跑。Skill 里写好的典型工作流:投喂笔记(POST /api/open/documents)、提问并制卡(POST /api/chat,问题以 ? / ? 结尾)、今日复习(GET /api/review/today + 反馈)、任务进度(GET /api/jobs/queue)。
先在 Inwit 设置 → 接口令牌 创建令牌(前缀 iwt_,明文只显示一次,可随时撤销),写入环境变量,不要贴进对话或仓库:
export INWIT_TOKEN='iwt_…'
export INWIT_BASE_URL='https://inwit.aimo.plus' # 本地可省略,默认 http://localhost:3020插件清单的布局与 CSI 相同(.claude-plugin / .codex-plugin / .cursor-plugin 等)。装过一个再装另一个,各自装一次。
/plugin marketplace add ximing/inwit
/plugin install inwit@inwit或:cp -r skills/inwit ~/.claude/skills/
本仓库同时是 Codex plugin marketplace(.agents/plugins/marketplace.json):
codex plugin marketplace add ximing/inwit
codex plugin add inwit@inwit清单在 .cursor-plugin/plugin.json。在 Cursor Agent 对话里执行 /add-plugin inwit,或把 skills/inwit 拷进项目的 .cursor/skills/。
从 ximing/grok-plugins 安装。skills/** 或插件清单有变更时,GitHub Actions 会把这份 skill 同步过去:
grok plugin marketplace add ximing/grok-plugins
grok plugin install inwit --trust或手动:cp -r skills/inwit ~/.grok/skills/。调用:/inwit。
/plugins install https://github.com/ximing/inwit
然后 /new 开一个新会话,让插件加载。
在 opencode.json(全局或项目)里注册 skills/:
{
"plugin": ["inwit@git+https://github.com/ximing/inwit.git"]
}pi install git:github.com/ximing/inwit根目录 package.json 的 pi.skills 指向 ./skills。
装好后对 Agent 说「投喂这段笔记到 Inwit」或「今日复习」即可。约定与模块索引见 skills/inwit/SKILL.md。接口目录按模块拆在 skills/inwit/references/,Agent 只应打开当前意图对应的那一个 md。
| 路径 | 页面 |
|---|---|
/ |
首页(Today):今日复习、捕捉、连续天数 |
/login |
登录 / 注册 |
/docs |
文档工作台(?doc= 打开,&edit=1 编辑,&anchor= 滚到卡片锚点) |
/review |
复习中心(Hub + SM-2 设置 + 翻卡;?tab=reports 为周报) |
/topics |
学习主题 |
/topics?topic=:id |
主题详情(知识地图 + 资料流) |
/jobs |
任务与用量 |
/settings |
外观、BYOK 模型、接口令牌 |
旧路径由前端跳到新地址,书签不用改:/doc/:id → /docs?doc=,/editor/:id → &edit=1,/card/:id → /review,/admin → /jobs。
服务端优先。Web / 桌面 / 移动共用同一套 API 与 DTO。
┌─────────────────────────────────────────────────────────┐
│ 客户端 │
│ Web (Vite + React 19 + @rabjs/react) │
│ 桌面 (Tauri 2,系统截图 / OCR) │
│ 移动 (Expo / React Native) │
├─────────────────────────────────────────────────────────┤
│ 服务端 Fastify 5 + drizzle-orm │
│ 认证 · BYOK 模型 · 文档 inbox · 复习队列 · 任务与用量 │
├─────────────────────────────────────────────────────────┤
│ Agent 层(全部收敛于 pi-agent-core,不在体系外直调 LLM) │
│ 消化 扫描 inbox → 切卡 → 出题 → 挂地图 │
│ 问答 直接提问 → 中文回答 → 自动转卡片 │
│ 主题 整理知识地图 / 补空白 / 提议开题 │
│ 进化 换讲法 / 拆卡 / 混淆对比 / 周报复盘 │
│ LLM @earendil-works/pi-ai,对话和消化用用户自己的模型 │
├─────────────────────────────────────────────────────────┤
│ 数据 │
│ PostgreSQL 业务数据 + 任务队列 │
│ Qdrant 向量召回(2560 维) │
│ Meilisearch 中文稀疏召回 │
│ 百炼 embedding + rerank │
│ S3 附件(客户端只拿预签名 URL,不持有密钥) │
└─────────────────────────────────────────────────────────┘
检索是混合召回:Qdrant 语义 + Meili 关键词 → RRF 融合 → rerank。所有查询按 userId 隔离。
Agent 跑在独立 worker 进程里,状态不在进程内存:领取、超时回收、失败重试都落在 PostgreSQL,进程重启也能接着跑。
pnpm monorepo,全 ESM(相对导入带 .js 后缀,tsconfig 为 NodeNext):
inwit/
├── apps/server Fastify + drizzle + worker(:3020)
├── apps/web Vite + React + @rabjs/react(:5190,/api 代理到 3020)
├── apps/desktop Tauri 2 桌面壳
├── apps/mobile Expo / React Native
├── packages/dto 前后端共享 zod schema(API 契约的唯一来源)
├── packages/doc-schema / doc-engine / markdown
├── packages/brand App 图标源(改 logo.svg 后 raster-icons)
├── skills/inwit 给外部编码 Agent 的 skill(HTTP 投喂 / 复习)
└── docs/ PRD、设计稿、任务与开发日志
写在 apps/server/.env。config.ts 用 zod 校验,缺项会拒绝启动。测试环境只读 apps/server/.env.test,不回落开发 .env。
| 变量 | 说明 |
|---|---|
NODE_ENV |
development / test / production |
PORT |
HTTP 端口,默认 3020 |
WEB_ORIGIN |
CORS 与 cookie 用的前端源,默认 http://localhost:5190 |
PG_HOST PG_PORT PG_USER PG_PASSWORD PG_DATABASE PG_SSL |
PostgreSQL |
JWT_SECRET / COOKIE_SECRET |
至少 32 字符 |
LLM_KEY_ENCRYPTION_KEY |
32 字节 hex,加密用户 BYOK key |
QDRANT_URL QDRANT_API_KEY |
向量库 |
MEILI_HOST MEILI_API_KEY |
中文稀疏检索 |
DASHSCOPE_API_KEY |
百炼:embedding 与 rerank。对话和消化必须使用用户自己的模型配置 |
EMBEDDING_MODEL / EMBEDDING_DIMENSIONS |
默认 qwen3-vl-embedding / 2560 |
RERANK_MODEL |
默认 qwen3.7-text-rerank |
WORKER_POLL_MS WORKER_CLAIM_LIMIT WORKER_STUCK_MS JOB_MAX_ATTEMPTS |
队列 |
DIGEST_CARD_GATE |
默认 false,仓库里不设。仅当带确认按钮的 mobile 构建已是用户正在运行的版本、且 web 已部署后,才在部署环境写成字符串 true,并同时重启 server 与 worker。此后新消化卡保持 proposed,直到用户接受。 |
附件走远端 S3,服务端签发预签名 URL;客户端不持有存储密钥,DB 只存对象 key。需要的变量见 ATTACHMENT_S3_*(.env.production.example 有完整清单)。Bucket CORS 需允许前端来源的 GET、PUT、HEAD,并暴露 ETag。
欢迎 issue 和 pull request。较大的行为变更,请先开 issue 对齐,再动手。
-
Fork,从
master拉功能分支。 -
pnpm install后按「快速开始」把 web + server + worker 跑起来。 -
提交前至少:
pnpm typecheck pnpm --filter @inwit/server test pnpm --filter @inwit/web build
约定(完整版在仓库根目录 CLAUDE.md):
- API 契约只出在
@inwit/dto。先改 zod schema,再改 server / web。 - Schema 变更走 drizzle(
schema.ts→migrate:generate→migrate),不手改数据库。 - Agent 可测逻辑放
*-logic.ts,编排和 IO 放旁边的模块;后端测试不连真实数据库。 - 前端一页一个 Service(
@rabjs/react),不要另引状态库。文案中文,语气克制书面。不要用window.alert/prompt/confirm,走全局 DialogService。 - 样式按功能就近:页面 CSS 放
apps/web/src/pages/<功能>/,不要往全局styles.css堆业务规则。新 CSS 必须在style-entry.css登记。 - 图片与文件只走服务端预签名 URL。
- 发版前先升级
apps/web/package.json的version(semver),Vite 构建时打进前端常量;不要在 UI 里手写版本号。
设计稿在 docs/design/v2/(先看目录索引;稿与稿冲突时以实现中的样式为准)。docs/prd.md 与 docs/design-system.md 是历史基线,不是现行需求。
| 文档 | 内容 |
|---|---|
| docs/prd.md | 历史基线:早期产品需求与概念模型,不是现行需求 |
| docs/design-system.md | 历史基线:v1「纸上学习」设计系统,不是现行样式 |
| docs/design/v2/ | UI 设计稿。同页多稿冲突时以实现中的样式为准,见目录索引 |
| skills/inwit/SKILL.md | 给外部编码 Agent:HTTP 投喂与复习 |
| CLAUDE.md | 给在本仓库里改代码的代理 |
| docs/dev-log.md | 开发日志 |
| docs/tasks/ | 历史任务与报告 |
AGPL-3.0。个人学习、阅读和提 PR 欢迎;基于源码的二次分发或网络服务需遵守 AGPL-3.0 开源义务,商用授权请开 issue 与维护者沟通。




