PlainDeck Agent API 与 CLI

August 27, 2026 · View on GitHub

PlainDeck v0.6.0 面向 Agent 的推荐工作流是:

init → inspect → operations → validate → dry-run → apply → render

项目格式版本仍为 schemaVersion: "0.1"。运行环境要求 Node.js 22 或更高版本。

CLI

plaindeck init <project> [--title <title>] [--template showcase|pitch|blank|paper-reading|nature-methods|flowchart] [--theme <id>] [--json]
plaindeck validate <project> [--json]
plaindeck inspect <project> [--json]
plaindeck apply <project> --ops <file|-> [--dry-run] [--json]
plaindeck add-slide <project> --layout <id> [--name <name>]
plaindeck add-cards <project> --content <file|-> [--style <id>] [--name <name>] [--after <slide-path>]
plaindeck add-table <project> --data <file|-> [--style rules|grid|stripes] [--title <title>] [--name <name>] [--after <slide-path>]
plaindeck styles [--search <query>] [--json]
plaindeck render <project> --format html|png|pdf --output <path> [--slide <index|path>] [--allow-network]

init 让 Agent 无需先编写 TypeScript 即可创建完整项目。默认仍生成五页 showcasestudio-cobalt,以保留已有 CLI 契约;nature-methodspaper-reading 默认使用 nature-editorial。创建前会检查所有计划文件,发生冲突时以退出码 2 停止且不写入。

--json 时 stdout 只包含 JSON,错误诊断写入 stderr。成功退出码为 0,校验或执行失败为 1,参数错误为 2apply --dry-run 会返回 changedPaths 与 validation 结果,但不会写入文件。

operations 也可以从 stdin 读取:

printf '[{"op":"rename-slide","slide":"./slides/001-intro.json","name":"Introduction"}]' \
  | plaindeck apply ./my-deck --ops - --dry-run --json

add-cards 接受 Markdown 或 JSON,把 1–8 个结构化要点转换为一张自适应卡片页。它不调用远程模型;Agent 可以先在会话中整理内容,再通过 stdin 写入项目:

cat brief.md | plaindeck add-cards ./my-deck --content - --name "Weekly brief" --json
plaindeck styles --search "水墨"
cat brief.md | plaindeck add-cards ./my-deck --content - --style inkLandscape

Markdown 使用 # 主标题## 卡片标题、描述和可选的 icon_name;兼容 { "mainTitle", "cards": [{ "title", "desc", "icon" }] } 形式的 Juya News Card JSON。styles 提供 174 个由 Juya 模板批量迁移的原生设计配方;它们归入 27 个分类和 10 类构图语法,颜色、字体、边框、圆角与装饰最终都转换为 PlainDeck 元素。生成后每张卡的背景、编号、标题和正文都可以继续在 Web 画布拖动和编辑。

add-table 接受 Markdown pipe table、CSV、TSV、二维 JSON 数组、对象数组,或 { "title", "columns", "rows" }。第一行是表头;建议不超过 8 列、12 个数据行。rules 是默认的学术表格样式,grid 适合参数矩阵,stripes 适合逐行比较。

Operations

所有操作使用页面路径和元素 ID,不使用数组索引。

[
  {
    "op": "set-element",
    "slide": "./slides/001-intro.json",
    "element": "title",
    "patch": {
      "text": "New title",
      "frame": { "x": 96 },
      "animation": { "enter": "fade-up", "delayFrames": 12, "durationFrames": 20 }
    }
  },
  {
    "op": "add-element",
    "slide": "./slides/001-intro.json",
    "element": {
      "id": "agent-note",
      "type": "text",
      "frame": { "x": 96, "y": 220, "w": 600, "h": 80 },
      "text": "Generated by an Agent",
      "fontSize": 28,
      "color": "#171714",
      "align": "left"
    }
  },
  { "op": "remove-element", "slide": "./slides/001-intro.json", "element": "old-note" },
  { "op": "move-element", "slide": "./slides/001-intro.json", "element": "agent-note", "before": "title" },
  { "op": "add-slide", "layout": "image-right", "name": "Results", "after": "./slides/001-intro.json" },
  {
    "op": "add-summary-slide",
    "name": "Weekly brief",
    "content": {
      "title": "本周关键进展",
      "cards": [
        { "title": "能力", "description": "模型更擅长结构化提炼,但重要事实仍需人工复核。", "icon": "auto_awesome" }
      ]
    }
  },
  {
    "op": "add-table-slide",
    "style": "rules",
    "content": {
      "title": "本文方法在两个指标上同时改进",
      "columns": ["Method", "Accuracy ↑", "Latency ↓"],
      "rows": [["Baseline", "82.4", "41 ms"], ["PlainDeck", "89.7", "28 ms"]],
      "alignments": ["left", "right", "right"],
      "source": "Table 2"
    }
  },
  { "op": "duplicate-slide", "slide": "./slides/001-intro.json", "id": "intro-copy" },
  { "op": "rename-slide", "slide": "./slides/002-results.json", "name": "Key results" },
  { "op": "move-slide", "slide": "./slides/002-results.json", "after": "./slides/001-intro.json" },
  { "op": "remove-slide", "slide": "./slides/003-appendix.json" },
  { "op": "set-theme", "patch": { "accent": "#2563eb", "background": "#ffffff" } },
  {
    "op": "set-slide-motion",
    "slide": "./slides/001-intro.json",
    "motion": { "camera": { "fromScale": 1, "toScale": 1.04, "durationFrames": 150 } }
  },
  {
    "op": "set-footer",
    "footer": {
      "left": { "type": "slide-name" },
      "center": { "type": "date" },
      "right": { "type": "page-of-count" }
    }
  }
]

set-footer 一次设置文档级左、中、右页脚,只修改 deck.json;设为 null 可关闭页脚。槽位类型为 nonetextdatepagepage-countpage-of-countdeck-titleslide-name,其中 text 还需要 text 字段。日期在显示或导出时生成,页码和页面名称会随页面排序自动更新。

set-element 可设置可选的 animationset-slide-motion 设置页面级镜头,传入 null 可移除。HTML/PNG/PDF 与普通 React 渲染保留最终版式但忽略动画,plaindeck/remotion 才按帧解释这些字段。

set-element 不能修改元素的 idtypemove-elementmove-slide 使用稳定 ID/路径及 beforeafter,不暴露数组索引。不存在的页面或元素、重复元素 ID、非法 patch、删除最后一页等都会使整批操作失败;操作在内存中全部完成并通过全量 schema 校验后,CLI 才会写盘。Web 编辑器也把交互动作转换为同一组 operations 后再更新历史与保存。

可用布局:blanktitle-bodysectionstatementmetrictwo-columnimage-rightthree-cardssummary-cardshook-statementprose-paneltakeaway,以及论文解读族 paper-figurepaper-tableversuscontributionslimitsclosing

TypeScript API

import {
  applyOperations,
  createDeckTemplate,
  inspectDeck,
  loadDeck,
  renderPdf,
  renderPng,
  saveDeck,
  validateDeck,
} from 'plaindeck'
import { renderHtml } from 'plaindeck/render'

const deck = await loadDeck('./my-deck')
const inspection = inspectDeck(deck)
const result = applyOperations(deck, operations)
const validation = validateDeck(result.document)
if (!validation.valid) throw new Error(JSON.stringify(validation.issues))
await saveDeck('./my-deck', result.document, result.changedPaths)

const html = renderHtml(result.document)
await renderPng(result.document, { projectPath: './my-deck', output: './dist/slides' })
await renderPdf(result.document, { projectPath: './my-deck', output: './dist/deck.pdf' })

createDeckTemplate('nature-methods', { title: 'My method' }) 创建 Web 默认使用的证据优先学术方案;CLI/API 也调用同一个模板工厂。CLI 无参数 init 仍保留 showcase,以避免破坏已有脚本。 flowchart 模板(5 页)用 process-flow(横向流程图)与 decision-branch(判断分支 + 回环)两个新布局把过程叙事画成节点和箭头;所有模板支持 { lang: 'en' | 'zh' } 双语文案,缺省为中文。布局目录可按语言取用:layoutPresetsFor(locale) / getLayoutPreset(id, locale)

plaindeck/core 公开 schema、类型、migration、canonical serializer、布局和主题预设。plaindeck/render 包含浏览器安全的纯 HTML renderer 与所有输出共用的 presentation model;文件系统、资源嵌入和 Playwright 渲染能力从包根入口 plaindeck 导出。React 页面组件由 plaindeck/react 导出,Remotion 时间轴由 plaindeck/remotion 导出(同一 npm 包的子路径,React 与 remotion 为可选 peer 依赖)。

渲染安全与输出

  • HTML 默认将项目内的本地图片转为 data URI,输出为独立的 Web 演示文件,并提供方向键、进度、页名和全屏控制。
  • 外部 http(s) 图片默认替换为占位图且不发起请求;仅对可信项目使用 --allow-network
  • PNG 默认输出全部页面到目录,以 001-name.png 命名;--slide 可接受从 1 开始的页码或完整页面路径。
  • PDF 每张幻灯片对应一页,页面尺寸来自 deck canvas。
  • PNG/PDF 使用 Playwright Chromium。若未安装,按照错误提示运行 npm install playwright && npx playwright install chromium
  • TypeScript API 可通过 browserExecutable 指定已有 Chromium 路径,适合容器或离线服务器。