installs.me
< cd ~/blog

·4 min read#personas#product

How installs.me Synthesizes a Person: the Pipeline

A persona plugin is not a fine-tune. It's a folder of Markdown that Claude reads on demand, and the entire craft of installs.me is deciding what goes in that folder. Here's the actual pipeline, with the boring parts included, because the boring parts are where quality lives.

Step 1: Sync the sources

A person's judgment is scattered across formats that were never meant to be read together. Blog posts, Google Drive docs, calendar history, call transcripts, old decks, uploaded files. The sync layer normalizes all of it to plain text with provenance: every chunk keeps its source URI, timestamp, and document type.

Provenance matters more than it looks. A pricing opinion from a 2019 board memo and the same opinion from a call last month are not equal evidence. Later stages weight recency and repetition, so the sync layer never throws away metadata to save space.

We also dedupe aggressively at this stage. Founders repost the same essay three places. Calendar exports contain the same recurring meeting 200 times. If you skip dedup, the extraction stage will confidently report that the person's number one belief is "Weekly sync, 30 min."

Step 2: Extract evidence in chunks

You cannot hand Claude 40MB of a person's life and ask "who is this?" Context windows are large but attention is not uniform, and a single-pass summary of that much text produces horoscope output: warm, plausible, useless.

So extraction is map-reduce. Each chunk (a few thousand tokens, split on document boundaries where possible) goes through an extraction pass with a narrow contract: pull out persona evidence, structured as typed claims.

The types that survived iteration:

  • Positions: opinions the person actually argues for, with the argument. "Charge from day one, free pilots teach you nothing" beats "believes in monetization."
  • Voice markers: sentence rhythm, recurring phrases, code-switching (Lautaro writes English with Rioplatense interference and that's a feature), what they never say.
  • Decision patterns: how they choose. Frameworks they invoke by name, heuristics they repeat across years.
  • Biography facts: dates, numbers, names. Rodati, Sirena, the $30M Zenvia exit, Darwin AI. These get triple-checked because a persona that gets its own résumé wrong is dead on arrival.

Every claim carries its source citation. Uncited claims are dropped at reduce time, no exceptions. This is the single most effective anti-hallucination measure in the pipeline: the synthesizer is only allowed to write from the evidence file, and the evidence file is only allowed to contain quoted, sourced material.

The reduce pass merges claims across chunks, counts corroboration, and resolves contradictions in favor of recency (people change their minds, and the plugin should hold their current view, with the old one noted if the shift itself is interesting).

Step 3: Synthesize SKILL.md and references/

Now the shape of the output matters, because Claude Code has opinions about how skills load.

A skill is a SKILL.md with YAML frontmatter (name, description) plus an optional references/ directory. The description is what lives in Claude's context at all times; the body loads when the skill triggers; reference files load only when the body tells Claude to go read them. Three tiers of laziness, and the synthesis stage targets each one deliberately:

  • Description (~2 sentences, always in context): who this person is and the exact trigger phrases. "as Lauta", "in my voice", "advise this founder." If the description is vague, the skill never fires and nothing else matters.
  • SKILL.md body (a few hundred lines, loaded on trigger): the compressed persona. Voice rules, top 10 positions with one-line arguments, the decision frameworks, hard biographical facts, and pointers into references/.
  • references/ (loaded on demand): the deep material. references/positions.md with full argued opinions, references/voice.md with real writing samples, references/bio.md with the timeline. For Lautaro's plugin this is where the lauta.blog essays live in extract form.

The synthesizer writes all of this from the evidence file only. It's a constrained generation problem, closer to compilation than creative writing, and that's on purpose.

Step 4: Package and release

The plugin gets a .claude-plugin/ directory with its manifest, and the marketplace gets a marketplace.json listing it. One hard-won detail: plugin sources served over a URL must be git-backed (git-subdir source). Relative HTTP paths don't error, they silently fail, and you'll spend an afternoon learning that. Verified on Claude Code CLI 2.1.x.

Releases are versioned. When your sources change (new blog post, new quarter of calls), a re-sync re-runs extraction only on new material, merges into the evidence file, and cuts a new release. Installed users pick up the update; the person keeps evolving and the plugin keeps up.

What Claude actually sees

The honest answer: almost nothing, almost always. In a normal session the only footprint is the description, a couple hundred tokens. Say "what would Lautaro tell this founder about pricing?" and the SKILL.md body loads, Claude reads the positions and voice rules, follows the pointer into references/positions.md if it needs the full argument, and answers as him, citing his actual stated views rather than a vibes-based imitation.

That's the whole trick. Not a model that is the person. A retrieval structure so well-organized that a general model, reading it just-in-time, produces the person's judgment on demand.

Install a person

installs.me turns your files, calendar and calls into a Claude Code plugin that thinks like you. Anyone installs it with two commands:

/plugin marketplace add https://installs.me/lautaro
/plugin install lautaro@lautaro-installs