If you ask a language model to write in your style, the usual shortcut is to upload a large archive of your writing to a hosted service. That creates two problems: the style signal is mixed with irrelevant material, and the original corpus leaves your machine.
idioleto takes a smaller, local-first approach. It reads a folder of Markdown, plain-text, or PDF files and writes a validated .idiolect JSON profile. The profile contains aggregate writing measurements and selected semantic anchors that a local model workflow can use later.
This tutorial builds a profile from a sample corpus, inspects the result, and explains where the privacy boundary is. The project is early development, so the goal is a reproducible vertical slice rather than a claim of human-level style imitation.
What you will build
By the end, you will have a file with a structure like this:
idioleto/
examples/
corpus/
sample.md
sample.idiolect
The output is JSON, but the .idiolect extension makes its role explicit. The current schema version is 0.1.0. The profile includes a source summary, stylometrics, and semantic anchors. The compiler does not need Ollama or a hosted API.
The repository currently documents version 0.1.0 as unreleased on its main branch. That matters here: the commands below target the current source, not a published package or a stable release tag.
Prerequisites
You need:
- Python 3.11 or newer
- Git
- A folder of writing you are allowed to process
The package declares httpx, pydantic, pypdf, and typer as runtime dependencies. The development extra adds pytest and Ruff. Ollama is optional for the later generate command, not for profile compilation.
Install the current project
Clone the public repository and create an isolated environment:
git clone https://github.com/paladini/idioleto.git
cd idioleto
python -m venv .venv
.venv\\Scripts\\Activate.ps1
python -m pip install -e ".[dev]"
On macOS or Linux, activate the environment with . .venv/bin/activate instead. The project is MIT licensed and publishes its source, schema, examples, tests, security policy, and contribution guidance in the repository.
Confirm that the CLI is available:
python -m idioleto --help
You should see the compile and generate commands. Calling the module is useful during development because it does not depend on the virtual environment placing the console script on your PATH.
Compile a profile
The repository includes a small Markdown corpus at examples/corpus/sample.md. Compile it into the example output path:
python -m idioleto compile `
--input examples/corpus `
--output examples/sample.idiolect
The command should print a message beginning with Wrote and create examples/sample.idiolect. The compile command accepts a directory, validates the input path, creates the output parent directory when needed, and writes UTF-8 JSON.
Open the generated file. Its top-level shape should contain these fields:
{
"schema_version": "0.1.0",
"profile_id": "sample",
"created_at": "...",
"language": "en",
"source_summary": {},
"stylometrics": {},
"semantic_anchors": []
}
The timestamp and measurements depend on the input. Do not compare those values as fixed snapshots. The meaningful check is that the output is valid against the project's typed contract and includes the expected sections.
Verify the output reproducibly
Use Python's standard library to parse the file and inspect the source count without relying on a JSON formatting choice:
python -c "import json; p=json.load(open('examples/sample.idiolect', encoding='utf-8')); print(p['schema_version']); print(p['source_summary']['file_count']); print(sorted(p))"
For the repository sample, the file count should be 1. The command should also show the schema version and the profile's top-level keys. If your own corpus contains unsupported extensions, the compiler only recognizes Markdown (.md), plain text (.txt), and PDF (.pdf).
Run the project's own checks as a second verification step:
python -m pytest -q
python -m ruff check .
The tests exercise the current implementation. They are a useful guard against assuming that a profile is valid merely because it looks like JSON.
Why this works
The compiler separates two kinds of evidence about a writing corpus.
stylometrics records quantitative markers such as average sentence length, type-token ratio, punctuation density, a lightweight passive-voice estimate, and disallowed n-grams. These measurements are compact and can help a later prompt compiler describe broad tendencies.
semantic_anchors stores short, high-signal snippets classified as philosophy, memory, worldview, preference, self-description, or argument pattern. These snippets can give a local model concrete context that aggregate numbers cannot provide.
That separation is practical. Metrics describe recurring form, while anchors preserve selected meaning. A downstream workflow can choose whether to use both, only metrics, or only carefully reviewed anchors.
The profile is also validated with Pydantic contracts. The contract requires a schema version, a timestamp, a language, source counts, bounded metrics, and valid anchor shapes. If an anchor contains an embedding, it must also identify the embedding model. This makes malformed profiles fail close to the compiler instead of surfacing later during generation.
Generate with a local model
The repository also includes a generate command. It sends a profile, a prompt, and a model name to Ollama's local HTTP API, whose default base URL is http://localhost:11434:
python -m idioleto generate `
--profile examples/sample.idiolect `
--prompt "Write a short note about local-first software." `
--model llama3
This step assumes that Ollama is installed, running locally, and has the named model available. The command is not a substitute for evaluating the generated text. Compare the result with your corpus, check for invented facts, and review whether the selected anchors are appropriate for the requested task.
You can save the generated text instead of printing it:
python -m idioleto generate `
--profile examples/sample.idiolect `
--prompt "Draft three concise release notes." `
--model llama3 `
--output examples/draft.txt
The core compiler remains useful even when you do not use this adapter. A profile can be inspected, reviewed, or passed to another local workflow.
Failure modes and security boundaries
The most important failure mode is treating a profile as harmless metadata. An .idiolect file can contain personal snippets and style signals. The schema guide explicitly warns that profiles are not anonymous. Keep generated profiles out of public repositories unless you have reviewed every anchor.
Compilation is designed to work without network access, but installation may download dependencies. The generation adapter makes a local HTTP request to Ollama when you invoke generate; it does not make the corpus compiler upload your source files. Review the configured Ollama URL before using an alternative endpoint.
The project is alpha software and has no released version yet. It does not promise that stylometrics capture every meaningful property of a voice, and semantic anchors can be incomplete or misleading. Treat the output as an inspectable aid, not an identity proof or a guarantee of faithful imitation.
FAQ
Do I need an API key?
No API key is required for compile. The documented generation path uses Ollama locally, but it still requires a locally installed model.
Can I process PDFs?
Yes. PDF is one of the three supported input extensions. Test your own documents because extraction quality depends on whether the PDF contains selectable text.
Does the profile include the entire corpus?
The profile stores counts, aggregate measurements, and selected anchors rather than a verbatim archive. Anchors can still contain sensitive text, so inspect them before sharing the file.
Is 0.1.0 a stable release?
No. The current changelog describes 0.1.0 as unreleased. Pin a commit or review changes before using the current main branch in an important workflow.
Takeaway
idioleto offers a small, understandable boundary for local writing-style experiments: compile a permitted corpus, inspect the resulting JSON, and decide deliberately which profile data a local model may use. Start with a disposable sample, review the anchors, and only then process more personal writing.
Have you found aggregate style metrics, short semantic anchors, or a combination of both more useful when evaluating local writing assistance?
AI assistance disclosure: AI helped organize and edit this tutorial. The commands, project details, limitations, and security notes were checked against the public
idioletorepository and its current source documentation.
Top comments (0)