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
17 changes: 17 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,23 @@ jobs:
- name: Type check
run: mypy src/ scripts/ --ignore-missing-imports

# The version is committed in five places. install.py stamps them from
# src/__init__.py at install time, so drift never breaks an install and stays
# invisible locally — it surfaces as a release that /plugin update declines to
# fetch, because Claude Code keys its cache on .claude-plugin/plugin.json.
versions:
name: Version consistency
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5

- uses: actions/setup-python@v6
with:
python-version: "3.12"

- name: Check version strings agree
run: python scripts/check_versions.py

test:
name: Test (${{ matrix.os }}, Python ${{ matrix.python-version }})
runs-on: ${{ matrix.os }}
Expand Down
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,9 @@ build/
# Environment
.env
*.env.local

# Jekyll (docs/)
docs/_site/
docs/.sass-cache/
docs/.jekyll-cache/
docs/.jekyll-metadata
319 changes: 319 additions & 0 deletions CHANGELOG.md

Large diffs are not rendered by default.

29 changes: 29 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -260,3 +260,32 @@ python3 -m pytest tests/ -v
```

All existing tests must continue to pass after adding a new processor.

## Releasing

`src/__init__.py` holds `__version__` and is the single source of truth — the
installer stamps the manifests from it. But the copies committed in the repo are
what users resolve against, and Claude Code keys its update cache on
`.claude-plugin/plugin.json`: **a release that forgets to bump that file reaches
nobody**, and `/plugin update` reports "already on the latest version".

So a release commit touches all five:

| File | Where |
|------|-------|
| `src/__init__.py` | `__version__` |
| `.claude-plugin/plugin.json` | `version` |
| `.claude-plugin/marketplace.json` | `plugins[0].version` |
| `antigravity/antigravity-plugin.json` | `version` |
| `docs/benchmarks.md` | `Version: **X.Y.Z**` header line |

Plus a new `## [X.Y.Z] - YYYY-MM-DD` section in `CHANGELOG.md`.

Verify before pushing — CI runs the same check and fails the PR otherwise:

```bash
python3 scripts/check_versions.py
```

Version numbers follow [semver](https://semver.org): MAJOR for breaking changes,
MINOR for new features, PATCH for bug fixes. Tag the merge commit `vX.Y.Z`.
82 changes: 77 additions & 5 deletions docs/_config.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
theme: minima
# just-the-docs is not a GitHub Pages native theme, so it can only be used via
# remote_theme — jekyll-remote-theme IS on the safe-mode plugin whitelist, which
# keeps the site building natively from the branch with no Actions workflow.
# Pinned to a tag, not a branch: an unpinned theme means upstream can break this
# site with no commit of ours, and Pages gives no build log worth the name.
remote_theme: just-the-docs/just-the-docs@v0.12.0

title: Token-Saver
# jekyll-seo-tag builds <title> as "page.title | site.tagline" and only
Expand All @@ -22,17 +27,84 @@ repository: ppgranger/token-saver
# front matter are skipped by Jekyll's default collections, so nothing here
# needs an explicit include/exclude list for the .md sources.

minima:
skin: auto
social_links:
github: ppgranger/token-saver
# just-the-docs only styles a page if it uses one of its layouts, and none of
# our sources declare one. Default every page to `default` rather than adding a
# layout line to 34 files.
defaults:
- scope:
path: ""
type: "pages"
values:
layout: "default"

# --- just-the-docs -----------------------------------------------------------

color_scheme: token-saver

search_enabled: true
search:
heading_level: 2
previews: 2
preview_words_before: 3
preview_words_after: 8
tokenizer_separator: /[\s/]+/
rel_url: true
button: false

heading_anchors: true
enable_copy_code_button: true

back_to_top: true
back_to_top_text: "Back to top"

aux_links:
"GitHub":
- "https://github.com/ppgranger/token-saver"
aux_links_new_tab: true

# Sidebar sorting: nav_order first, then title. The 29 processor pages carry no
# nav_order deliberately, so they sort alphabetically and adding a processor
# needs no renumbering. case_insensitive matches how the titles read.
nav_sort: case_insensitive

# Surfaces broken parent/ancestor references as a page on the site instead of a
# silent build success with pages missing from the sidebar.
nav_error_report: true

gh_edit_link: true
gh_edit_link_text: "Edit this page on GitHub"
gh_edit_repository: "https://github.com/ppgranger/token-saver"
gh_edit_branch: "main"
gh_edit_source: docs
gh_edit_view_mode: "tree"

footer_content: >-
Token-Saver is MIT licensed. No LLM calls, no network access, fully
deterministic.

callouts:
note:
title: Note
color: purple
warning:
title: Warning
color: red

# Keep the build to the well-known-safe plugin whitelist GitHub Pages runs
# without a custom Actions workflow. Anything outside this list forces a
# switch to build-via-Actions, which is unnecessary for a static docs site.
# jekyll-include-cache is not optional: just-the-docs calls include_cached in
# seven places and the build hard-fails without it.
plugins:
- jekyll-remote-theme
- jekyll-include-cache
- jekyll-seo-tag
- jekyll-relative-links

exclude:
- .sass-cache/
- .jekyll-cache/

markdown: kramdown
kramdown:
input: GFM
Expand Down
87 changes: 0 additions & 87 deletions docs/_includes/head.html

This file was deleted.

71 changes: 71 additions & 0 deletions docs/_includes/head_custom.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
{% comment %}
just-the-docs include hook: the theme's own _includes/head.html pulls this
file in as the last thing before the closing head element, right after it
invokes the seo tag. Because it is a supported extension point, nothing here
overrides a theme file — the theme keeps full control of its meta tags,
stylesheets, search and favicon assets. JSON-LD is the only addition.

This replaces a full override of minima's head.html, which was necessary only
because minima 2.5.1 (the version GitHub Pages builds with) never calls its
own custom-head hook. just-the-docs has no such gap.

Keep this a Liquid comment block, and never write Liquid tag syntax inside
it — not even as an example. Two separate outages came from ignoring that:

1. As an HTML comment, the seo tag named below still rendered (Liquid
evaluates tags anywhere, comments included). It emits its own HTML
end-comment marker, whose "--" + ">" closed this comment early and
leaked the remaining prose plus a duplicate head element into the page.
2. Rewritten as a Liquid comment, spelling out the opening comment tag in
prose opened a *nested* comment block, so the closing tag below matched
the inner one and the outer block was never closed. That's a hard build
failure: "Liquid syntax error: 'comment' tag was never closed".

Neither hazard went away with the theme switch — the theme still invokes the
seo tag on every page, and nested-comment parsing is pure Liquid. Refer to
tags by name only (seo tag, endcomment), never in brace-percent form.
{% endcomment %}
{%- if page.url == "/" -%}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "SoftwareApplication",
"@id": "https://github.com/ppgranger/token-saver",
"name": "Token-Saver",
"description": "{{ site.description | strip_html | strip_newlines | escape }}",
"applicationCategory": "DeveloperApplication",
"operatingSystem": "Windows, macOS, Linux",
"license": "https://github.com/ppgranger/token-saver/blob/main/LICENSE",
"codeRepository": "https://github.com/ppgranger/token-saver",
"url": "{{ site.url }}{{ site.baseurl }}/",
"offers": {
"@type": "Offer",
"price": "0",
"priceCurrency": "USD"
},
"author": {
"@type": "Person",
"name": "ppgranger",
"url": "https://github.com/ppgranger"
}
}
</script>
{%- elsif page.url contains "/processors/" or page.url == "/benchmarks/" or page.url == "/comparison/" -%}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "TechArticle",
"headline": "{{ page.title | strip_html | strip_newlines | escape }}",
"description": "{{ page.description | strip_html | strip_newlines | escape }}",
"url": "{{ site.url }}{{ page.url | relative_url }}",
"isPartOf": {
"@id": "https://github.com/ppgranger/token-saver"
},
"author": {
"@type": "Person",
"name": "ppgranger",
"url": "https://github.com/ppgranger"
}
}
</script>
{%- endif -%}
33 changes: 33 additions & 0 deletions docs/_sass/color_schemes/token-saver.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Token-Saver color scheme, selected by `color_scheme: token-saver` in
// _config.yml. just-the-docs imports color_schemes/light first and this file
// second, so everything here overrides the light defaults and anything left
// unset falls through to them.
//
// Written for libsass 3.5 (jekyll-sass-converter 1.5.2), which is what GitHub
// Pages' jekyll 3.10 build uses. No @use, no sass:math, no module system —
// those are dart-sass only and would fail the Pages build while compiling
// fine on a modern local toolchain.

$color-scheme: token-saver;

// Green is the compression-savings color already used by the README badge
// (docs/assets/badge-savings.svg, fill #4c1). Reusing it ties the site to the
// artifact people see first on GitHub instead of inventing a second identity.
$ts-green-000: #2da44e;
$ts-green-100: #1f7a3a;
$ts-green-200: #17602c;
$ts-green-300: #10441f;

$link-color: $ts-green-100;
$btn-primary-color: $ts-green-100;
$nav-child-link-color: $grey-dk-100;

$body-heading-color: $grey-dk-300;
$body-text-color: $grey-dk-100;

// A tinted sidebar separates navigation from content without a hard border.
$sidebar-color: #f4f8f5;
$search-background-color: $white;
$table-background-color: $white;
$code-background-color: #f6f8f6;
$feedback-color: darken($sidebar-color, 3%);
1 change: 1 addition & 0 deletions docs/benchmarks.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
title: Benchmarks
description: 22 measured compression scenarios for Token-Saver, sorted by ratio, gated by CI so they cannot regress silently.
permalink: /benchmarks/
nav_order: 3
---

# Token-Saver Compression Benchmarks
Expand Down
3 changes: 2 additions & 1 deletion docs/comparison.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
---
title: How Token-Saver Compares
title: Comparison
description: Token-Saver vs cc_token_saver_mcp, token-optimizer-mcp, and Claude Context Mode — approach, latency, offline support, and whether they can run together.
permalink: /comparison/
nav_order: 4
---

# How Token-Saver Compares
Expand Down
3 changes: 2 additions & 1 deletion docs/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
title: FAQ
description: Answers on privacy, precision guarantees, platform support, and how Token-Saver behaves when it fails.
permalink: /faq/
nav_order: 5
---

# FAQ
Expand Down Expand Up @@ -87,7 +88,7 @@ are numeric thresholds with no code path to abuse.

## Is a specific processor's behavior documented anywhere?

Yes — the [processor reference](index.md#processors) has a page per
Yes — the [processor reference](processors/) has a page per
processor covering what it matches, what it keeps, what it drops, and its
config knobs.

Expand Down
Loading
Loading