Documentation

Proselign is at milestone M0: the command-line contract, voice storage and fidelity checks are in place; style transfer quality depends on the local model you connect. Expect changes before 1.0.

Install

Ubuntu (PPA)

Ubuntu 22.04, 24.04 and 26.04 LTS. Packages are built for the architectures the local model tooling supports:

ArchitectureTierLocal inference
amd64, arm64Fullllama.cpp (CPU or GPU), Ollama, vLLM
ppc64el, s390xCPU-onlyllama.cpp or the vLLM CPU backend. No Ollama and no GPU acceleration. Expect a quantized 7–9B model to be usable but slow on many-core POWER and Z systems.
sudo add-apt-repository ppa:bceverly/proselign
sudo apt update
sudo apt install proselign

Debian package

Download the .deb for your architecture from the releases page, check it against SHA256SUMS, then:

sudo apt install ./proselign_*_amd64.deb

pip

Any system with Python 3.10 or newer. Proselign has no third-party runtime dependencies.

pip install proselign-*-py3-none-any.whl

From source

git clone https://github.com/bceverly/proselign
cd proselign
sudo make install          # into /usr/local; PREFIX=~/.local for a user install

Run a local model

Proselign rewrites through any server that speaks the OpenAI-compatible chat API. By default it expects one at http://127.0.0.1:8080/v1.

llama.cpp

llama-server -m Qwen2.5-7B-Instruct-Q4_K_M.gguf --host 127.0.0.1 --port 8080

Ollama

ollama pull qwen2.5:7b-instruct
export PROSELIGN_ENDPOINT=http://127.0.0.1:11434/v1
export PROSELIGN_MODEL=qwen2.5:7b-instruct

IBM POWER and Z (CPU-only tier)

Build llama.cpp from source (it includes POWER and Z vector optimizations) and run llama-server as above, or use vLLM's CPU backend. On s390x, which is big-endian, use a big-endian GGUF model: convert one with llama.cpp's gguf-py tools or download a published big-endian build.

A 4-bit 7–9B model runs well on a 12–16 GB GPU; larger models are worth evaluating on 24–32 GB cards. Bigger is not automatically better for style fidelity, so test with your own writing. Model weights carry their own licenses, separate from Proselign's.

Quick start

# 1. Learn a voice from your own .txt and .md files
proselign train --voice Bryan ~/Documents/Writing/

# 2. Rewrite: stdout carries the result and nothing else
cat draft.md | proselign --voice Bryan > final.md

# 3. Be conservative with a sensitive document
proselign --voice Bryan --strict --strength 0.3 < contract-summary.md

Try the pipeline without a model: --backend mock echoes text through every stage (segmentation, protection, validation), which is useful in scripts and CI.

Command reference

CommandWhat it does
proselign --voice NAME [FILE...]Rewrite stdin (or files; - is stdin) in a voice. Same as proselign rewrite.
proselign train --voice NAME PATH...Learn a voice from .txt/.md files. --append re-learns with additional documents.
proselign voicesList voices: id, name, document count (tab-separated).
proselign inspect NAMEPrint a voice's profile as JSON.
proselign export NAME [-o FILE]Write a portable .proselign archive. Corpus paths are omitted unless --include-sources.
proselign import FILE [--force]Install a voice from an archive. Nothing in an archive is ever executed.
proselign delete NAMEPermanently remove a voice.

Rewrite options

OptionMeaning
--strength 0.0–1.0Degree of stylistic change. Default 0.5.
--format markdown|textHow input is segmented. Default markdown.
--strictFail (exit 4) instead of keeping the original text when a chunk fails fidelity checks.
--backend openai-compat|mockInference backend.
--endpoint URL, --model NAMEWhere and what to call.
--offlineRefuse any endpoint that is not loopback.
--seed NSampling seed for reproducible runs (0–4294967295).
--max-chunk-tokens NUpper bound on each rewritten chunk. Default 1500.
--json-diagnosticsWrite a JSON run report to stderr.

Exit status

CodeMeaning
0Success.
1Unexpected error.
2Usage error: bad arguments or unreadable input.
3Voice error: unknown, invalid or conflicting voice.
4Validation error: a rewrite failed fidelity checks under --strict.
5Backend error: the endpoint is unreachable or replied badly.

Fidelity checks

Before a chunk is rewritten, Proselign records its protected tokens: numbers and currency, percentages, URLs, e-mail addresses, quotations, citations like [3] and inline code. After the rewrite, every token must still be present as many times as before. A failure is retried with the specific problems as feedback; if retries fail, the original text is kept and a warning goes to stderr, or with --strict the run fails with exit status 4.

Fenced code blocks, indented code, pipe tables, HTML blocks and YAML front matter are copied byte for byte and never sent to the model.

Voice format

A voice is a JSON manifest stored in $XDG_DATA_HOME/proselign/voices/<id>/voice.json (by default ~/.local/share/proselign/), readable only by you. It keeps objective measurements (metrics) apart from interpretive hints (style):

{
  "schema_version": 1,
  "voice_id": "bryan",
  "display_name": "Bryan",
  "style": { "tone": ["conversational"], "sentence_length": "short", "paragraphing": "compact" },
  "metrics": { "sentence_length_words": { "mean": 13.4, "median": 12.0, "stdev": 6.1 }, "...": "..." },
  "corpus_summary": { "documents": 214, "words": 186402 },
  "license_and_consent": { "raw_examples_exportable": false }
}

Exported .proselign archives are gzip'd tar files containing only that manifest. Import accepts nothing else: no other members, no links, no oversized files, no executable formats.

Configuration

VariableMeaning
PROSELIGN_BACKENDDefault for --backend.
PROSELIGN_ENDPOINTDefault for --endpoint.
PROSELIGN_MODELDefault for --model.
PROSELIGN_HOMEOverride the data directory entirely.
XDG_DATA_HOMEBase of the default data directory.

Security & privacy

Report vulnerabilities privately as described in SECURITY.md.