Autograph logo

Autograph

Community
smixs
autograph

Schema-as-code enforcement for any Obsidian vault. Zero hardcoded domains. Use when creating vault cards, checking vault health, running schema compliance, deduplicating entities, generating MOC indexes, running decay cycles, bootstrapping a vault, fixing wikilinks, finding orphans or backlinks, extracting entities from daily files, or touching/promoting cards. Do NOT use for content generation or non-vault file operations.

Overview

Publishersmixs
Repositoryautograph
Skill nameautograph
Stars
77
Forks
6
Bundled files
28
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • 28 bundled files

    Scripts, templates, and references the model can read while it works. Files are read-only and never executed.

  • Open source

    Published by smixs on GitHub. Read the source before you install it.

Installation

Install the Autograph AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/smixs/autograph/tree/main/skills/autograph
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/smixs/autograph.git /tmp/autograph
mkdir -p .claude/skills
cp -r /tmp/autograph/skills/autograph .claude/skills/autograph
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Autograph in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Autograph on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Autograph is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

autograph — typed vault engine

One schema. One graph. Works on any vault.

Overview

No hardcoded domains, types, or paths. The agent discovers structure from data, builds a schema, then enforces it. All scripts share common.py. Metadata uses PyYAML 6.0.3 (safe scalar loader); uv installs the declared dependency. API calls use urllib.

Quick Reference: 6 Workflows

WorkflowWhen to useEntry point
BOOTSTRAPNew vault / after import / first setupdiscover.py → enforce.py → graph.py health
HEALTHDaily maintenance / on requestgraph + strict YAML checks → scoped repair manifest
CREATE / UPDATENew knowledge card, or new info about an existing onesearch.py dedup → ADD/UPDATE/SUPERSEDE → link → touch
SEARCH & LINKFind info + strengthen connectionsHub → links → target; graph.py orphans → connect
ORCHESTRATEAutomated multi-agent workflows (no API keys)orchestrate.py health|bootstrap
DAILY → CARDSTurn a day's raw notes into linked cardsdaily.py extract → dedup-first process → link

Workflow 1: BOOTSTRAP (raw vault → structured graph)

When to use: New vault, bulk import, first setup. Run once, then switch to HEALTH.

Full guide: references/bootstrap-workflow.md

Summary (10 phases)

  1. Discover: uv run scripts/discover.py <vault-dir> --verbose > /tmp/discovery.json
  2. Generate schema: Script baseline (generate_schema.py) + agent swarm (swarm_prepare.py → Wave 1 haiku → swarm_reduce.py → Wave 2 sonnet). NEVER skip the swarm.
  3. Review: Human approves schema. Never auto-apply.
  4. Bootstrap + Enforce: engine.py init + enforce.py --apply
  5. Link cleanup: link_cleanup.py --apply (before enrichment)
  6. Tag enrich: enrich.py tags --apply (via OpenRouter API)
  7. Deduplicate: dedup.py --apply (before link enrichment)
  8. Link enrich: enrich.py swarm-links --apply (always swarm-links, never links)
  9. MOC generation: moc.py generate
  10. Verify: enforce.py --check on the scoped manifest + graph.py health on the staged vault; resolve concrete validation/link findings. A health score is not an acceptance gate.

Critical Rules

  • Always run Phase 2B (agent swarm). Script alone cannot classify unstructured content.
  • Always use swarm-links, not links (0.3% vs 81.6% match rate).
  • Always dry-run first — run without --apply before applying.
  • Dedup before link enrich — prevents links to merged/trashed files.

Workflow 2: HEALTH (diagnosis before scoped repair)

Read integrity.md before maintenance or creating cards.

  1. Build a staged view or run read-only checks. Use graph health for links and enforce --check for strict YAML/schema validation.
  2. Separate missing targets, ambiguous links, no-incoming cards, isolated cards and reachability from hubs. Counts overlap; the health score is not an acceptance gate.
  3. Inspect current sources and prepare an explicit file manifest. Preserve original bytes and body content for mechanical changes. Never infer a business state from an unknown status.
  4. Apply only the reviewed repair scope. Do not mutate readonly archival paths. MOC generation preserves legacy/manual files unless an explicit managed block exists.
  5. Recheck changed metadata and links, then publish the completed batch through the vault transport. Verify remote delivery separately.

The health orchestration command reports only; it does not automatically fix links, regenerate MOCs or change decay. Use uv run for all Python entry points so the declared YAML dependency is available.

Workflow 3: CREATE / UPDATE (dedup-first, then link)

When to use: Recording any card, or new information about something the vault may already track. Always look up first, always link immediately — a near-duplicate is the most common mistake; an orphan card is wasted knowledge.

Step 0: LOOKUP (mandatory — never skip)

bash
uv run scripts/search.py "<entity / key phrase>" --vault <vault-dir> --json
# fallback: grep -ril "<name>" <vault-dir>

Pick the operation (full rules: references/update-in-place.md):

  • ADD — no existing card → create it (steps 1–5 below).
  • NOOP — already captured, unchanged → stop.
  • UPDATE — same subject, new enrichment → open the card, sharpen description, append a dated line under ## Log, re-touch.
  • SUPERSEDE — new fact contradicts a current value → rewrite the current value (frontmatter field + top of description = "Compiled Truth"), move the OLD value to append-only ## History (- 2026-03→2026-06 · company: TDI Group), set updated:. Whole card obsolete → status: superseded + superseded_by: "[[new-card]]".

Only when the operation is ADD, continue:

Steps (ADD path)

  1. Type: Pick from schema node_types
  2. Path: Reverse-lookup domain_inference to find target folder:
    python
    # domain_inference maps path→domain. To find folder for domain "crm":
    for path_prefix, domain in schema['domain_inference'].items():
        if domain == 'crm':
            target_folder = path_prefix  # e.g. "work/crm/"
            break
  3. Frontmatter: Write description (search snippet, not title repeat), tags (2-5, lowercase, kebab-case), status from type's enum
  4. LINKING PROTOCOL (mandatory): a. Add ## Related section with [[hub]] file of the domain
    • Hub = _index.md or MEMORY.md of that domain b. Find 2-3 sibling cards of same type+domain → add [[links]]
    • uv run scripts/graph.py backlinks <vault> <hub> → find siblings
    • Or: read vault-graph.json → filter nodes by type+domain c. Run uv run scripts/engine.py touch <new-file>
  5. Verify checklist:
    • Hub linked?
    • 2+ related cards found?
    • description ≠ title repeat?
    • tags: 2-5, lowercase, kebab-case?
    • status ∈ schema enum?

Templates: references/card-templates.md


Workflow 4: SEARCH & LINK (find + strengthen connections)

When to use: Looking up information in the vault, or strengthening weak areas of the graph.

Navigation (Hub → Links → Target)

  1. Determine domain from the topic (work, personal, research, etc. — whatever your schema defines)
  2. Start at hub: _index.md or MEMORY.md of that domain
  3. Follow links — max 2 hops from hub to target
  4. Fallback: uv run scripts/graph.py backlinks <vault> <target> for reverse links

Orphan Rescue

bash
uv run scripts/graph.py orphans <vault-dir>        # find orphans
# For each orphan: connect to nearest hub or sibling card

Link Strengthening

bash
# Files with <2 links → enrich
OPENROUTER_API_KEY=sk-... uv run scripts/enrich.py swarm-links <vault-dir> --apply
uv run scripts/graph.py health <vault-dir>          # verify improvement

Workflow 5: ORCHESTRATE (automated multi-agent workflows)

When to use: Instead of running scripts manually. No API keys — the Claude Code agent does all judgment directly.

Phase 0: Script sequencing

bash
uv run scripts/orchestrate.py health <vault-dir>      # automated health workflow
uv run scripts/orchestrate.py bootstrap <vault-dir>    # full bootstrap (one command)

health runs graph and strict metadata checks only. It leaves cards and indexes unchanged; graph diagnostic reports may be written. bootstrap runs: enforce > cleanup > tags > dedup > swarm-links > MOC > verify.

Phases 1-3: Agent judgment (no API keys)

The agent (you) does the judgment directly — read prepared data, decide, write results.

bash
# Phase 1: prep dedup clusters for YOUR review
uv run scripts/orchestrate.py dedup-prepare <vault-dir>
# -> writes .graph/dedup-review-input.json
# -> YOU read clusters, mark approved=true, then: dedup.py --apply-manifest

# Phase 2: prep domain catalogs for YOUR link suggestions
uv run scripts/orchestrate.py link-prepare <vault-dir>
# -> writes .graph/link-review-input.json
# -> YOU read catalogs, suggest links per domain, write batch results

# Phase 3: prep graph data for YOUR semantic analysis
uv run scripts/orchestrate.py graph-prepare <vault-dir>
# -> writes .graph/graph-analysis-input.json
# -> YOU analyze contradictions, missing links, stale hubs, write findings

For Phases 1-3: run the prep command, read the output JSON, do the analysis yourself (you ARE the LLM), write results back. Use Agent tool for parallel domain work in Phase 2.


Workflow 6: DAILY → CARDS (day's notes → linked cards)

When to use: Turning a daily/YYYY-MM-DD.md note file into durable cards. Judgment-first — the scripts extract candidates; you classify, dedup, and link.

Full guide: references/daily-processor.md

Summary (4 phases + idempotency)

  1. CAPTURE: daily.py extract <daily-dir> <vault-dir> [date] (candidates → .graph/) + supersede.py <vault> (conflict scan). Read schema node_types, list noteworthy items + the day's topics.
  2. PROCESS: per item, run the Workflow 3 Step 0 decision (ADD / UPDATE / SUPERSEDE / NOOP — references/update-in-place.md); resolve every .graph/supersede-candidates.json entry.
  3. LINK: apply the Workflow 3 linking protocol (hub + 2 siblings + touch) to each card.
  4. SUMMARIZE (schema-gated): only if the schema defines a summary type, write a daily-summary card with topics + a MOC down to today's cards and the raw file. No hardcoded DAG.

Idempotency: append <!-- autograph-processed: YYYY-MM-DDTHH:MM cards=N --> to the end of the daily file; on re-run, skip content above the last marker. Never edit existing lines.


Decay Engine (Ebbinghaus)

The decay system models memory with three key mechanisms:

1. Access count (spacing effect)

Each touch increments access_count in frontmatter. More retrievals = slower forgetting:

strength = 1 + ln(access_count)
effective_rate = base_rate / strength
relevance = max(floor, 1.0 - effective_rate * days_since_access)

Example: a card touched 5 times has strength = 1 + ln(5) ≈ 2.6, decaying ~2.6x slower than a card touched once.

2. Domain-specific rates

Different content types decay at different rates. Configure in schema decay.domain_rates:

TypeRateHalf-life (~)Rationale
contact0.005100 daysPeople don't become irrelevant quickly
crm0.00862 daysDeals have medium lifecycle
learning0.01050 daysKnowledge fades moderately
project0.01242 daysProjects have defined timelines
daily0.02025 daysDaily notes lose relevance fast
(default)0.01533 daysFallback for unlisted types

3. Graduated recall

Touch promotes one tier at a time, not a direct jump to active:

archive → cold → warm → active

Each promotion sets last_accessed to a midpoint date, so without re-touch the card naturally drifts back.

Backward compatibility

  • Files without access_count → default=1 → 1+ln(1)=1.0 → rate unchanged
  • Files without type → default rate applies
  • Existing calls calc_relevance(days, schema) → work unchanged (new params optional)

Maintenance Commands

bash
uv run scripts/moc.py generate <vault-dir>                                       # MOC generation
uv run scripts/engine.py decay <vault-dir>                                       # decay cycle
uv run scripts/engine.py touch <vault-dir>/path/card.md                          # touch (graduated)
uv run scripts/engine.py creative 5 <vault-dir>                                  # creative recall
uv run scripts/engine.py stats <vault-dir>                                       # stats
uv run scripts/graph.py backlinks <vault-dir> path/to/card                       # backlinks
uv run scripts/graph.py orphans <vault-dir>                                      # orphans
uv run scripts/graph.py fix <vault-dir> --apply                                  # fix links
uv run scripts/search.py "<query>" --vault <vault-dir> --json                    # ranked memory search (dedup-first)
uv run scripts/supersede.py <vault-dir>                                          # conflict scan (dry-run)
uv run scripts/supersede.py <vault-dir> --apply                                  # stamp superseded (2-card, newer-by-date)
uv run scripts/daily.py extract <memory-dir> <vault-dir>                         # entity extraction
uv run scripts/engine.py init <vault-dir> --dry-run                              # bootstrap bare files
OPENROUTER_API_KEY=sk-... uv run scripts/enrich.py swarm-links <vault-dir> --apply  # link enrichment
OPENROUTER_API_KEY=sk-... uv run scripts/enrich.py tags <vault-dir> --apply         # tag enrichment
uv run scripts/link_cleanup.py <vault-dir> --apply                               # link cleanup
uv run scripts/cleanup.py <vault-dir> [schema.json]                              # preview bounded description repair
uv run scripts/cleanup.py <vault-dir> [schema.json] --apply                      # atomic repair before enforce/graph

Scripts

ScriptPurpose
common.pyShared: parse FM, walk, domain, decay (Ebbinghaus), wikilinks
discover.pyWorkflow 1: scan vault, output enum candidates
generate_schema.pyWorkflow 1: turn discovery JSON into draft schema
swarm_prepare.pyWorkflow 1: bin-pack vault into agent batches
swarm_reduce.pyWorkflow 1: consolidate + validate schema
enforce.pyWorkflow 1: validate + autofix against schema
cleanup.pyPreflight: bounded-memory repair for bug-bloated descriptions
link_cleanup.pyWorkflow 1/4: remove phantom wikilinks from ## Related
enrich.pyWorkflow 1/4: tags + swarm-links (catalog-oriented link enrichment)
dedup.pyWorkflow 1: safe merge + .trash/
graph.pyWorkflow 2/4: health score, link repair, backlinks, orphans
moc.pyWorkflow 2: MOC generation per domain
orchestrate.pyWorkflow 5: multi-agent orchestration (health, bootstrap, dedup-review, link-enrich, graph-analyze)
engine.pyWorkflow 2/3: decay (Ebbinghaus), touch (graduated), creative, stats, init
search.pyWorkflow 3/4: ranked memory search (BM25 FTS5 + link-graph rerank) — dedup-first lookup
supersede.pyWorkflow 3: deterministic same-entity conflict scan → .graph/supersede-candidates.json
daily.pyEntity extraction from memory files
tests/test_autograph.pySelf-contained tests (temp fixtures)

Files

FileIn package?Purpose
schema.example.jsonYesTemplate — copy and customize (includes domain_rates)
schema.jsonNoYour vault's schema (generated)
schema.local.jsonNoLocal override (gitignored)
references/YesBootstrap workflow, schema docs, card templates, linking protocol

Common Mistakes

MistakeFix
Skipping agent swarm in Phase 2CRITICAL: always run Step 2B. Script alone cannot classify unstructured content. No exceptions.
Using deprecated links subcommandlinks was removed (0.3% match rate). Only swarm-links is available — 81.6% match rate.
Creating cards without linkingAlways follow Workflow 3 — link to hub + 2 siblings immediately. Orphan cards are wasted knowledge.
Creating a near-duplicate instead of updatingWorkflow 3 Step 0 — search.py/grep first. Same subject → UPDATE or SUPERSEDE the existing card, never a second one.
Two contradictory current values on one subjectSUPERSEDE: rewrite the current value (Compiled Truth), move the old one to append-only ## History. Never leave both standing.
Touching archive cards to active directlyUse graduated recall — touch promotes one tier at a time (archive→cold→warm→active).
Running whole-file tools on a giant cardRun cleanup.py first; enforce.py skips files over 10 MiB and reports them.
Sending full vault to one agentUse swarm_prepare.py — bin-packs into ~50K token batches.
Running Wave 2 without Wave 1swarm_reduce.py prepare needs JSONL in .graph/swarm/classifications/.
Using schema.example.json directlyRun discover → generate your own schema.json
Description = title repeatWrite specific search snippet
Status not in enumCheck schema's node_types
Skip dry runAlways run without --apply first
Running link enrich before dedupCreates links to files that get merged/trashed. Dedup first.
Missing OPENROUTER_API_KEYenrich.py reads from OPENROUTER_API_KEY env var.
Only running swarm-links onceRun again with --force to enrich ALL files.

Default Models

CommandDefault modelOverride
tagsgoogle/gemini-3-flash-preview--model flag
swarm-linksgoogle/gemini-2.0-flash-001--model flag

Both are production-tested. Do not change defaults without benchmarking.

Troubleshooting

Error: Schema not found → Create schema.json from discover output, or pass path: enforce.py vault/ my-schema.json

Score drops after enforce → New files without frontmatter. Run engine.py init vault/

Dedup picks wrong canonical → Content richness wins. Enrich the right file first, re-run.

Low match rate on swarm-links (<60%) → Check if LLM returns paths instead of stems. Try --force for second pass.

swarm-links shows 0 matched for some batches → Usually network errors. Results are cached — rerun and only failed batches retry.

Bundled files

The model reads these on demand while the skill is loaded. They are exposed as readable files and are never executed.

Frequently asked questions

What does the Autograph AI skill do?

Schema-as-code enforcement for any Obsidian vault. Zero hardcoded domains. Use when creating vault cards, checking vault health, running schema compliance, deduplicating entities, generating MOC indexes, running decay cycles, bootstrapping a vault, fixing wikilinks, finding orphans or backlinks, extracting entities from daily files, or touching/promoting cards. Do NOT use for content generation or non-vault file operations.

Why use Autograph on TypingMind?

Because you install it once and use it with any model. Autograph is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Autograph in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/smixs/autograph/tree/main/skills/autograph. TypingMind reads its SKILL.md and bundles its files and installs it as a skill you can enable per chat.

Which AI models can use Autograph?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Autograph?

As many as you like. As long as a model supports skills, you can use Autograph with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Autograph AI skill free?

Yes. It is published on GitHub by smixs under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇