Stylog
Stylometry for text and source code
Stylog measures writing style in natural-language text and source code. It runs locally and provides fingerprints, feature comparisons, population baselines, sparse representations, and fitted authorship verifiers through a CLI and Python API.
Install
pip install stylog # text + Python/JS/TS/C/Rust analysis
pip install "stylog[nlp]" # spaCy linguistic features
pip install "stylog[ml]" # scikit-learn representations
pip install "stylog[data]" # Arrow/Parquet corpus I/O
pip install "stylog[all]" # all optional features
Stylog requires Python 3.12+.
The base package uses Python's tokenize and ast modules for Python source and checked Tree-sitter grammars for JavaScript, TypeScript, C, and Rust.
Commands
| Command | Purpose |
|---|---|
fingerprint |
Measure files and emit fingerprints |
analyze |
Inspect one artifact and its embedded artifacts |
compare |
Compare two artifacts feature by feature |
profile |
Place an artifact against a population baseline |
fit |
Fit an authorship verifier from labeled training data |
verify |
Evaluate two artifacts with a fitted verifier |
represent |
Convert documents to sparse vectors |
report |
Render an existing portable artifact |
benchmark |
Run a declarative benchmark spec |
info |
Report local capabilities, versions, and extras |
See the CLI reference for arguments, options, output formats, and exit codes.
Bare stylog shows a concise command map and exits successfully. Use -h or
--help for full help, stylog COMMAND -h for a workflow, and -V for the
version.
Quick start
Fingerprint
$ stylog fingerprint alice_1.txt --language en --format terminal
Fingerprint
Artifact alice_1.txt
Kind text
Language en
Encoding utf-8
Size 221 bytes; 221 Unicode code points
Features 27 total; 26 ok; 1 insufficient support
Diagnostics none
By default, a single input produces canonical JSON:
stylog fingerprint alice_1.txt | jq '.features[] | select(.status != "ok")'
Write a directory as JSONL:
stylog fingerprint src/ --output fingerprints.jsonl
Analyze
$ stylog analyze app.py
Analysis
Artifact app.py
Kind code
Language python
Embedded text 3 comments/docstrings
Diagnostics none
Feature families
FAMILY STATUS
code.python.comments 5 total; 5 ok
code.python.lexical 6 total; 5 ok; 1 insufficient support
code.python.naming 8 total; 6 ok; 2 insufficient support
code.python.structure 17 total; 10 ok; 7 insufficient support
...
Embedded artifacts are the docstrings and comment blocks found inside the source file; each is analyzed separately.
Compare
compare reports a distance for each comparable feature.
$ stylog compare alice_1.txt alice_2.txt
Comparison
Left alice_1.txt
Right alice_2.txt
Comparable features 17
Diagnostics none
text.lexical
FEATURE METRIC DISTANCE SUPPORT L/R UNIT
ttr_casefold ABS 0.00757576 44/46 word proportion points on [0,1]
word_length W1 0.469697 44/46 word word code points
...
$ stylog compare alice_1.txt bob_1.txt
Comparison
Left alice_1.txt
Right bob_1.txt
Comparable features 17
Diagnostics none
text.lexical
FEATURE METRIC DISTANCE SUPPORT L/R UNIT
ttr_casefold ABS 0.132064 44/51 word proportion points on [0,1]
word_length W1 2.76229 44/51 word word code points
...
Baselines
A baseline is a versioned reference distribution built from one or more documents in your corpus.
Build one with the Python API:
from pathlib import Path
import stylog
from stylog.serialization.jsonio import write_json_atomic
fps = [
stylog.fingerprint_file(path, language="en")
for path in Path("corpus").glob("*.txt")
]
baseline = stylog.build_baseline(
fps,
baseline_id="my-base",
kind="text",
language="en",
domain="news",
)
write_json_atomic("my-base.stylog-baseline.json", baseline)
Profile a document against it:
$ stylog profile alice_1.txt \
--baseline my-base.stylog-baseline.json \
--language en
Profile
Subject alice_1.txt
Baseline my-base 1.0.0
Features 17
Diagnostics none
FEATURE OBSERVED N MIDRANK % ROBUST Z
text.function_words.en.token_share 0.545455 24 100 4.93604
text.lexical.hapax_token_share_casefold 0.75 24 10.4167 -2.20666
text.lexical.ttr_casefold 0.840909 24 12.5 -2.28798
...
Baseline references containing a path separator or ending in .json resolve directly as paths. Baseline ids are resolved through baseline.search_paths, followed by:
platformdirs.user_data_path("stylog") / "baselines"
Authorship verification
Verification evaluates two documents under a fitted model and returns same_author, different_author, or abstain. Each verdict expresses model-relative support for an authorship hypothesis.
Training uses a stylog.verifier-training manifest that references a checksummed stylog.dataset manifest. Labeled pairs belong to author-disjoint train, tuning, and calibration populations. Train pairs fit the model and calibration pairs fit thresholds/calibration. Stylog records tuning-pair identity only; any hyperparameter selection using that population happens externally before stylog fit.
schema = "stylog.verifier-training"
schema_version = "0.1.0"
id = "demo-training"
dataset = "dataset.toml"
[verifier]
kind = "text"
l2_lambda = 1.0
min_support_fraction = 0.9
min_class_support_fraction = 0.8
min_pairs = 50
threshold_rule = "calibration_quantile_band"
threshold_alpha = 0.05
calibration_method = "platt"
[[pair]]
left = "t23663134a2a7a629"
right = "t38db1c322047e46a"
label = "same"
population = "train"
# ... more pairs ...
Fit the model:
$ stylog fit training.toml -o model.json
Diagnostic INFO VERIFIER_ELIGIBILITY candidate_feature_count=17 eligible_pair_count=150 ...
Verifier ID 3f71213b3f5be729d1f77b0b12ca23b3e4c45b19fcd0ca067d9efe183f8a9601
Verify two documents:
$ stylog verify doc_a.txt doc_b.txt --model model.json --language en
Verification
Verdict same_author
Model score 0.901019 (range (0,1); not a probability)
Probability 0.94066 same-author (platt; calibration-population conditional)
Features 16 used; 0 unavailable
Model stylog.verifier.logreg/1 1.0.0
Verifier ID 3f71213b3f5be729d1f77b0b12ca23b3e4c45b19fcd0ca067d9efe183f8a9601
Left doc_a.txt
Left fingerprint 8ccdfc25e1a9f9b20379aa90d5795abaea2907ce17d07f56a7b9f47929206d88
Right doc_b.txt
Right fingerprint 9d360c97af337f0a162c2e3cae46c5f155c7e16dd9de76c5408ce66c90c96c38
Diagnostics none
score is the model's unitless decision value. Models fitted with Platt calibration on a disjoint calibration split also report probability.
The verifier returns abstain when the available evidence is insufficient or the result falls within its uncertainty region. Typed reasons include insufficient_evidence and uncertain.
Use --format json for the machine-readable Verification object.
A fitted VerifierFit is stored as JSON. The fitting solver is implemented in pure Python.
From Python:
import stylog
model = stylog.load_verifier("model.json")
verification = stylog.verify_files(
"doc_a.txt",
"doc_b.txt",
model,
)
Verification records bind the hashes of both input fingerprints and the fitted model.
Representations
Install stylog[ml] to build sparse representations.
Fit a word-TFIDF vocabulary:
stylog represent docs/ \
--representation word-tfidf \
--fit-output fit.json
Transform another document with the saved fit:
stylog represent new-doc.md --fit-resource fit.json
Representation fits and vectors use the stylog.representation-fit and stylog.representation JSON schemas and record their backend provenance.
Common shortcuts:
-o --output
-m --model
For representation fits, --model and -m are aliases for --fit-resource.
The pre-0.2 command names verify-fit and capabilities remain available as hidden aliases for fit and info.
Python API
import stylog
fp = stylog.fingerprint_text(
"Don't re-enter now.",
language="en",
)
fp = stylog.fingerprint_file("app.py")
bundle = stylog.analyze_file("app.py")
comparison = stylog.compare_files("a.py", "b.py")
profile = stylog.profile_fingerprint(fp, "my-base")
Results are frozen Pydantic v2 models. Canonical JSON (RFC 8785) and hashing helpers live in stylog.serialization; the machine-readable contracts are the schemas in schemas/. See the Python API reference.
Documentation
- Getting started — a guided first workflow
- CLI reference — every command, option, and exit code
- Python API — the supported Python interface
- Methodology — how Stylog measures, compares, and decides
- Limitations — interpretation, uncertainty, failure modes
- Specification v0.1 — the normative contract
Development
pip install -e ".[all,dev]"
python -m pytest
python tools/generate_schemas.py --check
License
MIT. See LICENSE.
Metadata
Release files for stylog 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| stylog-0.1.0.tar.gz | 767.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| stylog-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 938.3 kB
Release files / stylog-0.1.0.tar.gz
| Download URL | stylog-0.1.0.tar.gz |
|---|---|
| Size | 767.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
18f0e817fdaf0b4a254186fc92e59d6353383d87aef9559ba93691f04011c0e1
|
|
BLAKE2b-256 checksum How to use checksums |
d84a8c52679f3496bec0f845085442a500e86441d9ecd733d0c758c6e66ae692
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 2, 2026.
Transparency logRelease files / stylog-0.1.0-py3-none-any.whl
| Download URL | stylog-0.1.0-py3-none-any.whl |
|---|---|
| Size | 170.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5b37633d8ca38940b0568be4a8edda5e1550148e4c84dc27c6d8a25a78b7057f
|
|
BLAKE2b-256 checksum How to use checksums |
0ff746975981778f0bd5d31cf0b1adf7f09cb912d5dfae42533cbb26d57c9197
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 2, 2026.
Transparency log