Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions .github/ISSUE_TEMPLATE/bug.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: Something's broken
description: A command fails, does nothing, or does something other than what the docs promise
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
Thanks for the report. **Don't paste session transcripts, wiki pages, or anything from a work context** — this repo is public and its history is permanent. Describe the shape of the problem, or build a synthetic file that reproduces it.
- type: input
id: version
attributes:
label: Version
description: Output of `crate --version`, plus your OS and Python version.
placeholder: crate 0.1.0 · macOS 15.5 · Python 3.13
validations:
required: true
- type: textarea
id: command
attributes:
label: Command and full output
description: The exact command you ran and everything it printed. Paste text, not a screenshot.
render: shell
validations:
required: true
- type: textarea
id: expected
attributes:
label: What you expected instead
description: If the README, `--help` or a slash command promised something different, quote the line. A promise that no longer matches the code is a real bug and worth its own report.
validations:
required: true
- type: dropdown
id: area
attributes:
label: Which part
options:
- Capture (the Stop hook, crate capture)
- A vault command (init, upgrade, index, lint, …)
- A slash command (/ingest, /ask, /daily, /lint)
- The docs are wrong
- Not sure
validations:
required: true
- type: textarea
id: log
attributes:
label: Capture log
description: If a session card didn't appear, the last few lines of `~/.claude/crate-capture.log`. Capture fails quietly by design, so this is usually the only place the reason shows up. Redact any paths you'd rather not publish.
render: shell
validations:
required: false
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
blank_issues_enabled: true
24 changes: 24 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!-- One deliverable per branch, one issue per deliverable. The issue is the spec. -->

Closes #

## What this changes



## Where the boundary falls

<!-- Anything with a single right answer is code; judgment is a prompt (ADR-0004, ADR-0008). Tick what this touches. -->

- [ ] CLI — a deterministic primitive
- [ ] A parser or the card core
- [ ] A slash command / the vault schema
- [ ] `docs/` only

## Checklist

- [ ] No real session data, vault content, client names or internal paths — fixtures are synthetic
- [ ] `uv run ruff check .` and `uv run ruff format --check .` pass
- [ ] `uv run pytest -q` passes
- [ ] `uv tool install --editable . && crate --version` works
- [ ] An ADR if a real alternative was rejected — and none if one wasn't
35 changes: 35 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Changelog

Notable changes to `crate-wiki`. The design and its rejected alternatives live in [docs/adr/](docs/adr/); this file records what changed for someone using the tool.

## Unreleased

Nothing yet.

## 0.1.0 — 2026-08-28

First public release. The loop closes: a session captures itself for free, and four operations turn captured sessions into a wiki that gets denser as you use it.

### Capture — free, deterministic, automatic

- **Claude Code sessions capture themselves** through a Stop hook (`crate install-hook`), in pure Python at zero token cost. It fails quietly and never blocks session exit, logging every outcome to `~/.claude/crate-capture.log` ([ADR-0002](docs/adr/0002-free-capture-paid-synthesis.md)).
- **The parser discards rather than converts.** It walks Claude Code's `parentUuid` tree to the live leaf so rewinds and abandoned branches never replay as work you did, and drops `tool_result` bodies and `thinking` blocks — roughly a tenth the size, carrying nearly all the signal, which is what makes synthesis affordable.
- **Codex sessions too**, through a second adapter over a shared card core ([ADR-0014](docs/adr/0014-shared-card-core-per-source-adapters.md)). Codex has no session-exit hook, so it's swept on demand with `crate capture codex` or `/fetch-codex`.
- **A day of a session is a card** ([ADR-0015](docs/adr/0015-a-day-of-a-thread-is-a-card.md)). A thread resumed across three days is three files, each dated to its own day and carrying that day's branch, duration and tool version. A rewind re-renders the day it changed, in place ([ADR-0016](docs/adr/0016-a-rewind-re-renders-the-day-it-changed.md)).
- **Cards are dated in local wall-clock time** ([ADR-0013](docs/adr/0013-local-session-timestamps.md)), so work after midnight lands on the day you did it.
- **Each card records the day's token usage** — input, output and cache read/write kept separate, with the model. The dollar cost is deliberately left outside the engine, where the rate table can age without the card going stale ([ADR-0018](docs/adr/0018-tokens-are-captured-cost-is-external.md)).

### The four operations — paid, and only when you ask

- **`/ingest`** folds a raw source into the wiki, stopping to show you its takeaways and a numbered page plan before it writes anything. There's no flag to skip that step.
- **`/ask`** queries the wiki and promotes answers worth keeping to `wiki/syntheses/`, adding no command of its own ([ADR-0011](docs/adr/0011-ask-and-the-promoted-synthesis.md)).
- **`/daily`** writes an account of a day, reading session cards straight out of `raw/` with no ingest required ([ADR-0012](docs/adr/0012-daily-reads-raw-and-earns-a-command.md)).
- **`/lint`** reports and never repairs ([ADR-0020](docs/adr/0020-the-linter-reports-and-never-repairs.md)). `crate lint` answers the five questions with a single right answer — dead wikilinks, orphans, a drifted `index.md`, a page citing a private or missing source — and the prompt asks only the four that need judgment.

### The vault

- **`crate init --scope work|personal`** scaffolds an Obsidian vault: the schema, the tree, the templates and a git repo. A work vault has no journal and refuses to push anywhere ([ADR-0001](docs/adr/0001-local-only-work-vault.md)).
- **Layer 3 is split.** `CLAUDE.md`/`AGENTS.md` are the engine's and `crate upgrade` refreshes them; `CONVENTIONS.md` is yours and the engine never writes it again ([ADR-0010](docs/adr/0010-conventions-file-and-upgrade-baseline.md)).
- **`crate upgrade` knows what it wrote.** A baseline of content hashes tells "the template moved" apart from "you edited this", so an edited file is reported rather than clobbered. `--adopt` claims a vault that predates the baseline; `--dry-run` shows what would change.
- **Staleness is a content comparison, not a timestamp** ([ADR-0017](docs/adr/0017-staleness-is-a-content-comparison.md)) — `git checkout` rewrites every mtime in a vault, which would report a fresh clone as entirely stale.
- **Deterministic primitives** the operations call at the points where the answer is fixed: `crate pending`, `day`, `new`, `extend`, `index`, `log`, `fmt`, `lint`.
27 changes: 27 additions & 0 deletions CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Contributor Covenant Code of Conduct

## Our Pledge

We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.

## Our Standards

Examples of behavior that contributes to a positive environment include demonstrating empathy and kindness toward other people, being respectful of differing opinions and experiences, giving and gracefully accepting constructive feedback, accepting responsibility and apologizing to those affected by our mistakes, and focusing on what is best for the overall community.

Examples of unacceptable behavior include the use of sexualized language or imagery and unwelcome sexual attention or advances, trolling, insulting or derogatory comments, personal or political attacks, public or private harassment, publishing others' private information without explicit permission, and other conduct which could reasonably be considered inappropriate in a professional setting.

## Enforcement Responsibilities

Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.

## Scope

This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement by opening an issue or contacting the maintainer through GitHub. All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the reporter of any incident.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 2.1, available at https://www.contributor-covenant.org/version/2/1/code_of_conduct.html.
39 changes: 39 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Contributing

Thanks for looking. Here's the honest state of things.

## Pull requests

**I'm not taking pull requests right now.** This is a solo project working through a numbered set of deliverables, one per issue, and each issue is the spec for the change that closes it. A PR arriving outside that sequence is one I'd have to decline, and I'd rather say so here than waste your afternoon.

That will change once the roadmap in [Milestone 3](https://github.com/bmxcode/crate-wiki/milestone/3) is done. Until then, the useful contribution is an issue.

## Issues

Genuinely welcome, and the more specific the better:

- **A bug** — what you ran, what happened, what you expected. `crate --version`, your OS, and your Python version help. **Don't paste session transcripts, vault content, or anything from a work context** — a redacted description of the shape of the problem is enough, and this repo's history is public and permanent.
- **A command that lies** — the README and `--help` make promises, and promises rot. If one of them doesn't match what the code does, that's a real bug and I want it.
- **A design decision that looks wrong** — read the [ADR](docs/adr/) first if there is one, since it will name the alternative that was already rejected and why. If the reasoning doesn't hold, say so; that's worth more than a patch.

## Running the checks

```bash
uv run ruff check .
uv run ruff format --check .
uv run pytest -q
uv tool install --editable . && crate --version
```

CI runs all of these plus a check that the *installed* command works, which is where a broken entrypoint hides. System Python on macOS is 3.9 and this project needs ≥3.11 — go through `uv`, never bare `python3`.

Secrets are scanned on both sides. Install the local hook once per clone:

```bash
brew install gitleaks
pre-commit install
```

## Test data

**Fixtures are synthetic, always.** The temptation is to copy a real session out of `~/.claude/projects/` to test the parser. Don't — this repo's git history is exposed retroactively, and one such commit is permanent.
Loading
Loading