| name | clipli |
| description | macOS clipboard intelligence CLI for agents and power users. Use when working with
the system clipboard, generating formatted Excel tables from CSV or JSON, editing
clipboard table cells, building or editing nested HTML/Markdown lists, managing
reusable HTML templates, or converting between RTF, HTML, plain text, and Jinja2.
Triggers on clipboard read/write/inspect operations, Excel-pasteable HTML/SVG/PNG
table generation, nested list generation/editing, reusable template capture/render/paste,
privacy-aware clipboard history/watch/filter/prune/restore workflows, previewing
rendered HTML without touching the clipboard, shell completions, doctor readiness
checks, and agent-command templatization or batch rendering.
Requires macOS. Binary must be built first with cargo build --release.
|
clipli — Clipboard Intelligence CLI
Setup
Build from the repo root: cd tools/clipli && cargo build --release
Binary in this repo: tools/clipli/target/release/clipli
Current binary version: clipli 1.0.0
All clipboard operations require a macOS GUI session. Non-clipboard commands (doctor --skip-clipboard, convert, lint, render, preview, history record --input, history list/search/show/prune, excel --dry-run, list-build --dry-run, list-edit --dry-run) work in automation and CI-like contexts.
Readiness Check
Run doctor first when the environment is unknown, when clipboard access fails, or before using clipli from automation:
clipli doctor
clipli doctor --json
clipli doctor --json --skip-clipboard
doctor checks platform, config parsing, template-store writability, textutil availability, pasteboard access, and external agent command launchability when configured.
In sandboxed agent environments, doctor may report the template store as not writable if the sandbox blocks ~/Library/Application Support/clipli. Treat that as environment signal, not necessarily a product failure.
Agent-first summary
If a new agent is handed clipli as a skill, the main thing to understand is that it mixes safe inspection commands with commands that mutate live user state.
write, capture, paste, excel, excel-edit, list-build, and list-edit change the current macOS clipboard.
watch, history record, and history restore can persist or replay clipboard data. Treat them as privacy-sensitive.
capture, edit, delete, restore, and import persist changes under the clipli config store, typically ~/Library/Application Support/clipli/templates/ on macOS.
history persists entries under the clipli config store, typically ~/Library/Application Support/clipli/history/ on macOS.
doctor, inspect, read, convert, search, show, lint, and render are the safest first moves.
excel --dry-run, excel-edit --dry-run, list-build --dry-run, list-edit --dry-run, and paste --dry-run let you preview output before touching the clipboard.
preview writes rendered HTML to a preview file and never touches the clipboard.
capture reads whatever is on the clipboard right now. It does not capture from a file path.
paste renders from stored template data. It does not use the current clipboard as input.
render writes files or stdout only. It does not touch the clipboard.
capture --strategy agent --agent-command <cmd> invokes an external process directly, passes a JSON request on stdin, and validates JSON from stdout.
- If the user asks for an Excel table copied as SVG or PNG, use
clipli excel --copy-as svg or clipli excel --copy-as png; do not use the default editable HTML clipboard path for that request.
- For generated Excel-style table data, prefer one-shot stdin commands. Pipe or heredoc CSV/JSON directly into
clipli excel; do not write a temporary CSV/JSON file first unless the user also needs that file.
- For nested lists, use
clipli list-build for new lists and clipli list-edit for path-based edits. Default to HTML unless the user asks for Markdown.
watch and history record default to --sensitive skip, which stores metadata only if common secret markers are detected. Use --sensitive allow only when the user explicitly wants payload retention.
- If the clipboard format is unknown, start with
inspect.
Safe Vs Mutating Commands
| Command family | Side effect |
|---|
doctor, inspect, read, convert, list, show, search, versions, lint, render, preview, history list, history search, history show | Safe read/preview operations |
excel --dry-run, excel-edit --dry-run, list-build --dry-run, list-edit --dry-run, paste --dry-run, history restore --dry-run | Safe preview operations |
write, paste, excel, excel-edit, list-build, list-edit | Mutate the live clipboard |
capture, edit, delete, restore, import | Change the persistent template store |
watch, history record | Change the persistent history store |
history prune | Removes matching persistent history entries unless --dry-run is used |
history restore | Mutates the live clipboard unless --dry-run is used |
Safe Default Workflow
When the user has not explicitly asked you to overwrite the clipboard, the safest sequence is:
- Use
inspect to see what is on the clipboard now.
- Use
read, show, search, or lint to understand the existing content or template.
- Use
convert, render, excel --dry-run, excel-edit --dry-run, list-build --dry-run, list-edit --dry-run, or paste --dry-run to preview the exact output.
- Only then use a clipboard-mutating command.
If the environment itself is uncertain, run clipli doctor --json --skip-clipboard before step 1.
The Core Loop
Copy from App → clipli capture → reusable template → clipli paste → Paste into App
Alternatively, for structured data without capturing:
CSV/JSON data → clipli excel → clipboard → Cmd+V into Excel
clipli excel-edit → refine formatting → Cmd+V
For agent-generated tables, the preferred loop is one shot:
CSV or JSON heredoc → clipli excel → clipboard → Cmd+V into Excel
Choosing the Right Command
| I want to... | Use |
|---|
| Turn generated CSV into a formatted Excel table | `printf 'Name,Revenue\nAlice,1200\n' |
| Turn generated JSON rows into a formatted Excel table | clipli excel --preset finance <<'JSON' ... JSON |
| Copy an Excel-style table as SVG | clipli excel --copy-as svg <<'CSV' ... CSV |
| Copy an Excel-style table as PNG | clipli excel --copy-as png <<'CSV' ... CSV |
| Tweak colors/values on an existing clipboard table | clipli excel-edit --set-bg "C3:#A0D771" |
| Build a nested list as HTML | clipli list-build --item "Launch > [x] QA" |
| Build a nested list as Markdown | clipli list-build --copy-as markdown <<'LIST' ... LIST |
| Edit a nested list by path | clipli list-edit --set "1.2:Updated" --append "1:[ ] Follow-up" |
| Put arbitrary HTML on the clipboard | clipli write --type html -i file.html |
| Generate a table from JSON with a Jinja2 template | clipli paste --from-table |
| Save clipboard content for reuse later | clipli capture --name my_template |
| Fill a saved template with new data | clipli paste my_template -D '{...}' |
| Preview rendered HTML without changing clipboard | clipli preview my_template -D '{...}' --open |
| See what's on the clipboard | clipli inspect |
| Check whether clipli is usable here | clipli doctor --json |
| Convert RTF to HTML | clipli convert --from rtf --to html |
| Render many outputs without touching the clipboard | clipli render my_template --data-file rows.json |
| Let an external LLM tool templatize captured HTML | clipli capture --name my_template --templatize --strategy agent --agent-command my-agent |
| Record one clipboard item into history | clipli watch --once |
| Search clipboard history | clipli history search "revenue" |
| Prune old history entries safely | clipli history prune --keep-latest 200 --dry-run --json |
| Restore a history item safely | clipli history restore ID --dry-run -o payload.bin |
| Generate shell completions | clipli completions zsh |
1. CSV or JSON to Excel Table
Reads CSV or JSON, generates Excel-native HTML by default, and writes it to the clipboard. It can also copy the same styled table as SVG or PNG when the user requests an image artifact. User then Cmd+V into the target app.
When the user asks for SVG or PNG, pass --copy-as svg or --copy-as png. In those modes, clipli copies the requested image artifact to the clipboard instead of HTML.
clipli excel <<'CSV'
Name,Revenue
Alice,1200
CSV
clipli excel --preset finance <<'JSON'
[{"Name":"Alice","Revenue":1200,"Margin":0.42}]
JSON
clipli excel --preset status --copy-as svg <<'JSON'
[{"Task":"Launch","Status":"Done"}]
JSON
clipli excel --copy-as svg <<'CSV'
Name,Revenue
Alice,1200
CSV
clipli excel --copy-as png <<'CSV'
Name,Revenue
Alice,1200
CSV
clipli excel \
--col "Revenue:currency:right" \
--col "Margin:percent_int:center" \
--col "SKU:text" \
--bold "SKU" \
--header-bg "#007873" \
--font "Aptos Display" <<'CSV'
SKU,Revenue,Margin
A-1,1200,42
CSV
clipli excel \
--title "Q1 2026 Product Report" \
--col "Revenue:currency:right" \
--col "Margin:percent_int:center" \
--col "Last Updated:datetime_iso:right" \
--bold "SKU" --italic "Category" --wrap "Product Name" \
--align "Status:center" \
--fg-color "Status:#C62828" \
--color-if "Margin:>=:50:#A0D771:#628048" \
--color-if "Margin:<:30:#C92E25:white" \
--link "SKU:https://example.com/dp/{}" \
--total-row --total-formula \
--rename "Units Sold:Units" \
--columns "SKU,Product Name,Revenue,Margin,Status" \
--hide "Internal ID" \
--row-height 24 --header-height 28 <<'CSV'
SKU,Product Name,Revenue,Margin,Status,Internal ID
A-1,Widget,1200,42,Done,secret-1
CSV
clipli excel --col "Revenue:currency" --dry-run > preview.html <<'CSV'
Name,Revenue
Alice,1200
CSV
clipli excel --copy-as svg --dry-run > preview.svg <<'CSV'
Name,Revenue
Alice,1200
CSV
clipli excel --copy-as png --dry-run --out-file preview.png <<'CSV'
Name,Revenue
Alice,1200
CSV
clipli excel data.csv
--col format syntax: COLUMN_NAME:FORMAT[:ALIGNMENT]
| Format | Display | Notes |
|---|
currency | $4,230,000 | Red negatives |
accounting | $4,230,000 | Dash for zero, parentheses for negatives |
percent | 15.60% | Excel treats input as fractional (0.156 = 15.6%) |
percent_int | 42% | Integer percentage |
percent_1dp | 15.6% | One decimal |
integer | 12,819 | Comma-grouped, no decimals |
text | B0BFBRL47B | Force text — prevents number auto-detection |
datetime_iso | 2026-03-25 14:30 | ISO datetime |
standard | 1234.5678 | Like General with more decimals |
--color-if syntax: COLUMN:OPERATOR:VALUE:BG_HEX:FG_HEX
Operators: >=, <=, >, <, ==, !=, contains, empty, not_empty. First matching rule wins.
--link syntax: COLUMN:URL_PATTERN where {} is replaced by the cell value.
Presets: default, finance, executive, minimal, and status. Explicit style flags and --col/--bold/--wrap/color rules override preset defaults.
Styles: --style table (default — banded rows, blue-gray borders) or --style plain (thick outer border, thin gridlines).
Column widths are controlled by Excel on paste (auto-fit) — cannot be set via clipboard HTML.
2. Edit Clipboard Cells
Reads the current clipboard HTML, modifies specific cells by A1 reference, writes it back. Use after clipli excel to refine formatting without regenerating from CSV or JSON.
Cell references: A1 = row 1 col 1 (header row), B2 = row 2 col 2 (first data cell), AA5 works for columns beyond Z.
clipli excel-edit --set "B3:New Product Name"
clipli excel-edit --set-bg "D4:#A0D771" --set-fg "D4:#628048"
clipli excel-edit --set-format "E2:currency" --set-align "E2:right"
clipli excel-edit --set-bold "A2" --set-italic "C5" --set-wrap "B2"
clipli excel-edit --set-formula "E7:=SUM(E2:E6)"
clipli excel-edit \
--set-bg "F6:#C92E25" --set-fg "F6:white" \
--set-bold "D4" --set "A7:Total"
clipli excel-edit --set-bg "D4:#A0D771" --dry-run
Edits are cumulative — run excel-edit multiple times to build up formatting.
3. Nested Lists
Build nested lists from JSON, Markdown, indented lines, or repeatable item paths. HTML is the default clipboard format because it pastes richly into Mail, Word, Docs, browser editors, and many note apps. Use --copy-as markdown when the destination explicitly wants Markdown/plain text.
clipli list-build --title "Launch Plan" \
--item "Prep > [x] QA pass" \
--item "Prep > [ ] Docs" \
--item "Ship > Announce"
clipli list-build --ordered --copy-as markdown <<'LIST'
Phase 1
QA
Docs
Phase 2
LIST
clipli list-build --copy-as markdown <<'JSON'
{"title":"Plan","items":[{"text":"Launch","items":[{"text":"QA","checked":true}]}]}
JSON
clipli list-build --item "Launch > QA" --dry-run
clipli list-build --item "Launch > QA" --copy-as markdown --dry-run
Task-list state uses [x] and [ ] prefixes in Markdown, indented lines, or --item paths. Generated HTML includes hidden clipli metadata so list-edit --input-format html can recover the structured list for later edits.
Use list-edit for deterministic edits. Paths are 1-based and dot-separated: 1 is the first top-level item, 1.2 is its second child.
clipli list-edit \
--set "1.1:Regression QA" \
--check "1.1" \
--append "1:[ ] Docs" \
--insert-after "1:Measure" \
--copy-as markdown \
--dry-run <<'LIST'
- Prep
- QA
LIST
clipli list-edit --append "1:Follow-up" --check "1.1"
clipli list-edit --indent "2" --outdent "1.2" --sort "root" --dedupe --dry-run
Common edit flags: --set PATH:TEXT, --append [PATH:]TEXT, --insert-before PATH:TEXT, --insert-after PATH:TEXT, --remove PATH, --check PATH, --uncheck PATH, --toggle PATH, --indent PATH, --outdent PATH, --sort PATH, --dedupe, --title TEXT, --kind ordered|unordered, --copy-as html|markdown.
4. Clipboard Inspection and I/O
Inspect — see what types and sizes are on the clipboard:
clipli inspect
clipli inspect --json
Output shows UTI type identifiers and byte sizes. Use this to discover what's available before reading.
Read — extract a specific type from the clipboard:
clipli read --type html
clipli read --type plain
clipli read --type rtf
clipli read --type html -o captured.html
clipli read --type png -o screenshot.png
clipli read --type html -c
Supported types: html, rtf, plain, svg, png, tiff, pdf. Binary types (png, tiff, pdf) require --output (can't print binary to terminal). SVG is text and can be printed to stdout.
Write — put content onto the clipboard:
clipli write --type html -i report.html
clipli write --type plain -i notes.md
echo "hello" | clipli write --type plain
clipli write --type svg -i diagram.svg
clipli write --type png -i image.png
When writing HTML, --with-plain (default: true) auto-generates a plain-text fallback so apps that don't accept HTML still get content.
5. Clipboard History and Watch
History is local and privacy-sensitive. Prefer bounded commands in agent workflows.
clipli watch --once
clipli watch --max-items 10 --sensitive redact
clipli watch --max-items 100 --max-history 200 --sensitive skip
clipli history record --type plain --input note.txt --json
clipli history list
clipli history list --json
clipli history list --source-app Excel --type html --from 2026-05-01
clipli history search "quarterly revenue"
clipli history search "launch" --type html --json
clipli history show ID --content
clipli history prune --keep-latest 200 --before 2026-05-01 --dry-run --json
clipli history prune --source-app Safari --type html --before 2026-04-01
clipli history restore ID
clipli history restore ID --dry-run
clipli history restore ID --dry-run -o restored.bin
Default sensitive policy is skip: if text contains common secret markers such as api_key, bearer , password, private key, secret=, or token=, clipli stores metadata but no payload. redact stores a redacted marker payload. allow stores the original payload and should only be used when payload retention is explicitly desired.
History metadata includes ID, timestamp, source app when available, pasteboard type, UTI, byte size, SHA-256, payload path, and redaction status. Payloads live under the clipli config directory in history/payloads/. History writes use a single-writer lock file to avoid corrupting index.jsonl.
6. Format Conversion
Reads from stdin (or -i file), converts, outputs to stdout (or -o file). Does not touch the clipboard.
clipli convert --from rtf --to html -i document.rtf -o document.html
cat document.rtf | clipli convert --from rtf --to html > output.html
clipli convert --from html --to plain < page.html
clipli convert --from html --to j2 --strategy heuristic < table.html
clipli convert --from j2 --to html -D '{"name":"Alice","revenue":"$5.2M"}' -i template.j2
7. Capture Clipboard as Template
Copy formatted content in any app (Excel, PowerPoint, Word, browser), then run:
clipli capture --name quarterly_report
clipli capture --name quarterly_report --templatize
clipli capture --name quarterly_report \
--templatize \
--strategy heuristic \
--description "Q1 earnings table from Excel" \
--tags finance,quarterly \
--preview \
--force
--preview opens the cleaned or templatized HTML in the browser before saving. --force overwrites an existing template and snapshots the previous version first.
Pipeline: read clipboard (HTML > RTF > plain text fallback) -> clean Office HTML -> extract variables -> save to the clipli template store.
Strategies: heuristic (fast regex: dates, currency, %, emails, numbers), agent (stdio protocol or direct external command for smarter extraction), manual (save as-is, edit by hand later).
--raw skips HTML cleaning — preserves original Office markup.
External agent command mode:
clipli capture --name slide_snippet \
--templatize \
--strategy agent \
--agent-command my-agent \
--agent-timeout 60 \
--json
When --agent-command is set, clipli launches the command without a shell, writes one JSON request to stdin, reads one JSON response from stdout, captures stderr/exit status on failure, and validates the returned template before saving.
Expected agent response:
{
"template": "<p>Hello {{ name }}</p>",
"variables": [
{
"name": "name",
"type": "string",
"default_value": "Alice",
"description": "Person name"
}
]
}
Validation rejects invalid Jinja, invalid variable names, structural mismatches, scripts, iframes, event handlers, and javascript: URLs.
8. Render and Paste Templates
Fill a saved template with data, write the rendered HTML + plain-text fallback to the clipboard.
clipli paste quarterly_report -D '{"title":"Q2 Report","revenue":"$5.2M"}'
clipli paste quarterly_report --data-file quarter_data.json
echo '{"title":"Q3"}' | clipli paste quarterly_report --stdin
clipli paste quarterly_report -D '{"title":"Q2"}' --dry-run
clipli paste quarterly_report -D '{"title":"Q2"}' --open
clipli paste quarterly_report -D '{}' --plain-text none
clipli paste quarterly_report -D '{}' --plain-text auto
Built-in table templates (no capture needed):
echo '{
"headers": [{"value":"Name","style":{"bold":true}},{"value":"Score","style":{}}],
"rows": [[{"value":"Alice","style":{}},{"value":"95","style":{}}]],
"style": {"header_bg":"#007873","header_fg":"#FFFFFF"}
}' | clipli paste --from-table --dry-run
echo '...' | clipli paste --from-table -t table_excel
Batch render without touching the clipboard:
clipli render quarterly_report --data-file rows.json --output-dir ./out
clipli render quarterly_report --data-file rows.json --format plain
clipli render quarterly_report --data-file rows.json --json
Preview without touching the clipboard:
clipli preview quarterly_report -D '{"title":"Q2"}' --open
clipli preview --input snippet.html --output preview.html --json
printf '<p>Hello</p>' | clipli preview --json
preview writes a standalone HTML file under the clipli config directory, or to --output, and never copies to the clipboard.
9. Template Lifecycle
Find templates:
clipli list
clipli list --json
clipli list --tag finance -v
clipli search "revenue"
clipli search "quarterly" --tag finance --json
Examine a template:
clipli show quarterly_report
clipli show quarterly_report --html
clipli show quarterly_report --schema
clipli show quarterly_report --meta
clipli show quarterly_report --open
Edit manually (opens $EDITOR, auto-snapshots before editing):
clipli edit quarterly_report
clipli edit quarterly_report --auto-schema
Version history (auto-created on force-save, edit, restore, import):
clipli versions quarterly_report
clipli versions quarterly_report --json
clipli show quarterly_report --version 20260326T120000Z
clipli restore quarterly_report --version 20260326T120000Z
Max 20 versions per template. Snapshots are full copies stored under <template>/versions/<id>/.
Validate before use:
clipli lint quarterly_report
clipli lint quarterly_report --strict
clipli lint quarterly_report --json
Checks: unbalanced {{ }}/{% %}, invalid identifiers, duplicate schema vars, template vars not in schema, schema vars not in template.
Share between machines:
clipli export quarterly_report -o report.clipli
clipli import report.clipli
clipli import report.clipli --force --name new_name
Delete:
clipli delete quarterly_report
clipli delete quarterly_report --force
clipli delete quarterly_report --keep-versions
Excel Format Reference
The default clipli excel command generates Excel-native HTML (Office XML namespaces, mso-* properties, mso-pattern, ProgId=Excel.Sheet). Users never need to think about this — the command handles it. When users request an image copy, clipli excel --copy-as svg copies SVG and clipli excel --copy-as png copies PNG instead of editable HTML.
For hand-crafted Excel HTML via clipli write --type html, see references/excel_format.md.
Shell Completions
Generate completion scripts from the installed binary:
clipli completions bash
clipli completions zsh
clipli completions fish
Config
Optional config file, typically ~/Library/Application Support/clipli/config.toml on macOS. CLI flags always override these values:
[defaults]
font = "Aptos Display"
font_size_pt = 12.0
plain_text_strategy = "tab-delimited"
[clean]
keep_classes = false
target_app = "generic"
[templatize]
default_strategy = "heuristic"
[agent]
command = "my-agent"
args = []
timeout_secs = 30
Error Handling
Without --json: errors go to stderr as plain text, exit code 1.
With --json, errors go to stdout as {"ok":false,"error":"...","code":"STORE_NOT_FOUND"}. JSON mode is available on the automation-oriented commands, including inspect, capture, paste, list, show, delete, versions, lint, search, excel, excel-edit, list-build, list-edit, render, convert, doctor, watch, and history.
Error code prefixes: PB_ (pasteboard), STORE_ (template store), RENDER_ (template engine), CLEAN_ (HTML cleaner), TEMPLATIZE_ (variable extraction), RTF_ (conversion).
v1.0 Stability Notes
The stable v1.0 surface is the macOS clipboard/template core: inspect/read/write, capture/paste/render/preview, conversion, lint/search/versioned templates, Excel HTML/SVG/PNG generation, list HTML/Markdown generation and editing, history record/list/search/show/restore/prune, completions, doctor, and JSON error envelopes.
Agent-command templatization and long-running watch are implemented and tested, but should still be treated as advanced workflows. Prefer explicit data files, --dry-run, lint, and bounded retention when automating them.