git log
built-in 0.0% Savings
0 Commands
0 Tokens saved
4 Tests
Install
Safety checks passed
Filter definition
# git-log.toml — reduce full `git log` to one line per commit
#
# Raw: multi-line commit entries with full metadata and message bodies
# Filtered: `<short-sha> <subject>`, capped at 20 commits
#
# This filter used to `run = "git log --oneline --no-decorate -n 20 {args}"`.
# That destroyed the history before tokf ever saw it: `tokf raw <id>` returned
# 20 one-line summaries and there was no way to recover the rest (issue #430).
# The reduction now happens here, over the real `git log` output, so the full
# history is captured and recoverable.
#
# Empty-output handling: when git log returns no commits (e.g. for an
# untracked pathspec, an empty branch range, or a search that matched
# nothing), the model previously got back nothing — indistinguishable
# from "tokf filtered everything out". Observed retry pattern: agents
# would burn 10–40 calls cycling through flag variations
# (`--all`, `--diff-filter=A`, `--grep=…`, `--source`, `--follow`,
# `-- 'path'`) before realising the answer was "the file is untracked".
# `on_empty` makes the empty-result case unambiguous and actionable.
command = "git log"
description = "Show one-line-per-commit format, last 20 entries"
# Skip the filter when the user asks for an output shape this reduction would
# misrepresent. These flags change the structure of the output, so the chunk
# splitter below either can't parse it (`--oneline`, `--format`, `--graph`) or
# would silently discard the extra content the user explicitly asked for
# (`-p`, `--stat`).
passthrough_args = [
"-p", # patch (full diff content per commit)
"--patch",
"--oneline", # already one line per commit — nothing to reduce
"--format", # custom output format
"--pretty",
"--graph", # ASCII graph
"--stat", # diffstat per commit
"--shortstat", # one-line diffstat per commit
"--dirstat", # per-directory change stats
"-L", # line-history (-L 1,10:file or -L:funcName:file) — patch output
]
# When git returns no commits, give the model a one-line hint about the
# most likely causes instead of empty output.
on_empty = "(no matching commits — if querying a path, verify it's tracked: `git ls-files -- <path>`; for cross-branch history, add `--all`; for renamed-file history, add `--follow`)"
# Cap at 20 commits. Applied after rendering, so the full log is still
# captured in history and recoverable via `tokf raw`.
#
# Must stay above the [[chunk]] tables below: TOML array-of-tables sections
# capture every subsequent key, so a top-level field written after them is
# silently absorbed into the table instead.
max_lines = 20
# Guard: only render the reduction when the output actually looks like the
# default `git log` format.
#
# `on_empty` fires whenever the rendered output is empty, and the chunk
# splitter renders nothing for output it can't parse. Without this section, a
# user with `format.pretty = oneline` in their gitconfig — which is invisible
# to `passthrough_args`, since it isn't a CLI flag — would be told "no matching
# commits" about a log full of commits.
#
# When no section collects, the branch falls back to the raw output, so
# unparseable-but-real output is passed through and `on_empty` is left to mean
# what it says.
[[section]]
name = "commit-headers"
match = '^commit [0-9a-f]{7,}'
collect_as = "commit_header_lines"
# One chunk per commit. `Merge:`, `Author:` and `Date:` lines are dropped by
# not being extracted; the message body is dropped by taking only the first
# indented line (the subject).
[[chunk]]
split_on = '^commit [0-9a-f]{7,}'
collect_as = "commits"
[chunk.extract]
pattern = '^commit ([0-9a-f]{7})'
as = "sha"
# First indented non-blank line of the message is the subject; later body
# lines match too, but body_extract keeps the first match only.
[[chunk.body_extract]]
pattern = '^ (\S.*)$'
as = "subject"
[on_success]
output = """{commits | each: "{sha} {subject}" | join: "\n"}"""
# Route --name-only / --name-status to a tree-structured child filter
# instead of passing through unfiltered.
[[variant]]
name = "name-list"
detect.args_pattern = '--(name-only|name-status)'
filter = "git/log-name-list"
Examples
output is capped at 20 commits
~1123 tokens → ~263 tokens
(77% saved)
Raw output
commit 4c2887241fcf61116ee1e1a965838e2d9b1214d4
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 20 10:10:00 2026 +0200
feat(filter): add chunk-based git log reduction
A longer explanation of the change spanning
several lines of body text.
Refs #430
commit 04dd4b1f7b9653ccc8d6743155607fed7cb2544d
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 19 10:11:00 2026 +0200
fix(config): handle missing optional fields
Co-Authored-By: Grace Hopper <grace@example.com>
commit fa26181ec60eb2ae8b41c45748514afbd4d67045
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 18 10:12:00 2026 +0200
test(filter): add fixtures for cargo-test failure case
commit c538c297ccf1fd1db448e73334ae3fc29f5f076a
Merge: 1a2b3c4 5d6e7f8
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 17 10:13:00 2026 +0200
docs: document the run override rule
commit c4a3b8e248580111a7c2c2a97201b301be4b60cb
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 16 10:14:00 2026 +0200
refactor(runner): extract expand_run_command
commit ae283850259575235f0a5a30bedbb1066be8445a
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 15 10:15:00 2026 +0200
chore(deps): bump serde to 1.0.219
commit 147d207fb81ab920f0d092c3dd503e7daa989a6d
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 14 10:16:00 2026 +0200
ci: add clippy to the workflow
commit d8ecacc50b189c8b5a01349d85678638fbf5c750
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 13 10:17:00 2026 +0200
perf(filter): avoid cloning chunk items
commit 19a0bf77bc93890771088801d56c94ed814d6aa0
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 12 10:18:00 2026 +0200
fix(history): record executed command
commit 8b22a8fd6f319c50b419a3cf519b4fc445d984ad
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 11 10:19:00 2026 +0200
feat(cli): add tokf raw subcommand
commit cbb1ab571e114f24abe381ac6e51c01fac522ce1
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 10 10:10:00 2026 +0200
test(history): cover schema migration
commit f1741767ece4681587b6c012ca1133266c4982fb
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 09 10:11:00 2026 +0200
docs(readme): regenerate from docs/
commit 68a97b570f38e67a7f1a14a4917ccf419a9795a0
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 08 10:12:00 2026 +0200
fix(hook): stop swallowing stderr
commit 8449705ed01476411190f9c29d4a5a88c0cb3efa
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 07 10:13:00 2026 +0200
refactor(config): split types module
commit d8a09c97cba3eda464519408b0ff8f46b6a08124
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 06 10:14:00 2026 +0200
feat(output): annotate with history id
commit aef47ff065244575998aeb59faaa95c3c7c233ca
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 05 10:15:00 2026 +0200
chore: release main
commit a621bb4a6a353950da76cd0a1670c466d5fffc20
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 04 10:16:00 2026 +0200
fix(tracking): guard against zero retention
commit 2419eac713021ba0831eae3bab01f8dd5e3e0c1e
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 03 10:17:00 2026 +0200
test(cli): end-to-end passthrough case
commit ad387a02c3d507e61973885766ba18faacb59347
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 02 10:18:00 2026 +0200
feat(gh): add pr checks filter
commit 850951619c7aec7a85ee6dd5255a26ed07a49692
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 20 10:19:00 2026 +0200
fix(docker): correct ps format string
commit df5c8089aebee76c5a34e551fc467ed17a1105ba
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 19 10:10:00 2026 +0200
docs(filters): explain passthrough semantics
commit 9f89b43d64cbc659c11c1d52d6cdb640b41cec07
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 18 10:11:00 2026 +0200
chore(deps): update rust to 1.96.1 Filtered output
4c28872 feat(filter): add chunk-based git log reduction 04dd4b1 fix(config): handle missing optional fields fa26181 test(filter): add fixtures for cargo-test failure case c538c29 docs: document the run override rule c4a3b8e refactor(runner): extract expand_run_command ae28385 chore(deps): bump serde to 1.0.219 147d207 ci: add clippy to the workflow d8ecacc perf(filter): avoid cloning chunk items 19a0bf7 fix(history): record executed command 8b22a8f feat(cli): add tokf raw subcommand cbb1ab5 test(history): cover schema migration f174176 docs(readme): regenerate from docs/ 68a97b5 fix(hook): stop swallowing stderr 8449705 refactor(config): split types module d8a09c9 feat(output): annotate with history id aef47ff chore: release main a621bb4 fix(tracking): guard against zero retention 2419eac test(cli): end-to-end passthrough case ad387a0 feat(gh): add pr checks filter 8509516 fix(docker): correct ps format string
empty git log emits actionable hint instead of nothing
~0 tokens → ~49 tokens
Raw output
Filtered output
(no matching commits — if querying a path, verify it's tracked: `git ls-files -- <path>`; for cross-branch history, add `--all`; for renamed-file history, add `--follow`)
full git log reduces to one line per commit
~1123 tokens → ~263 tokens
(77% saved)
Raw output
commit 4c2887241fcf61116ee1e1a965838e2d9b1214d4
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 20 10:10:00 2026 +0200
feat(filter): add chunk-based git log reduction
A longer explanation of the change spanning
several lines of body text.
Refs #430
commit 04dd4b1f7b9653ccc8d6743155607fed7cb2544d
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 19 10:11:00 2026 +0200
fix(config): handle missing optional fields
Co-Authored-By: Grace Hopper <grace@example.com>
commit fa26181ec60eb2ae8b41c45748514afbd4d67045
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 18 10:12:00 2026 +0200
test(filter): add fixtures for cargo-test failure case
commit c538c297ccf1fd1db448e73334ae3fc29f5f076a
Merge: 1a2b3c4 5d6e7f8
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 17 10:13:00 2026 +0200
docs: document the run override rule
commit c4a3b8e248580111a7c2c2a97201b301be4b60cb
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 16 10:14:00 2026 +0200
refactor(runner): extract expand_run_command
commit ae283850259575235f0a5a30bedbb1066be8445a
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 15 10:15:00 2026 +0200
chore(deps): bump serde to 1.0.219
commit 147d207fb81ab920f0d092c3dd503e7daa989a6d
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 14 10:16:00 2026 +0200
ci: add clippy to the workflow
commit d8ecacc50b189c8b5a01349d85678638fbf5c750
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 13 10:17:00 2026 +0200
perf(filter): avoid cloning chunk items
commit 19a0bf77bc93890771088801d56c94ed814d6aa0
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 12 10:18:00 2026 +0200
fix(history): record executed command
commit 8b22a8fd6f319c50b419a3cf519b4fc445d984ad
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 11 10:19:00 2026 +0200
feat(cli): add tokf raw subcommand
commit cbb1ab571e114f24abe381ac6e51c01fac522ce1
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 10 10:10:00 2026 +0200
test(history): cover schema migration
commit f1741767ece4681587b6c012ca1133266c4982fb
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 09 10:11:00 2026 +0200
docs(readme): regenerate from docs/
commit 68a97b570f38e67a7f1a14a4917ccf419a9795a0
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 08 10:12:00 2026 +0200
fix(hook): stop swallowing stderr
commit 8449705ed01476411190f9c29d4a5a88c0cb3efa
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 07 10:13:00 2026 +0200
refactor(config): split types module
commit d8a09c97cba3eda464519408b0ff8f46b6a08124
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 06 10:14:00 2026 +0200
feat(output): annotate with history id
commit aef47ff065244575998aeb59faaa95c3c7c233ca
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 05 10:15:00 2026 +0200
chore: release main
commit a621bb4a6a353950da76cd0a1670c466d5fffc20
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 04 10:16:00 2026 +0200
fix(tracking): guard against zero retention
commit 2419eac713021ba0831eae3bab01f8dd5e3e0c1e
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 03 10:17:00 2026 +0200
test(cli): end-to-end passthrough case
commit ad387a02c3d507e61973885766ba18faacb59347
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 02 10:18:00 2026 +0200
feat(gh): add pr checks filter
commit 850951619c7aec7a85ee6dd5255a26ed07a49692
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 20 10:19:00 2026 +0200
fix(docker): correct ps format string
commit df5c8089aebee76c5a34e551fc467ed17a1105ba
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 19 10:10:00 2026 +0200
docs(filters): explain passthrough semantics
commit 9f89b43d64cbc659c11c1d52d6cdb640b41cec07
Author: Ada Lovelace <ada@example.com>
Date: Mon Jul 18 10:11:00 2026 +0200
chore(deps): update rust to 1.96.1 Filtered output
4c28872 feat(filter): add chunk-based git log reduction 04dd4b1 fix(config): handle missing optional fields fa26181 test(filter): add fixtures for cargo-test failure case c538c29 docs: document the run override rule c4a3b8e refactor(runner): extract expand_run_command ae28385 chore(deps): bump serde to 1.0.219 147d207 ci: add clippy to the workflow d8ecacc perf(filter): avoid cloning chunk items 19a0bf7 fix(history): record executed command 8b22a8f feat(cli): add tokf raw subcommand cbb1ab5 test(history): cover schema migration f174176 docs(readme): regenerate from docs/ 68a97b5 fix(hook): stop swallowing stderr 8449705 refactor(config): split types module d8a09c9 feat(output): annotate with history id aef47ff chore: release main a621bb4 fix(tracking): guard against zero retention 2419eac test(cli): end-to-end passthrough case ad387a0 feat(gh): add pr checks filter 8509516 fix(docker): correct ps format string
output the splitter can't parse is passed through, not called empty
~12 tokens → ~12 tokens
Raw output
abc1234 some subject def5678 another subject
Filtered output
abc1234 some subject def5678 another subject
Warning: Community filters are third-party code. Review the filter definition above before installing it in production environments.Browse all filters