Auditable qualitative coding
Move from raw interview transcripts to a traceable codebook, exact excerpts, analytic memos, and theory exports—without losing the path from a claim back to its source.
Explore a finished example. Search and filter coded excerpts from twenty public-domain letters exchanged by John and Abigail Adams in the interactive HTML explorer generated by Bewley.
01 Orientation
Bewley is a local-first command-line workspace for coding interviews, field notes, open-ended responses, and other UTF-8 text. It is designed for analyses where interpretation matters, but so do provenance and recovery.
Evidence stays exact
Annotations point to a whole document, an inclusive line range, or an exact byte span.
History is append-only
Edits and undo operations become events. Earlier analytic decisions remain inspectable.
Codes can evolve
Rename, merge, split, nest, and link codes as distinctions sharpen.
Outputs stay portable
Export quotes, snippets, theory structures, narratives, or standalone HTML.
02 The local data model
| Object | Role | Why it matters |
|---|---|---|
| Document | A versioned UTF-8 source | Preserves the material being interpreted. |
| Code | A named analytic category | Makes the codebook explicit and revisable. |
| Annotation | A code attached to evidence | Connects an interpretation to an exact passage. |
| Memo | An analytic note | Records comparisons, hypotheses, and exceptions. |
| Event | An append-only state change | Provides history, audit, and non-destructive undo. |
.bewley/. The SQLite index is derived state and can be rebuilt.03 Installation
pip install "git+https://github.com/expectedparrot/bewley.git"
bewley --help
bewley docs list
For local development, clone the repository and install it in editable mode:
git clone https://github.com/expectedparrot/bewley.git
cd bewley
pip install -e .
pytest -q
--cwd option. Run every project command from the directory containing .bewley/.04 Start a project
Keep a small pilot corpus inside the project so paths remain stable and the first codebook can be reviewed before scaling.
mkdir customer-interviews
cd customer-interviews
mkdir corpus
cp /path/to/interviews/*.txt corpus/
bewley init
bewley add corpus/interview-01.txt
bewley add corpus/interview-02.txt
bewley list documents
bewley status
Read the pilot set before formal coding. Note recurring language, surprising cases, the unit of analysis, and the research question the codes must help answer.
Optional agent-run open coding
Bewley packages current document revisions as EDSL Jobs; the ep CLI executes them, and Bewley audits the Results before producing candidates for review.
Configure EDSL once per workspace
Use the EDSL CLI to authenticate and check connectivity. Login stores the Expected Parrot key for the working directory; keep the resulting .env private and out of version control.
ep auth login
ep auth status
ep check
# Optional: inspect or manage named environments
ep profiles list
ep profiles current
ep profiles --help
See EDSL’s Managing Keys guide for Expected Parrot and model-provider keys.
bewley open-coding jobs --output jobs.ep --pilot 5
ep run jobs.ep --model <model-name> --output results.ep
bewley open-coding ingest results.ep --jobs jobs.ep
qualitative-analysis/candidate_codes.csv; it does not create codes or annotations.05 Code exact evidence
Create a compact starter codebook, with descriptions that distinguish neighboring concepts. Then attach each code at the narrowest useful scope.
bewley code create onboarding_friction \
--description "Difficulty reaching an initial successful outcome"
# Lines are 1-based and inclusive.
bewley annotate apply onboarding_friction corpus/interview-01.txt \
--lines 18:24
# Bytes are 0-based with an exclusive end.
bewley annotate apply onboarding_friction corpus/interview-02.txt \
--bytes 412:603
bewley show snippets --code onboarding_friction
--document, --lines S:E, or --bytes S:E. Prefer spans for claims that will later need direct quotations.06 Refine the codebook
Qualitative coding is not a one-pass labeling exercise. Review excerpts together and revise categories when a distinction repeatedly matters.
bewley code rename setup_problems onboarding_friction \
--description "Difficulty reaching an initial successful outcome"
bewley code create unclear_guidance
bewley code set-parent unclear_guidance onboarding_friction
bewley code link onboarding_friction early_churn causes \
--memo "Repeated in four interviews"
bewley code list --tree
bewley code links onboarding_friction
Use merge for synonyms, split for a code that hides meaningful variation, hierarchy for “is a kind of,” and links for analytic relationships such as causes, enables, or contradicts.
07 Constant comparison and memos
Retrieve coded evidence across the corpus, compare positive and deviant cases, and write down why the comparison changes your interpretation.
bewley query 'onboarding_friction & early_churn'
bewley query 'onboarding_friction & !early_churn'
bewley memo add --code onboarding_friction \
"Friction predicts churn mainly when no human recovery occurs."
bewley memo add --document corpus/interview-07.txt \
"Deviant case: severe setup friction, but strong support restored trust."
Quote boolean expressions because &, |, !, and parentheses also have meaning to a shell.
08 Export evidence and theory
bewley export quotes --all --format jsonl --human > quotes.jsonl
bewley export html --output coded-corpus.html
bewley export theory --format json --output theory.json
bewley export theory --format mermaid --output theory.mmd
bewley export plots --output-dir plots
bewley export narrative --output narrative.md
See the result of bewley export html in the interactive Adams letters explorer.
Descriptive plots, not findings
Plots help audit the shape of the coding work: which codes dominate, which documents received disproportionate attention, and which codes appear in the same documents. They are diagnostics for returning to the evidence—not statistical tests.
Before reporting a finding, inspect the export and confirm that its excerpts are non-empty, correctly scoped, and representative of the pattern. Treat a generated narrative as an inventory to interpret, not as a substitute for reading the evidence.
09 Integrity and recovery
bewley status
bewley history
bewley fsck
bewley rebuild-index
# Undo by appending a compensating event:
bewley undo <event_id>
Run fsck before handing artifacts downstream. If a source document changes, review any conflicted annotations and resolve them against the new revision rather than silently accepting shifted text.
10 Command map
| Need | Command family |
|---|---|
| Import or revise sources | add, update, list documents |
| Run agent-assisted open coding | open-coding jobs, ep run, open-coding ingest |
| Build the codebook | code create|rename|merge|split|set-parent|link |
| Attach and inspect evidence | annotate apply|show|remove|resolve, show snippets |
| Compare cases | query, code coverage |
| Record interpretation | memo add|list|show|edit |
| Publish artifacts | export quotes|html|plots|theory|narrative |
| Inspect methodology | docs show getting-started|workflow|commands|grounded-theory |
11 Agent-facing JSON contract
Bewley is designed to be driven by agents. Every command emits exactly one versioned JSON envelope by default. Branch on ok; do not infer success from the shape of data.
{
"schema_version": "1.0",
"ok": true,
"command": ["bewley", "status"],
"data": {"documents": 20, "codes": 7},
"warnings": [],
"next_actions": []
}
Failures replace data with a structured error and exit nonzero. Suggested actions use argv arrays and declare whether they mutate state, require network access, or require user approval.
bewley capabilities
bewley agent status
bewley agent schema envelope
bewley agent schema action
--human or -H only for terminal presentation. Agents should consume the default envelope.