Releases: ahundt/ai-session-search
Release list
v1.0.0rc1
ai_session_tools v0.3.1
ai_session_tools v0.3.1 (2026-03-18)
Patch release: Edit tool tracking in file recovery, new --include-result flag, and bug fixes.
Install / Upgrade
Already installed?
uv tool upgrade ai_session_toolsNew install:
uv tool install git+https://github.com/ahundt/ai_session_toolsWhat's New
Edit tool tracking in files search/history/extract
aise files history now shows Edit tool calls as separate versions alongside Write calls.
Previously only Write calls appeared. Each Edit becomes a numbered version with a diff
summary (+lines/-lines), timestamp, and session ID.
aise files search shows per-tool counts: how many Write, Edit, and NotebookEdit calls
touched each file across sessions.
--include-result flag
aise messages get --include-result and aise messages search --include-result include
tool result content alongside tool use messages. Previously tool results were filtered out.
tool_use_only filter
aise messages get --tool-use-only shows only tool call messages (Write, Edit, Bash, etc.),
filtering out conversational messages.
Bug Fixes
aise messages search "a|b"with regex pipe returned zero results; regex was compiled
with the raw pipe as a literal character instead of alternation. Fixed regex parsing
in cli.py.aise messages search "multi word query"returned zero results when query contained
spaces; query was split on whitespace before matching. Fixed to pass full query string.aise files searchandaise messages correctionscrashed with Rich MarkupError on
content containing bracket-like text (e.g.[tag]). Fixed by escaping Rich markup
in output formatting.aise listandaise files searchdefaulted to table format even when stdout was
piped (non-TTY). Fixed to default to plain format when not a TTY.engine.py: Fixed F821 ruff lint error (missingCallableimport from typing).
Internal
- Config resolution for org_dir, claude_dir, gemini_dir moved from scattered inline
logic toconfig.pyfunctions. No behavior change. - Demo recording infrastructure: added Post B (file recovery) and Post D (compaction)
demo modes, improved version ordering in fixtures, reduced banner hold time.
ai_session_tools v0.3.0
ai_session_tools v0.3.0 (2026-03-08)
Key changes in v0.3.0 that affect daily use:
- Date filtering on every command:
--since,--until,--whenscope results without grep, and skip files older than the cutoff. On large session directories this cuts search time by roughly 50x. - Unified search across Claude Code, AI Studio, and Gemini CLI: auto-discovered on first run, searched together by default.
AISessionlibrary entry point: zero-config Python API; all methods return typed dataclasses.
Install / Upgrade
uv tool install git+https://github.com/ahundt/ai_session_toolsAlready installed?
uv tool upgrade ai_session_toolsPython 3.12+ required (raised from 3.8 in v0.2.0). orjson is now a required dependency (was optional [fast]); it installs automatically with the package.
Breaking Changes
Python minimum raised from 3.8 to 3.12. Required by orjson, which is now a mandatory dependency (was optional [fast]).
Renamed classes and entry point
| v0.2.0 | v0.3.0 |
|---|---|
SessionBackend |
AISession |
RecoveredFile |
SessionFile |
RecoveryStatistics |
SessionStatistics |
Renamed methods (on AISession)
| v0.2.0 | v0.3.0 |
|---|---|
analyze_session() |
get_session_analysis() |
timeline_session() |
get_session_timeline() |
analyze_planning_usage() |
get_planning_usage() |
cross_reference_session() |
get_file_edits() |
export_session_markdown() |
get_session_markdown() |
search() |
search_files() |
search_messages_with_context() |
search_messages(context=N) |
search_messages(query, context=0) now uses keyword-only arguments after query.
get_statistics() return type
Returns a SessionStatistics dataclass instead of a plain dict:
# v0.2.0
stats = engine.get_statistics()
n = stats["total_sessions"]
# v0.3.0
stats = engine.get_statistics()
n = stats.total_sessionsFilterSpec renames
| v0.2.0 | v0.3.0 |
|---|---|
FilterSpec(after=...) |
FilterSpec(since=...) |
FilterSpec(before=...) |
FilterSpec(until=...) |
.with_session() |
.with_sessions() |
.with_edit_range(min, max) |
.with_edit_range(min_edits=N, max_edits=N) |
FilterSpec is now callable directly. The intermediate SearchFilter class is gone:
# v0.2.0
matching = SearchFilter(spec)(files)
# v0.3.0
matching = spec(files)Removed classes
| v0.2.0 | v0.3.0 |
|---|---|
LocationMatcher |
SearchFilter.by_location_pattern(include=[], exclude=[]) |
ChainedFilter(f1, f2) |
f1 & f2 operator |
CLI flag renames
--sourcerenamed to--provider--afterand--beforestill accepted but hidden; use--sinceand--untilSummarydisplay mode renamed toCompact
What's New
Date filtering
Every command accepts --since, --until, and --when:
aise messages search "auth" --since 14d # messages from the last two weeks
aise messages corrections --since 30d # corrections you gave Claude, by type
aise files history engine.py # version history of a file across sessions
aise stats --since 2026-01 # session stats since January
aise list --since 7d # last 7 days
aise files search "*.py" --when 202X # entire 2020s decade
aise stats --since 2026-02-01 --until 2026-03-01You can write dates in whatever form is natural: exact ISO dates, partial dates like
2026-01, duration shorthands like 7d or 2w, NLP phrases like "yesterday" or
"2 weeks ago", EDTF wildcards like 202X for an entire decade, and EDTF intervals
like 2026-01/2026-03. Run aise dates for the full format reference and spec link.
When --since is set, aise checks each session file's mtime before opening it.
Sessions older than the cutoff are skipped. On directories with hundreds of sessions,
this cuts search time by roughly 50x.
Unified search across Claude Code, AI Studio, and Gemini CLI
All three session sources are auto-discovered on first run and searched together:
aise messages search "authentication" # all sources
aise messages search "authentication" --provider claude # Claude only
aise list --provider aistudio # AI Studio sessions only
aise stats --provider geminiSources are cached for 24 hours and managed with:
aise source list
aise source scan --force # re-discover everything
aise source add name /path # register a custom directory
aise source remove nameAuto-discovery covers macOS CloudStorage, Linux drive mounts, and Windows Google
Drive paths.
AISession: zero-config library entry point
Auto-detects all sources; no paths required:
import ai_session_tools as aise
with aise.AISession() as session:
sessions = session.get_sessions(since="7d")
messages = session.search_messages("authentication")
files = session.search_files("*.py")All methods return typed dataclasses (SessionInfo, SessionMessage, SessionFile,
SessionStatistics).
New CLI commands
aise --version/-Vaise history: session history with--format/--provideraise commands list|context: slash command discovery across sessions; shows working directory and git branch per commandaise messages inspect: single-session message analysis (renamed frommessages analyzeto avoid collision withaise analyze)aise instruction-history: extract system prompt / instruction injection historyaise dates: date format referenceaise config show|init: show or create config file
New CLI flags
--full-uuid: show full 36-char session IDs instead of 8-char prefix--type user|assistant|slash|compactiononmessages searchandmessages timeline--context Nonmessages search: show N surrounding messages per match--context-before/--context-after: asymmetric context windows--fixed-strings/-F: literal string matching instead of regex--skip-injection: filter out SKILL.md/CLAUDE.md injection content--ids-only: output session IDs only (onlist,corrections,planning,commands)--no-compaction: exclude compaction summaries from search results--greponmessages timeline: git-log-style regex filtering--detailonplanningandcommands: show arguments and session IDs--sessiononcorrections: scope to a single session--after-index/--after-timestamp: resume search from a position--format json --output <file>routing on all commands--limit 0means unlimited (previously returned zero results)- Config defaults: set
format,max_chars,providerinconfig.json["defaults"]
Analysis pipeline
aise analyze classifies your sessions by technique, vocabulary, and era, and groups
them by working directory. If you work across multiple projects and want to understand
how your AI usage patterns have changed over time, or which projects saw the most
activity, this is the command. Unchanged sessions are skipped on re-runs:
aise analyze # run full pipeline, skip unchanged sessions
aise analyze --force # re-run all stages
aise analyze --status # dry-run: show what would run
aise analyze --step codebook # run one stage onlyThe pipeline stages: codebook-based technique classification (with word-boundary
markers to avoid partial-word false positives), prose/code splitting for vocabulary
analysis (strips code tokens from n-grams before counting), and era detection from
filename date prefixes, ISO dates in content, and Gemini startTime fields. Output
formats are symlinks (default), JSON, and Markdown. A provenance graph
(SESSION_GRAPH.json) records which sessions belong to which working directories.
Unified config
Config lives at the OS-appropriate path and is auto-created on first use:
| OS | Path |
|---|---|
| macOS | ~/Library/Application Support/ai_session_tools/config.json |
| Linux | ~/.config/ai_session_tools/config.json |
| Windows | %APPDATA%\ai_session_tools\config.json |
The defaults section sets per-user defaults for format, max_chars, provider,
and correction patterns. Override for a single run with AI_SESSION_TOOLS_CONFIG=/path.
Windows support
aise now runs on macOS, Linux, and Windows:
- Rich Console uses ASCII fallback for box-drawing characters on Windows cp1252 consoles
(previously crashed withUnicodeEncodeError) - All docstrings use only cp1252-safe characters
- pathlib-based path handling throughout
Bug Fixes
Data correctness
get_versions("data[0].py")returned zero results; glob metacharacters in filenames were not escaped. Now usesglob.escape().- Sessions with no JSONL timestamp incorrectly passed date filters; falsy
ts_firstbypassed comparison. Now excluded when a date filter is active. cross_reference_session("cli.py")matchedold-cli.py;endswith()was too broad. Changed to exactPath(fp).namematch.search_messages_with_context(message_type="user")dropped adjacent assistant messages from context windows; filter moved from buffer loop to match loop.source="all"silently excluded Claude sessions; missingClaudeSourceadapter added.aise stats --provider claudereported 0 sessions; was counting from emptyrecovery_dirinstead of_iter_all_jsonl().- Multi-source
list_sessions()returned AI Studio sessions first instead of newest-first; cross-source timestamp sort added. - AI Studio
message_countalw...

