Init
将会话启动的文件夹转化为连接到此插件的 PARA 存储库,并保持其状态:第二次运行时补全缺失内容并迁移旧版方案。这是唯一会写入存储库配置的技能,也是在缺少配置时唯一能运行的技能。
写入内容
以下所有内容,除此之外不写入其他内容。REPO_ROOT、PARA_DIR、PARA_ROOT 的定义遵循 paths.md。
| 内容 | 位置 | 方式 |
|---|---|---|
| PARA 文件夹 | PARA_ROOT/ + Projects、Areas、Resources、Archive、Inbox、Templates | 仅在缺失时创建 |
| 笔记模板 | PARA_ROOT/Templates/ | 从插件播种,仅在缺失时(参见「Templates」) |
| 标识符日志 | PARA_ROOT/Archive/.removed-ids | 仅写入其头部,仅在缺失时(参见 project-id.md 中的「The journal」) |
| 存储库配置 | REPO_ROOT/.claude/para/vault.md、areas.md;adapter.md 仅在 TASKS 为 mcp 时 | 从 config.example/ 复制;从不覆盖 |
| 插件的块 | REPO_ROOT/CLAUDE.md | 仅在标记之间(参见「CLAUDE.md」) |
| 技能权限 | REPO_ROOT/.claude/settings.json | 合并,从不替换(参见「Settings」) |
| Obsidian 设置 | REPO_ROOT/.obsidian/app.json、templates.json | 合并(参见「Obsidian」) |
| 用户的笔记和文件夹(仅 B) | 从它们当前的位置移动到 PARA 文件夹 | 移动,从不编辑 — 仅执行已批准计划中列出的移动(参见「Scenario B」) |
| 项目概览(仅 B) | PARA_ROOT/Projects/PROJ-xxxx <title>/ | 新创建,针对用户称为项目的文件夹(参见「Scenario B」) |
| 概览中的配对键(仅 C) | PARA_ROOT/Projects/、PARA_ROOT/Archive/ | 仅重命名一个 frontmatter 键,其他不变(参见 scenario-c.md) |
| 存储库的规划文件(仅 C) | REPO_ROOT/.claude/local/planning.md | 新创建,从旧工具提升而来(参见 scenario-c.md) |
| 旧的内嵌工具(仅 C) | REPO_ROOT/.claude/、CLAUDE.md、旧模板的文档 | 移至 macOS 废纸篓,第 2 级(参见 scenario-c.md) |
基础层
在执行前阅读,每个文件相对于本技能的基础目录(同样适用于 ../../config.example/、../../lang/、../../templates/):
../../para/paths.md— 始终需要:两个根目录、「Language」、用于TASKS的适配器。init写入的所有内容都必须与其一致。../../para/tasks.md— 操作、「Pairing」、「Backend missing」../../para/adapters/mcp-generic.md— 当TASKS为mcp时;其他值的适配器由paths.md命名../../para/note-format.md— 模板必须匹配的 frontmatter 方案../../para/migrations.md— 插件当前的SCHEMA以及迁移的运行方式../../para/claude-md-block.md— 用于CLAUDE.md的块../../para/confirm.md— 层级;下面的计划是init满足它们的方式../../para/project-id.md— 「The journal」:标识符日志的头部(第 5.1 步)../../config.example/vault.md、areas.md、adapter.md— 配置的形状- 仅情景 B:
../../para/move.md(移动如何保持链接)、project-id.md(颁发标识符)、../../para/thresholds.md(区域陈旧阈值和「The limit of mtime」)、paths.md中的「IGNORE」 ../../lang/<LANG>.md(一旦LANG已知):init.*字符串- 仅情景 C 以及 C 的剩余内容在重新运行时:
scenario-c.md位于本技能的基础目录中 — 关于旧布局的所有内容;以及../../para/move.md(废纸篓)
下面的 SKILL_DIR 是本技能的基础目录,由工具框架声明。
整个运行的规则
REPO_ROOT是会话的工作目录,作为绝对路径(pwd)。这是插件从工作目录获取根的唯一点:init将其写入以供其他所有技能使用。计划中会说明是哪个文件夹,以便在写入任何内容前捕获在错误位置启动的会话。- 在计划的「是」之前不写入任何内容。 检查、询问和探测任务后端都是只读操作。
vault.md最后写入。 它标志着存储库已设置完成;中断的运行不会留下vault.md,下次运行会重新开始,但会发现已经完成的工作。- 每个步骤都是幂等的:在缺失时创建,在存在时合并,从不覆盖。连续运行
init两次,第二次不会改变任何内容。 - 引用每个路径(
paths.md中的「Rules」)。REPO_ROOT可能包含空格。 - 语言。 在选择
LANG之前,使用用户输入的语言(如果没有输入,则使用英语 — 例如裸的/para:init)。之后,所有内容都使用LANG,遵循paths.md中的「Language」,包括剩余的问题;计划和报告标题使用init.*字符串。
预先给出的答案
$ARGUMENTS 可能已经包含答案:语言、PARA_DIR(「默认」表示建议的值)、任务后端、Areas 模型、情景 B 中的排序答案(按文件夹或根笔记,以及重复名称的处理)、快照答案以及对计划的批准。接受每个已给出的答案,不要再次询问;只询问缺失的内容。答案不是有效选项时,会说明原因并再次询问。
预先给出的批准意味着:显示计划,然后立即应用,无需等待 — 但仅在计划的每一行都添加新内容(文件夹、文件、键、条目)时适用。任何一行包含更改或替换现有内容(不同的 Obsidian 值、不同的 CLAUDE.md 块、迁移中的模板、现有 vault.md 中的 REPO_ROOT)都属于第 2 级(confirm.md):需要显示计划,并且即使有预先批准,init 也会等待「是」。
情景 B 的移动分为两种,这是关于预先批准如何覆盖它们的唯一声明。用户在自身答案中决定的移动(B3,或 $ARGUMENTS 中的排序答案)改变了笔记的位置,但从不改变其内容,并且 confirm.md 将移动归为第 1 级:计划的「是」(无论是当时给出还是预先给出)都覆盖它。仅由规则决定的移动(B2:移至 Archive/ 或 Resources/)是 init 对用户笔记的判断:需要用户对显示该移动的计划实时说「是」,即使预先给出了批准。无论哪种情况,都会在移动前提供快照(第 4 步)。预先回答的排序问题不再询问;未回答的会询问,在得到答案之前不会应用任何内容,无论是否有批准。
第 1 步 — 检查
只读。确定文件夹是什么并命名情景。
REPO_ROOT=$(pwd)
ls -A "$REPO_ROOT"
ls "$REPO_ROOT/.claude" "$REPO_ROOT/.claude/para" "$REPO_ROOT/.claude/skills" 2>/dev/null
# 旧的内嵌布局(情景 C):其配置文件夹或基础层
ls -d "$REPO_ROOT/.claude/para/local" "$REPO_ROOT/.claude/para/paths.md" 2>/dev/null # 旧布局
# 与旧内嵌技能同名的技能文件夹:仅报告,本身不构成情景 C
for s in inbox projects areas resources archive remove vault-lint; do
[ -f "$REPO_ROOT/.claude/skills/$s/SKILL.md" ] && echo "旧技能:$s"; done
# 笔记:所有不在 REPO_ROOT 点条目下的 .md 文件,排除存储库自身的文件和模板
#(相对于 REPO_ROOT 剪除点条目,因此位于点目录下的存储库仍然可见)
find "$REPO_ROOT" -mindepth 1 -name '.*' -prune -o -name "*.md" -not -path "*/Templates/*" \
! -path "$REPO_ROOT/CLAUDE.md" ! -path "$REPO_ROOT/README.md" ! -path "$REPO_ROOT/CHANGELOG.md" -print | head -50
# 此文件夹上方的存储库:init 在子文件夹中启动
d=$(dirname "$REPO_ROOT")
while [ "$d" != "/" ] && [ "$d" != "$HOME" ]; do
{ [ -e "$d/.claude/para/vault.md" ] || [ -d "$d/.obsidian" ]; } && echo "上方的存储库:$d"
d=$(dirname "$d")
done
在进行任何操作前,如果以下情况则停止:
REPO_ROOT是$HOME或/— 不是存储库;说明情况。- 在上方发现存储库 — 说「从
<那个文件夹>运行/para:init」并停止;绝不在另一个存储库内部设置存储库。
然后按此顺序决定并说明发现的内容和是哪种情况:
- 设置完成 —
.claude/para/vault.md存在 → «重新运行和迁移» 以下。 - 情景 C — 旧的内嵌工具,通过其旧的基础层或仅配置识别(上面的
old-layout行):其配置文件夹local/或.claude/para/内的基础层文件paths.md。→ «情景 C»。 一个与旧技能同名的技能文件夹(旧技能:行)但缺少上述两种情况之一,不是 C:根据以下规则进入 B 或 A。说明找到的是哪个文件夹,并且init将保持不动;计划的「不执行」部分会再次指出它。 一个仅包含此插件的配置文件(areas.md、adapter.md)且没有vault.md的.claude/para/目录不是 C:这是init首次运行但在写入vault.md前被中断或拒绝。按照以下 B 或 A 规则继续,就好像它不存在一样,但那些文件是存储库的配置 — 绝不覆盖 — 并且它们已回答的问题(关于areas.md的问题 4)不再询问。运行将补全其余部分。 - 情景 B — 找到了笔记(上面的
find输出了内容)。→ «情景 B»。 - 情景 A — 否则:空文件夹,或仅包含非笔记文件(新 Obsidian 存储库的
.obsidian/、CLAUDE.md)。→ 第 2 步。
第 2 步 — 问题
逐个询问,按此顺序,跳过预先回答的问题。每个问题显示其选项,如果有默认值也显示。
-
语言 (
LANG)。选项是插件附带的语言:一个代码,同时存在lang/<code>.md和templates/<code>/(paths.md中的「Language」):for f in "$SKILL_DIR"/../../lang/*.md; do l=$(basename "$f" .md) [ -d "$SKILL_DIR/../../templates/$l" ] && echo "$l"; done -
PARA 文件夹 (
PARA_DIR)。每个情景的默认值:A —PARA,一个子文件夹,以便工具和笔记分离;B —.,以便 PARA 文件夹置于用户自有文件夹旁边,除非「情景 B」另有说明。.将 PARA 文件夹直接放入REPO_ROOT。有效值:.或一个文件夹名称 — 不包含/,不以.开头,不是 PARA 文件夹名称本身。 -
任务后端 (
TASKS)。选项是todoist、files或mcp;推荐第一个。用一句话说明每个的含义:应用程序的收件箱和项目;存储库中的任务笔记,无需应用程序;通过 MCP 连接的任何其他待办事项应用。然后探测 — «探测后端» 以下。探测失败的值永远不会被记录。 -
Areas 模型 (
areas.md)。一个问题:Areas 是否分组 —none,或组名(例如 Work、Home)?其他所有内容都派生并在计划中显示,用户可以在其中更改:键 分组 noneGROUPING字段名, sphere,除非用户命名了一个(种子模板的键)noneGROUPS给出的名称 空 PLACEMENTAreas/<GROUP>/<title>.mdAreas/<title>.mdREVIEW_GROUPING每个组一个块,报告内容为空的组被删除 一个平面列表 PLACEMENT_CHECK笔记的 GROUPING字段必须命名其所在的顶级文件夹noneAREA_TASK_PROJECTSGROUPS的名称一个名称: areas.review.heading字符串
探测后端
探测是 inbox.list,根据所选值的适配器运行(paths.md)。它是只读的;收件箱为空也算成功。仅打印计数,绝不打印内容。
files— 无需探测:适配器是磁盘,并且不可能出现「Backend missing」(tasks.md)。mcp— 立即运行adapters/mcp-generic.md的第 1–6 步。第 1 步未找到工具则探测失败。当用户同意且应用程序有收件箱时,第 6 步是探测;否则计划说明映射未验证。第 7–8 步属于计划和下面的「第 5 步」。- 任何其他值 — 通过其适配器运行
inbox.list。如果适配器的工具不在本次会话中,或调用失败:用一句话说明原因(tasks.md中的「Backend missing」),不记录该值,并改为提供files— 或连接应用程序后重新运行/para:init。绝不为探测失败的TASKS值写入记录,也绝不在许诺稍后切换的情况下记录一个值。
第 3 步 — 计划
一个包含所有内容的列表,包括将要创建、合并或更改的每项内容,以 init.plan.heading 字符串为标题。它是用户可以编辑的提案,而非通知:编辑会生成新计划并再次显示。它以 init.plan.approve 字符串结束,在用户说「是」(或在「预先给出的答案」设定的限制内给出预先批准)之前不应用任何内容。
计划按此顺序列出:
REPO_ROOT(此文件夹)和PARA_ROOT。- 要创建的文件夹,以及缺失时的标识符日志。
- 要复制的模板,每个模板附带「Templates」对其所做的更改。在情景 B 中,这里还包括:移动、项目、
IGNORE、保留的重复项以及将断开的链接(「情景 B」、「计划的 B 部分」)。 - 配置:
vault.md和areas.md的每个键及其值;对于mcp,适配器表(mcp-generic.md第 7 步 — 计划的「是」就是该表的「是」)。 CLAUDE.md、.claude/settings.json、.obsidian/app.json、.obsidian/templates.json:每个要添加的内容。每个将要更改的现有值都作为单独的一行,显示旧值和新值。- 探测结果:后端已响应(含收件箱计数),或
files。 - 不执行的内容及其原因(模板已存在、值已保留等)。
第 4 步 — 快照(仅 B 和 C)
在应用会影响现有存储库的计划之前,提供一份 zip 副本放在其旁边 — 始终会询问,拒绝会被接受,接受的预先答案会被采用。它在与计划批准的同一消息中询问(init.snapshot 字符串),因此用户一次性回答:
zip_path="$(dirname "$REPO_ROOT")/$(basename "$REPO_ROOT")-backup-$(date +%Y-%m-%d).zip"
ditto -c -k --keepParent "$REPO_ROOT" "$zip_path"
情景 A 没有需要保存的内容,因此跳过此步。
...(内容因翻译限制而截断)