Skip to content

Releases

ctxpack v0.1.16

Choose a tag to compare

@la2278647-arch la2278647-arch released this 28 Sep 05:48

What's changed in v0.1.16

The MCP parity release: the server's analytic tools now walk the tree the
same way the CLI does, and the arguments they advertise actually take effect.

  • MCP repo_map honours no_gitignore and hidden — the flags were
    declared in the schema but ignored; now a caller asking for
    no_gitignore: true really gets the unfiltered tree. It also reads
    contents like the CLI's map, so totals agree.
  • MCP count_tokens reads contents like the CLI's tokens — the same
    tree previously produced two different totals depending on which interface
    you asked; max_size still caps the reading.

Plus the walk-flag integration series: every
--include/--exclude/--max-size/--depth/--hidden/gitignore behavior
now has a test at both the CLI and MCP layers.

Full changelog: https://github.com/la2278647-arch/ctxpack/blob/v0.1.16/CHANGELOG.md

Assets are the eight cross-compiled release binaries plus SHA256SUMS.txt.

ctxpack v0.1.15

Choose a tag to compare

@la2278647-arch la2278647-arch released this 28 Sep 00:42

What's changed in v0.1.15

The empty-diff release: both frontends now treat "nothing changed" as a
normal result.

  • diff --format json emits an envelope even when nothing changed —
    scripts can json-parse every diff run; the stderr note stays and respects
    --quiet.
  • MCP diff_repo reports an empty diff as a success, not an error — json
    gets the same empty envelope as the CLI.

Plus a long tail of hardening since v0.1.14: empty-directory envelopes for
both frontends, --top 0 semantics across all four top-taking commands,
--include/--exclude path globs and their pack/tokens integration,
--max-size's estimate behavior on map, the window/limit/reserve
invariants on both json envelopes, and a gofmt sweep.

Full changelog: https://github.com/la2278647-arch/ctxpack/blob/v0.1.15/CHANGELOG.md

Assets are the eight cross-compiled release binaries plus SHA256SUMS.txt.

ctxpack v0.1.14

Choose a tag to compare

@la2278647-arch la2278647-arch released this 27 Sep 21:51

What's changed in v0.1.14

The parity release: the CLI's tokens --json fit envelope and the MCP
count_tokens envelope are now identical field for field —
model/vendor/window/used/limit/fits/pct_used — so a script
consuming both interfaces needs exactly one parser.

  • tokens --json fits now carry vendor and window (the raw window,
    alongside limit). The csv output is unchanged.
  • MCP count_tokens fits rename name to model, matching the CLI.
  • smoke checks install.sh --help does not touch the network, so the
    installer's help branch cannot rot into a version install.

Full changelog: https://github.com/la2278647-arch/ctxpack/blob/v0.1.14/CHANGELOG.md

Assets are the eight cross-compiled release binaries plus SHA256SUMS.txt.

ctxpack v0.1.13

Choose a tag to compare

@la2278647-arch la2278647-arch released this 27 Sep 20:21

What's changed in v0.1.13

  • Installers learn --help — install.sh --help prints the usage and
    exits without downloading; install.ps1 gets the same branch.
  • commandscheck now runs the invocations in examples/diff-demo/README.md
    — the <repo> placeholder is rewritten to a scratch repository before
    splitting, so the documented diff commands run for real.
  • help --help / help -h show the help instead of an
    unknown command "--help" error.
  • tokens --top now means "the N largest context windows" in all three
    formats, matching models --top (it used to cut the registration order).
  • MCP count_tokens top fixed to the same window semantics as the CLI.
  • A bad --output path no longer calls os.Exit(1) — it returns exit
    code 1 like any other runtime error, and is now testable.
  • The (still doc-only) workflow's release job builds with Go 1.26,
    matching the test matrix.

Full changelog: https://github.com/la2278647-arch/ctxpack/blob/v0.1.13/CHANGELOG.md

Assets are the eight cross-compiled release binaries plus SHA256SUMS.txt.

ctxpack v0.1.12

Choose a tag to compare

@la2278647-arch la2278647-arch released this 27 Sep 17:40

What's changed in v0.1.12

  • Bash, zsh and fish shell completion for every command and flag —
    scripts/completion.bash, scripts/completion.zsh, scripts/completion.fish.
  • smoke verifies the completion tables against the help text in both
    directions, and caught a real drift on its first run (--quiet was missing).
  • version --short prints just the semantic version (0.1.12), identical
    across version/--version/-v.
  • MCP version tool — the build identity alone, without a full doctor
    report; its JSON envelope matches the CLI's version --json.
  • -h/--help return 0 on every subcommand, and help <command>
    validates the command name.
  • The (still doc-only) GitHub Actions workflow now runs the remaining
    make ci guards, produces the SHA256SUMS.txt the installers parse, and
    tests Go 1.21 through 1.26.
  • commandscheck no longer reports real variables as unread — the two
    CTXPACK_TAP/CTXPACK_BUCKET variables read by check-release.sh are
    recognized.

Full changelog: https://github.com/la2278647-arch/ctxpack/blob/v0.1.12/CHANGELOG.md

Assets are the eight cross-compiled release binaries plus SHA256SUMS.txt.

ctxpack v0.1.11

Choose a tag to compare

@la2278647-arch la2278647-arch released this 27 Sep 14:34

What's changed in v0.1.11

  • version --json — machine-readable build identity for scripted consumers.
  • models --csv and tokens --csv — the lookup tables as CSV,
    mirroring the --json field names (name,context_window,vendor and
    model,used,limit,fits,pct_used).
  • MCP list_models now accepts vendor, top and sort; MCP
    repo_map
    accepts top for a flat largest-files list — both matching
    their CLI commands.
  • map --top header fix — says "by tokens"/"by bytes", the real ranking
    key, instead of the misleading --sort default of "name".
  • Model table cleanup — removed the legacy qwen2.5 alias (duplicate of
    qwen-2.5-72b); the table is 30 models across 7 vendors.

Full changelog: https://github.com/la2278647-arch/ctxpack/blob/v0.1.11/CHANGELOG.md

Assets are the eight cross-compiled release binaries plus SHA256SUMS.txt.

ctxpack v0.1.10

Choose a tag to compare

@la2278647-arch la2278647-arch released this 26 Sep 12:15

v0.1.10

The release that fixes how the packer decides what a file is. packer.priority
scores every file before a budget is applied, and three of the fixes below are
matching defects in that one function: each one classified a file as something it
is not, so under a tight budget the wrong files survived. The other seven are
release-plumbing defects — the parts of the pipeline that turn a commit into a
downloadable binary — most of which had never been exercised on any machine other
than the one that wrote them.

Fixed

  • readme_helper.py was scored as a project document.
    The README check was strings.HasPrefix(base, "readme") — any basename
    beginning with readme. readme_helper.py and readmes.py therefore scored
    1000, the policy-document tier, instead of 200 (source), outranking config
    files, scripts and every test. The same function matched policyDocs by exact
    basename, where securityscanner.go correctly scored 200 against
    SECURITY.md at 1000, so the two halves of one rule disagreed: one exact, one
    greedy. isPolicyDoc now accepts only the basename readme or readme.<ext>,
    so README.md and docs/README.rst still score 1000 while readme_helper.py
    and readmes.py score 200 and docs/READMEING.md scores 300 — a markdown file
    that is not a README.

  • notmain.go was scored as an application entry point.
    Entry-point detection ran strings.HasSuffix on the full path, and
    HasSuffix("notmain.go", "main.go") is true — as are myindex.js against
    index.js, mymanage.py against manage.py and customserver.js against
    server.js. Four ordinary source files therefore scored 400, outranking the
    real source they sat among at 200, so a tight budget spent tokens on
    notmain.go before they reached anything the repository actually runs. Entry
    points are now an exact-basename set: main.go, mod.go, index.ts,
    index.js, index.jsx, index.tsx, server.js, manage.py.

  • React and TSX files scored 10, the lowest tier of all.
    The source list was .go .ts .js .py .rs .java .rb .cs and contained no
    .tsx or .jsx, so React and TypeScript-JSX components fell through to the
    default 10 — below config files (150), shell scripts (100) and even test files
    (50). Under a budget a component was dropped before a YAML file. Both
    extensions now score 200 as source, and index.jsx / index.tsx are
    registered as entry points at 400.

  • ctxpack models --sort vendor could sort wrong.
    The comparator compared vendor strings raw for equality but folded them to
    lowercase for ordering, so OpenAI and openai were treated as different
    vendors while ordering as equal. That is an inconsistent comparator, and
    sort.Slice has no defined result for one — the grouping came out wrong. The
    default (name) sort had the identical defect for case-variant names. Both now
    fold before comparing. Found by writing tests for the two tiebreak branches
    that had never been exercised; the real 31-entry table has distinct names, so
    neither branch had ever run.

  • Both installers could not verify any checksum file.
    install.sh and install.ps1 matched an asset with a two-space separator,
    which is what sha256sum -t emits in text mode. But GNU coreutils defaults to
    binary mode when given file arguments, which emits hash *name instead.
    sha256sum --help states it plainly: -b, --binary read in binary mode (default unless reading tty stdin). So the checksum file that make release
    produces on this project's own release host made both installers fail with
    ctxpack_0.1.10_windows_amd64.exe is not listed in SHA256SUMS.txt — the
    installers rejected every release, on every platform. Neither had ever been
    executed, so the defect shipped for four releases. Both parsers now accept
    either marker and compare the name after stripping it, and the Makefile pins
    -t so the published file is deterministic. The parsers are covered by 8
    offline cases each: binary and text mode, the asset not being first, and two
    prefix traps — ..._amd64.exe must not match ..._amd64.exe.debug, and
    ..._386.exe must not match ..._amd64.exe.

  • install.sh without a version produced a "version" made of release notes.
    The REST call was piped through grep -m1 '"tag_name"', which returns the
    whole matching line. When the API answers on a single line that line is the
    entire response including the release body, and the greedy sed then matched
    inside it, yielding a URL fragment before curl refused the malformed URL.
    grep -o extracts just the "tag_name": "v0.1.10" fragment, so the sed only
    ever sees that.

  • A transient GitHub connection reset aborted an install.
    Invoke-WebRequest has no retry of its own, and the script runs under
    $ErrorActionPreference = 'Stop', so one reset connection killed the install
    with no attempt to recover. install.ps1 now retries with backoff before
    giving up, and install.sh passes --retry 3 to curl. Under a live reset the
    retry path was observed printing retry 1/4 ... 3/4 and then rethrowing the
    real error, so a failure still reports clearly.

  • The CI release-binary job could not upload its artifacts.
    The workflow declares permissions: contents: read at the top level, and that
    applies to every job unless a job overrides it. actions/upload-artifact@v4
    requires actions: write, so the packages job would have failed at the very
    last step of a release build. The job now declares both permissions itself
    instead of widening the whole workflow. Found while validating the workflow
    structurally — every step, matrix and permission is checked by a script that
    parses the YAML, and all seven run: blocks pass bash -n.

  • CI release binaries were named differently from the real release assets.
    The workflow built ctxpack-0.1.10-linux-amd64 (hyphens) while make release,
    the published assets, and both installers all use
    ctxpack_0.1.10_linux_amd64 (underscores). A CI artifact therefore could not
    stand in for a release download, and a sha256sum -c against the published
    sums file would fail. The naming now matches.

  • A mistyped -ldflags -X path is now detected instead of silently ignored.
    Go accepts a wrong -X path with exit 0 and quietly leaves the source default
    in place: building with -X ...version.Vresion=9.9.9-typo (one letter wrong)
    and with -X ...internal/versionz.Version=... (wrong package) both succeed, and
    both binaries report the source default. That makes a typo in a version stamp
    invisible until a user inspects the output. The test job now builds with a
    sentinel version and fails if it does not appear in ctxpack version.

Added

  • Fourteen regression cases pin the priority ladder's matching rules.
    TestPriorityLadder now covers the two basename boundaries the defects above
    crossed — readme.md, readme.rst and docs/README.adoc at 1000 against
    readme_helper.py and readmes.py at 200 and docs/READMEING.md at 300 —
    every entry-point near miss (notmain.go, myindex.js, mymanage.py,
    customserver.js, all 200) against the real entry points at 400, and the new
    .tsx / .jsx tiers. Each case varies the extension and the basename
    independently, so the two matching rules cannot drift back into each other
    again. The self-packing snapshots in examples/ are regenerated in the same
    commit: they now cover 55 files instead of 54 and about 280922 tokens instead
    of 273107, because internal/cli/sortmodels_test.go is new since they were
    taken and enters the omitted list. The kept-file selection is unchanged, so
    they still demonstrate the same budget behaviour.

  • Twelve tests cover the sortModels contract, including the two branches
    that had never run.

    internal/cli/sortmodels_test.go pins the ordering for name, window, and
    vendor — the primary key, each tiebreak, case-folding, case-insensitive sort
    keys, the fallback for an unknown key, idempotence, and empty and
    single-element slices. Coverage of internal/cli rose from 99.4% to 99.6%;
    the one remaining uncovered statement is outputWriter's os.Create failure,
    which calls os.Exit(1) and so cannot be reached from a test.

  • The go install path is now verified end to end.
    It is the first install method the README and release notes show, and it had
    never been executed. From a clean GOPATH, go install github.com/la2278647-arch/ctxpack@v0.1.9 downloads, builds and installs
    ctxpack.exe, which reports ctxpack 0.1.9. @latest and @main resolve to
    the release, @v0.1.8 correctly resolves the older release, and @v9.9.9
    fails with a clear error. This also confirms the module path in go.mod
    matches the repository and that the root package is a main package, both of
    which go install silently requires.

Test coverage

package v0.1.9 v0.1.10
cli 99.4% 99.6%
counter 100% 100%
doctor 98.0% 98.0%
format 99.3% 99.3%
gitutil 100% 100%
ignore 98.0% 98.0%
mcp 97.3% 97.3%
packer 100% 100%
repomap 100% 100%
version 100% 100%
walker 94.4% 94.4%
total 98.5% 98.5%

425 test functions and 12 subtests, all passing. packer stays at 100%: the
three fixes above are covered by the new TestPriorityLadder rows, and the
function they changed already had no uncovered statement. Every remaining
uncovered branch in the suite is one that cannot be reached — a filepath.Abs
failure that needs the working directory deleted mid-call, a json.Marshal
failure over values that cannot fail to marshal, a regexp.Compile of a pattern
the translator always escapes, and outputWriter's os.Create failure, which
calls os.Exit(1). They are marked in comments ra...

Read more

ctxpack v0.1.9

Choose a tag to compare

@la2278647-arch la2278647-arch released this 26 Sep 05:23

v0.1.9

The release that closes the gap between what the tool advertises and what the
tool does. Six of the seven fixes below were not found by reading the code but by
pointing a test or a smoke assertion at the boundary between a documented
contract and the implementation behind it.

Fixed

  • pack_repo with format: "json" and a model returned unparseable JSON.
    The MCP tool prepended the HTML comment the text formats carry — <!-- fit: OVERFLOW model=gpt-4 used=267.6k/4.1k (6533%) OVERFLOW --> — in front of the
    JSON document, so any client that JSON.parses the tool result threw on every
    annotated call. The CLI sidesteps this by routing the note to stderr, but an
    MCP client only ever sees the envelope. The annotation now travels inside the
    envelope as a fit object using the same keys count_tokens --json already
    uses for its per-model entries (name, vendor, window, limit, used,
    pct_used, fits, reserve), so the information is still there and the
    document stays valid. diff_repo shares the path and gets the same treatment.
    Text formats keep the comment, and an unknown model yields
    fit: {"model": "...", "unknown": true} instead of destroying the envelope.
    fitNote now derives both renderings from one place, and the smoke suite
    asserts the fit key survives.

  • doctor -o FILE did not work.
    The help text advertises -o, --output FILE on all commands, but doctor only
    registered the long form. The shorthand failed with flag provided but not defined: -o and exited 2, so anyone scripting ctxpack doctor -o report.txt
    got a usage screen instead of a report. Both spellings now write to the file,
    matching pack, map, diff, tokens and models.

  • The help text described flags the commands do not take.
    printHelp called the walk flags "map / tokens only" when pack and diff
    accept them too, filed --depth under a three-command group while four commands
    take it, and told diff it "also accepts" only eight of the sixteen flags it
    registers, omitting --max-size, --depth, --no-gitignore, --hidden,
    --output, --dry-run and --list. There is now one WALK FLAGS group naming
    the four traversing commands plus a complete section per command, with no scope
    note the code contradicts.

  • The README's MCP tool table was missing doctor.
    doctor shipped in v0.1.8 but the table never gained its row, so a client
    reading the README concluded that a failing pack could not be diagnosed from
    inside the server — the exact case doctor exists for. The prose beside it
    called the analytic tools "three" when there are four. doctor is now listed
    with its format? / top? arguments, the list_models footnote moved out of
    the cell so the argument lists stay machine-readable, and the fit object is
    described where format: "json" and model meet. The README's install
    snippets also still pinned v0.1.7 and the Docker examples 0.1.4.

  • make smoke could destroy uncommitted README.md edits.
    The diff test dirties README.md to exercise diff, then restored it with
    git checkout -- README.md. That restores from the index, so anyone who ran
    the smoke suite with uncommitted README work lost it without warning. It now
    copies the file aside and copies it back, preserving the exact bytes that were
    there before the run. The finding was self-inflicted: the MCP table edit was
    applied, the suite was run, and the edits came back missing from the commit.

  • Twenty-three smoke assertions failed silently.
    scripts/smoke.sh ran under set -euo pipefail, but 23 assertions were bare
    grep calls: when one failed the script aborted with no message at all — a wall
    of passing sections followed by silence, with no way to tell which check broke.
    All of them now go through fail, which prints a specific reason. The bug had
    stayed hidden for a structural reason: fail was defined near the bottom of
    the script, after the assertions it was meant to serve, so those sections could
    not have used it. It now sits at the top. Wiring the doctor --output
    assertion up is what surfaced the -o bug above, which had been a silent
    no-op.

Added

  • Regression tests pin the documentation to the code.
    internal/cli/help_test.go walks the union of every flag against all six
    commands and asserts that each advertised flag parses (exit 0) and each
    non-advertised one is rejected by the parser (exit 2). Two further tests read
    the real printHelp output and check both directions: every documented flag
    must be registered, and no section may document a flag the command rejects.
    internal/mcp/readme_test.go parses the README's tool table and compares it
    both ways against the schemas tools() returns, so a tool added to or removed
    from the server fails it, as does a required/optional mismatch. Both are
    mutation-checked: deleting doctor's -o registration fails the help test
    with exactly cmd doctor: -o accept (exit 2, want 0), and deleting the
    doctor row from the table fails the README test with the table does not document doctor; the server advertises it.

  • The Run dispatcher and three CLI error branches now have tests.
    internal/cli/cli_gaps_test.go drives cli.Run — the function main.go
    actually calls — through its doctor case, which was the one command never
    dispatched by a test, so a typo in the case label would have shipped as
    "unknown command" for a command the help text advertises. The same file adds
    the near-miss check (Run(["docter"]) must hit the unknown-command branch),
    the tokens --model OVERFLOW verdict with the reverse case proving the mark is
    a property of the repository/model pair rather than of the fixture, and
    diff --dry-run's "omitted by the budget" line with the converse case proving
    it follows the cap rather than printing unconditionally.
    TestDoctorRejectsExtraArgs previously rejected only an unknown flag, which
    made its name overclaim — flag parsing and positional-argument rejection are
    two different branches with two different messages, and it now covers both and
    asserts both.

  • The fit-report selection and sorting contracts are pinned.
    Tests now fix the order --sort tokens / --sort bytes produce, which file
    wins a tie, and that --top truncates the text breakdown while the JSON
    payload stays complete.

Test coverage

package v0.1.8 v0.1.9
cli 97.6% 99.4%
counter 100% 100%
doctor 98.0% 98.0%
format 99.3% 99.3%
gitutil 100% 100%
ignore 98.0% 98.0%
mcp 97.1% 97.3%
packer 100% 100%
repomap 100% 100%
version 100% 100%
walker 94.4% 94.4%

423 tests, all passing, up from 389. Every remaining uncovered branch in the
suite is one that cannot be reached: a filepath.Abs failure that needs the
working directory deleted mid-call, a json.Marshal failure over values that
cannot fail to marshal, and outputWriter's os.Create failure, which calls
os.Exit(1). They are marked in comments rather than tested around. The suite
still asserts go.sum stays absent and go list -m all reports exactly one
module, so the binary remains dependency-free.

Installation

# Homebrew
brew tap la2278647-arch/tap https://github.com/la2278647-arch/homebrew-tap
brew install ctxpack

# Go
go install github.com/la2278647-arch/ctxpack@v0.1.9

# Windows PowerShell
irm https://raw.githubusercontent.com/la2278647-arch/ctxpack/main/install.ps1 | iex

# Linux/macOS
curl -fsSL https://raw.githubusercontent.com/la2278647-arch/ctxpack/main/install.sh | bash

# Direct download
# https://github.com/la2278647-arch/ctxpack/releases/tag/v0.1.9

What's next

  • GitHub Actions CI workflow (blocked on workflow scope token)
  • Docker daemon testing of the multi-stage Dockerfile
  • Model table expansion (blocked: context windows cannot be verified)
  • Promotion posts (drafts in docs/promote.md)

ctxpack v0.1.8

Choose a tag to compare

@la2278647-arch la2278647-arch released this 25 Sep 18:27

v0.1.8

The release that gives the MCP server a way to explain itself. A new doctor
tool answers the question an agent cannot otherwise ask, and the whole smoke
suite finally moved into one script that the CLI, the Makefile and CI all share.

Added

  • doctor is an MCP tool.
    An agent that got git error: exit status 128 from diff_repo had no way to
    tell whether git was missing, on the wrong version, or whether the ref was
    simply wrong — and the one diagnostic that answers that required a path,
    which is exactly what the agent may be unable to name. doctor takes no path
    at all: it reports the server's version, Go version, platform, git availability
    and version, and the model registry broken down by vendor. top truncates
    only the text breakdown; the N models, M vendors total and the
    format: "json" payload always stay complete, so a truncated answer cannot
    understate the registry. It accepts just text and json and refuses
    anything else — a client cannot request a format it would silently get back
    as text.

  • scripts/smoke.sh: the smoke suite as one script.
    It drives every command, all four output formats, the
    --sort/--top/--format/--dry-run/--list flags, diff with a
    --ref A..B range, a deletion across all four formats, and the MCP server over
    stdio — against the source tree itself. make smoke now delegates to it, so
    there is one copy instead of a Makefile recipe and a CI recipe that could drift
    apart. The script finds the repository root from its own path, so it runs from
    any working directory and accepts an explicit binary path as an optional first
    argument.

  • doctor, the file-selection flags, and all six MCP tools are in the smoke
    suite.

    doctor was documented and unit-tested but never exercised end to end. Nor
    were --include, --exclude, --max-size, --depth, --hidden,
    --no-gitignore, map --csv or models --vendor. The suite now asserts each
    one's contract with relative counts rather than pinned numbers, so it keeps
    passing as the repository grows: --depth must shrink the file set,
    --max-size must leave the count alone while collapsing the token total,
    --include and --exclude must each shrink it, --hidden must add files,
    and --no-gitignore can only keep or add. On the MCP side the suite asserts
    that tools/list advertises all six tools, that each is callable, and that
    five failure modes are reported correctly.

Changed

  • doctor moved into a shared package.
    The CLI's doctor command and the MCP doctor tool now both call
    internal/doctor instead of each implementing the checks. That is the same
    "frontends share an engine" rule the packer and repomap packages already follow,
    and it removes about a hundred lines of duplicated git probing and vendor
    sorting from internal/cli. The JSON keys the CLI has always emitted are
    unchanged, so a script that parses ctxpack doctor --json keeps working.

  • --dry-run writes its report to stderr, and the smoke suite asserts it.
    The suite used to discard dry-run output with > /dev/null, which silently
    failed to silence it — this codebase sends artifacts to stdout and status to
    stderr, and a dry run produces status, not an artifact, so the redirect
    captured nothing at all. The assertions now capture stderr and require the
    report to be present, so the stream convention is pinned instead of tolerated.

  • The CI smoke test calls scripts/smoke.sh instead of inlining its steps.
    The inlined copy had two bugs the script run surfaced: it grepped for "tree"
    in MCP output, where the tool result arrives escaped as \"tree\" inside the
    JSON-RPC envelope string, and it used > /dev/null to silence dry-run output
    that travels on stderr.

  • The README MCP table was corrected.
    It omitted pack_repo's max_depth, and the introductory sentence implied
    only repo_map, count_tokens and list_models take a format when all six
    tools do. The smoke suite now exercises max_depth through the MCP interface
    so this cannot quietly regress.

Test coverage

package v0.1.7 v0.1.8
cli 96.6% 97.6%
counter 100% 100%
doctor — 98.0%
format 99.3% 99.3%
gitutil 100% 100%
ignore 98.0% 98.0%
mcp 97.4% 97.1%
packer 100% 100%
repomap 100% 100%
version 100% 100%
walker 94.4% 94.4%

389 tests, all passing. The suite still asserts go.sum stays absent and
go list -m all reports exactly one module, so the binary remains dependency-free.

Installation

# Homebrew
brew tap la2278647-arch/tap https://github.com/la2278647-arch/homebrew-tap
brew install ctxpack

# Go
go install github.com/la2278647-arch/ctxpack@v0.1.8

# Windows PowerShell
irm https://raw.githubusercontent.com/la2278647-arch/ctxpack/main/install.ps1 | iex

# Linux/macOS
curl -fsSL https://raw.githubusercontent.com/la2278647-arch/ctxpack/main/install.sh | bash

# Direct download
# https://github.com/la2278647-arch/ctxpack/releases/tag/v0.1.8

What's next

  • GitHub Actions CI workflow (blocked on workflow scope token)
  • Docker daemon testing of the multi-stage Dockerfile
  • Model table expansion (blocked: context windows cannot be verified)
  • Promotion posts (drafts in docs/promote.md)

ctxpack v0.1.7

Choose a tag to compare

@la2278647-arch la2278647-arch released this 25 Sep 16:24

v0.1.7

The release that teaches diff about history. diff now understands git
ranges and reports files that were deleted, and pack stops printing your
machine's absolute path into the bundle.

Added

  • diff ranges (--ref A..B).
    ctxpack diff --ref HEAD~5..HEAD compares two revisions as history. A range
    never includes the working tree's untracked files, because those belong to
    neither side of the range. A plain ref (--ref main) still diffs against the
    working tree, so uncommitted changes remain included. The MCP diff_repo
    tool accepts the same range syntax for its ref argument.

  • diff reports deleted files.
    A deletion has no content to pack, so before this release the bundle simply
    never mentioned it — a removed file looked like it had never existed. diff
    now lists removed paths in a Deleted section: XML adds a <deleted>
    element, Markdown a ## Deleted heading, text a ==== deleted ==== block,
    and JSON a deleted array. --dry-run prints the count and each path. The
    MCP diff_repo tool reports them the same way. Paths are reported by name
    only, never content.

  • examples/diff-demo: a reproducible diff snapshot.
    A generated ctxpack diff output over a two-commit range containing a
    modification, an addition and a deletion — the smallest example that shows
    range syntax and the new Deleted section together. make.sh builds the
    scratch repository in a temp directory and deletes it on exit, so the
    committed diff.xml is byte-identical on any machine.

Changed

  • Bundles name the directory, not the machine.
    pack and diff now label the bundle with the walked directory's base name
    (<root>ctxpack</root>) instead of its absolute path
    (<root>D:\Users\alice\ctxpack</root>). The machine the bundle was built on
    is not information a model needs, and an absolute path leaks the username of
    whoever packed the repository. This matches what map already did for its
    root node; pack and diff had diverged from it. The JSON root field
    carries the same shortened value.

    If you parsed the JSON root field and expected an absolute path, read it
    from the file system instead — the bundle now names the directory.

  • gitutil.DiffFiles splits deletions from changes.
    ChangedFiles keeps its signature and behaviour, now returning only the
    packable set; callers that need to report removals use the new DiffFiles,
    which returns both lists.

Test coverage

package v0.1.6 v0.1.7
cli 96.6% 96.6%
counter 100% 100%
format 99.1% 99.3%
gitutil 100% 100%
ignore 98.0% 98.0%
mcp 97.4% 97.4%
packer 100% 100%
repomap 100% 100%
version 100% 100%
walker 94.4% 94.4%

369 tests, all passing.

Installation

# Homebrew
brew tap la2278647-arch/tap https://github.com/la2278647-arch/homebrew-tap
brew install ctxpack

# Go
go install github.com/la2278647-arch/ctxpack@v0.1.7

# Windows PowerShell
irm https://raw.githubusercontent.com/la2278647-arch/ctxpack/main/install.ps1 | iex

# Linux/macOS
curl -fsSL https://raw.githubusercontent.com/la2278647-arch/ctxpack/main/install.sh | bash

# Direct download
# https://github.com/la2278647-arch/ctxpack/releases/tag/v0.1.7

What's next

  • GitHub Actions CI workflow (blocked on workflow scope token)
  • Docker daemon testing of the multi-stage Dockerfile
  • Model table expansion (blocked: context windows cannot be verified)
  • Promotion posts (drafts in docs/promote.md)