← 返回
未分类 中文

org-cli

Task capture, scheduling, and linked knowledge in org-mode files via the `org` CLI. Query, mutate, link, and search the user's org files and org-roam database.
通过 org CLI 在 org 模式文件中捕获任务、排程并关联知识;可查询、修改、链接并搜索用户的 org 文件和 org-roam 数据库。
dcprevere
未分类 clawhub v1.0.2 1 版本 100000 Key: 无需
★ 0
Stars
📥 358
下载
💾 0
安装
1
版本
#latest

概述

org-cli

Maintain structured, linked, human-readable knowledge in org-mode files via the org CLI. Org files combine plain text with rich structure — headlines, TODO states, tags, properties, timestamps, links — and back onto a SQLite knowledge graph via org-roam.

This skill teaches the agent to manage the user's org setup on their behalf: capture tasks, schedule and close them, store knowledge in the user's roam graph, search across everything. One workspace, one store. If you also want the agent to persist its own memory in org, install the org-memory skill on top.

The prime directive

Everything persistent goes in org. Tasks, notes, facts, preferences, relationships, decisions — if the user says it and it has lasting value, it lives in an org file.

  • Never hold long-term information in chat context alone.
  • Never reply "got it" without a corresponding write when a write is warranted.
  • If a mutation fails, retry or surface the error — do not silently drop it.

Always surface the ID when you mention an item. When you create, find, reference, or list anything in org, include its short CUSTOM_ID (or UUID for roam nodes) in your reply so the user can act on it by ID. If an item has no ID (index missing — see Stable identifiers), say so and offer to backfill.

After every write, print exactly:

org-cli: <action> [<id>] <file-path>

Examples:

org-cli: added TODO [k4t] ~/org/inbox.org
org-cli: added note [k4t] ~/org/inbox.org
org-cli: marked DONE [k4t] ~/org/inbox.org
org-cli: created node [3f2a-…] ~/org/roam/sarah.org

If the response JSON has no custom_id (and no id for roam nodes), print [no-id] and flag it.

No silent writes. Ever.

Shortcuts

When the user types these prefixes, act immediately.

ActionPrefixTargetDoes
------------
n noten:inboxCreate plain headline (no TODO, no date)
k knowledgek:roamStore/update a knowledge node
f findf:allFull-text search across headlines and roam nodes, return IDs
t todot:inboxCreate TODO, extract any date
s schedules:workspaceReschedule matching TODO
d doned:workspaceMark matching TODO DONE

t vs n: t creates a TODO (appears in TODO lists, can be scheduled/done). n creates a plain captured headline — a thought parked under inbox, no TODO state. Use n when the user is noting something for themselves, not committing to action. A dateless TODO is still t: with no date in the text; it just lands without SCHEDULED/DEADLINE.

Action details

In the examples below, $DIR is $ORG_CLI_DIR, $ROAM is $ORG_CLI_ROAM_DIR, and $DB is $ORG_CLI_DB.

n — create a plain note

A plain headline, no TODO keyword, no date. Does not appear in TODO lists. Use for captured thoughts, ideas, observations the user wants parked.

org add "$DIR/inbox.org" '<text>' --db "$DB" -f json

If the user later wants to promote it to a TODO, use the ID: org todo set TODO -d "$DIR" --db "$DB".

k — knowledge in the roam graph

Store in the user's roam graph. Never create duplicates.

  1. Find: org roam node find '' -d "$ROAM" --db "$DB" -f json
  2. Exists → org append '' -d "$DIR" --db "$DB" -f json
  3. New → org roam node create '' -d "$ROAM" --db "$DB" -f json then append.

Roam nodes live in $ROAM, never in the workspace root.

Roam nodes are identified by UUID (data.id); headlines inside them by CUSTOM_ID (data.custom_id). Surface whichever applies: Noted against Sarah [3f2a-…]: prefers morning meetings.

f — find across headlines and knowledge

Search the user's org files and roam graph, return matches with IDs. No mutation. Matches any headline — TODO, done, or plain — and any roam node.

  1. org fts '' -d "$DIR" --db "$DB" -f json (full-text across titles and bodies)
  2. org roam node find '' -d "$ROAM" --db "$DB" -f json
  3. Merge results, group by kind, print as [] </code> lines.</li></ol><p>If the user is specifically asking for TODOs only, use <code>org todo list --search '<query>' -d "$DIR" --db "$DB" -f json</code> instead. If they're asking for a headline by exact title or a filter like tag/state, use <code>org headlines</code> with the relevant flags.</p><p>Return the list even when empty — say "no matches" rather than retrying silently.</p><h3><code>t</code> — create a TODO</h3><p>Extract any relative or absolute date from the text. Use <code>--deadline</code> for hard dates ("by Friday", "due March 1st"); <code>--scheduled</code> for softer timing ("in 3 weeks", "next month"). If no date, omit both — the TODO is still created, just without a date.</p><pre><code>org add "$DIR/inbox.org" '<title>' --todo TODO [--scheduled <date> | --deadline <date>] --db "$DB" -f json </code></pre><ul><li><code>t: submit taxes in 3 weeks</code> → <code>--scheduled 2026-05-09</code></li><li><code>t: renew passport by June</code> → <code>--deadline 2026-06-01</code></li><li><code>t: call dentist tomorrow</code> → <code>--scheduled 2026-04-19</code></li><li><code>t: book flights</code> → no date flag</li></ul><p>Read <code>data.custom_id</code> from the JSON response and include it in your reply. Example: <code>Added TODO [k4t]: Submit taxes, scheduled 2026-05-09.</code></p><h3><code>s</code> — reschedule</h3><p>Same search flow as <code>d</code>, then:</p><pre><code>org schedule <custom_id> <date> -d "$DIR" --db "$DB" -f json </code></pre><h3><code>d</code> — mark DONE</h3><ol><li>Search: <code>org todo list --search '<text>' -d "$DIR" --db "$DB" -f json</code></li><li>One match → <code>org todo set <custom_id> DONE -d "$DIR" --db "$DB" -f json</code></li><li>Multiple → show each as <code>[<custom_id>] <title></code> so the user can pick by ID. Ask which.</li><li>None → say so. If you searched with <code>--state TODO</code> and got nothing, retry without it (the match may be in another state).</li></ol><p>Reply with the ID: <code>Marked DONE [k4t]: Submit taxes.</code></p><h2>Ambient capture</h2><p>When the user mentions a durable fact in passing — a preference, a relationship, a date, a constraint — offer to save it. Complete the explicit request first; then say "I'd like to note: <X>" and wait for confirmation.</p><p>Bias toward capturing. Under-capture is worse than over-capture: you can always prune, but you can't recover what was never written.</p><h2>Stable identifiers</h2><p>Every headline added via <code>org add</code> gets a short CUSTOM_ID (e.g. <code>k4t</code>) — <strong>but only when the index DB exists.</strong> If you ran the first-time setup, it does. If a headline was created by hand, by <code>batch</code>, or by <code>add</code> before the index was built, it won't have one.</p><p>Every roam node created via <code>org roam node create</code> gets a UUID <code>:ID:</code> unconditionally. Nodes also carry a CUSTOM_ID on their file-level headline if the index exists.</p><p>Use IDs in subsequent commands — no file path needed:</p><pre><code>org todo set k4t DONE -d "$ORG_CLI_DIR" --db "$ORG_CLI_DB" -f json org schedule k4t 2026-05-01 -d "$ORG_CLI_DIR" --db "$ORG_CLI_DB" -f json org append k4t 'Note' -d "$ORG_CLI_DIR" --db "$ORG_CLI_DB" -f json </code></pre><p>Preference order: CUSTOM_ID > org-id (UUID) > exact title. <strong>Never use <code>pos</code></strong> — it changes on every edit. For multiple mutations in one file, use <code>org batch</code>.</p><p><strong>Always include the ID when you mention an item to the user.</strong> Read <code>data.custom_id</code> from any JSON response; for roam nodes, also read <code>data.id</code>. Echo it in brackets: <code>[k4t]</code> or <code>[3f2a-…]</code>. This is how the user follows up — "reschedule k4t to Friday" is only possible if you told them the ID existed.</p><p>If a response has no <code>custom_id</code>, tell the user: "This item has no short ID — run <code>org custom-id assign -d <dir> --db <db></code> to backfill, or refer by title." Never silently proceed with just a title — the next lookup may match the wrong item.</p><p>Backfill missing IDs: <code>org custom-id assign -d <dir> --db <db></code>.</p><h2>Output</h2><p>All commands accept <code>-f json</code>. Always pass it. Envelopes:</p><ul><li>Success: <code>{"ok":true,"data":...}</code></li><li>Error: <code>{"ok":false,"error":{"type":"...","message":"..."}}</code></li></ul><p>Branch on <code>ok</code>. Handle by <code>type</code>: <code>file_not_found</code>, <code>headline_not_found</code> (re-query), <code>parse_error</code> (don't retry), <code>invalid_args</code> (check <code>org schema</code>).</p><h2>Command safety</h2><p><strong>Only environment variable paths go in double quotes. User text always goes in single quotes.</strong> Double quotes expand <code>$(...)</code>, backticks, and variables — that's shell injection when the text came from the user.</p><pre><code># Right org add "$ORG_CLI_DIR/inbox.org" 'User provided text' --todo TODO -f json # Wrong — user text in double quotes is an injection vector org add "$ORG_CLI_DIR/inbox.org" "User provided text" --todo TODO -f json </code></pre><p>Embedded single quote → <code>'\''</code>. Multi-line → pipe via stdin:</p><pre><code>printf '%s' 'Long text' | org append k4t --stdin -d "$ORG_CLI_DIR" --db "$ORG_CLI_DB" -f json </code></pre><p>(If you are calling the org-cli OpenClaw plugin's <code>org_*</code> tools instead of shelling out, pass raw text — those tools use <code>execFile</code> and do no shell interpolation.)</p><p>Never bypass <code>org</code> for org-file mutations — no <code>echo >></code>, no direct file edits, no <code>sed</code>/<code>awk</code> rewrites. The CLI maintains formatting, timestamps, index sync, and ID allocation; ad-hoc edits silently break all of that.</p><h2>Configuration</h2><p>Required:</p><table><thead><tr><th>Variable</th><th>Default</th><th>Purpose</th></tr></thead><tbody><tr><td>---</td><td>---</td><td>---</td></tr><tr><td><code>ORG_CLI_DIR</code></td><td><code>~/org</code></td><td>User's workspace (inbox.org, tasks, projects)</td></tr><tr><td><code>ORG_CLI_DB</code></td><td><code>$ORG_CLI_DIR/.org.db</code></td><td>SQLite database (roam + index)</td></tr></tbody></table><p>Optional:</p><table><thead><tr><th>Variable</th><th>Default</th><th>Purpose</th></tr></thead><tbody><tr><td>---</td><td>---</td><td>---</td></tr><tr><td><code>ORG_CLI_ROAM_DIR</code></td><td><code>$ORG_CLI_DIR/roam</code></td><td>Roam nodes</td></tr><tr><td><code>ORG_CLI_BIN</code></td><td><code>org</code></td><td>Path to the <code>org</code> binary</td></tr><tr><td><code>ORG_CLI_INBOX_FILE</code></td><td><code>inbox.org</code></td><td>Inbox filename</td></tr></tbody></table><p>Always pass <code>--db</code>. Without it, the CLI defaults to <code><directory>/.org.db</code>, which may diverge from configured locations.</p><h2>First-time setup</h2><pre><code># Sync existing files (skip if starting fresh) org roam sync -d "$ORG_CLI_DIR" --db "$ORG_CLI_DB" # Build the headline index — enables CUSTOM_IDs and file-less commands org index -d "$ORG_CLI_DIR" --db "$ORG_CLI_DB" </code></pre><h2>Discovery</h2><p><code>org schema</code> dumps the full command catalog as JSON. Use it to construct commands without memorising flags.</p><p>Any mutation can be previewed with <code>--dry-run</code> — the command runs its logic and reports what <em>would</em> change without touching the file. Use it when the user asks to preview, when a batch is large, or when you're uncertain which headline will match.</p><h2>Useful commands</h2><p>Read-only queries the shortcuts don't cover directly. All accept <code>-f json</code>.</p><p><strong>Today / agenda</strong> — "what do I need to do":</p><pre><code>org today -d "$DIR" --db "$DB" -f json # TODOs due today + overdue org agenda today -d "$DIR" --db "$DB" -f json # scheduled + deadlines + overdue for today org agenda week -d "$DIR" --db "$DB" -f json # next 7 days org agenda todo --state TODO -d "$DIR" --db "$DB" -f json # every open TODO </code></pre><p><strong>TODO list filters</strong> — narrower than <code>f:</code>:</p><pre><code>org todo list --state TODO --unscheduled -d "$DIR" --db "$DB" -f json # TODOs with no date org todo list --state TODO --overdue -d "$DIR" --db "$DB" -f json # past their scheduled/deadline org todo list --state TODO --due-before 2026-05-01 -d "$DIR" --db "$DB" -f json org todo list --state TODO --tag work -d "$DIR" --db "$DB" -f json org todo list --state TODO --priority A -d "$DIR" --db "$DB" -f json org todo list --state TODO --sort priority -d "$DIR" --db "$DB" -f json </code></pre><p><strong>Headlines</strong> — any headline (TODO, done, or plain), filter by tag/level/property:</p><pre><code>org headlines --todo TODO -d "$DIR" --db "$DB" -f json org headlines --tag project -d "$DIR" --db "$DB" -f json org headlines --property CATEGORY=admin -d "$DIR" --db "$DB" -f json </code></pre><p><strong>Roam</strong> — list, get, sync:</p><pre><code>org roam node list -d "$ROAM" --db "$DB" -f json org roam node get <uuid> -d "$ROAM" --db "$DB" -f json org roam sync -d "$DIR" --db "$DB" </code></pre><h2>References</h2><p>Read on demand:</p><ul><li><strong>Task management</strong> (<code>{baseDir}/references/task-management.md</code>) — for batch ops or translating natural language to queries.</li><li><strong>Knowledge management</strong> (<code>{baseDir}/references/knowledge-management.md</code>) — when working with the roam graph.</li></ul></div> </div> </div> <div id="tab-versions" class="detail-content"> <div class="detail-section"> <h2>版本历史</h2> <p style="margin-bottom:12px;font-size:14px;color:#94a3b8;">共 1 个版本</p> <ul class="version-list"> <li> <div> <span class="version-tag">v1.0.2</span> <span style="font-size:11px;color:#5b6abf;margin-left:8px;background:#eef0ff;padding:1px 8px;border-radius:10px;">当前</span> </div> <div style="font-size:12px;color:#94a3b8;"> 2026-05-07 10:07 安全 安全 </div> </li> </ul> </div> </div> <div id="tab-security" class="detail-content"> <div class="detail-section"> <h2>安全检测</h2> <div class="sec-grid"> <div class="sec-card"> <h4>腾讯云安全 (Keen)</h4> <div class="sec-status sec-safe"> 安全,无风险 </div> <a href="https://tix.qq.com/search/skill?keyword=832ed1dcf9c9050fd9a790a0753e21d3" target="_blank">查看报告</a> </div> <div class="sec-card"> <h4>腾讯云安全 (Sanbu)</h4> <div class="sec-status sec-safe"> 安全,无风险 </div> <a href="https://static.cloudsec.tencent.com/html-report-v2/2026/05/26/440901_f0d64939d7e665221947868f861b55f7.html?q-sign-algorithm=sha1&q-ak=AKID8JMG1bzBC1dz96qNhssfFftujT1NCoFi&q-sign-time=1781427763%3B1812963763&q-key-time=1781427763%3B1812963763&q-header-list=host&q-url-param-list=&q-signature=8a33f82d5579083999d2e48728868ccceb2a3c4f" target="_blank">查看报告</a> </div> </div> </div> </div> <!-- Recommended Skills --> <div style="margin-top:24px;"> <h2 style="font-size:18px;font-weight:600;margin-bottom:16px;">🔗 相关推荐</h2> <div class="rec-grid"> <div class="rec-card"> <span class="badge-cat" style="margin-bottom:8px;display:inline-block;">security-compliance</span> <h3><a href="/s/skill-vetter">Skill Vetter</a></h3> <div class="rec-owner">spclaudehome</div> <div class="rec-desc">AI智能体技能安全预审工具。安装ClawdHub、GitHub等来源技能前,检查风险信号、权限范围及可疑模式。</div> <div class="rec-stats"> <span style="color:#f39c12;">★ 1,219</span> <span style="color:#5b6abf;">📥 266,878</span> </div> </div> <div class="rec-card"> <span class="badge-cat" style="margin-bottom:8px;display:inline-block;">developer-tools</span> <h3><a href="/s/github">Github</a></h3> <div class="rec-owner">steipete</div> <div class="rec-desc">使用 `gh` CLI 与 GitHub 交互,通过 `gh issue`、`gh pr`、`gh run` 和 `gh api` 管理议题、PR、CI 运行及高级查询。</div> <div class="rec-stats"> <span style="color:#f39c12;">★ 672</span> <span style="color:#5b6abf;">📥 324,538</span> </div> </div> <div class="rec-card"> <span class="badge-cat" style="margin-bottom:8px;display:inline-block;">ai-intelligence</span> <h3><a href="/s/self-improving">Self-Improving + Proactive Agent</a></h3> <div class="rec-owner">ivangdavila</div> <div class="rec-desc">自我反思+自我批评+自我学习+自组织记忆。智能体评估自身工作、发现错误并持续改进。</div> <div class="rec-stats"> <span style="color:#f39c12;">★ 1,363</span> <span style="color:#5b6abf;">📥 319,063</span> </div> </div> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded',function(){ document.querySelectorAll('.detail-tab').forEach(function(btn){ btn.addEventListener('click',function(e){ var tab = this.getAttribute('data-tab'); document.querySelectorAll('.detail-tab').forEach(function(b){b.classList.remove('active')}); document.querySelectorAll('.detail-content').forEach(function(c){c.classList.remove('active')}); this.classList.add('active'); var el = document.getElementById('tab-'+tab); if(el) el.classList.add('active'); }); }); }); </script> <div class="footer"> <p>Skill工具集 © 2026</p> </div></body> </html>