Skip to content

ai_session_tools v0.3.0

Choose a tag to compare

@ahundt ahundt released this 09 Mar 23:01
· 31 commits to main since this release

ai_session_tools v0.3.0 (2026-03-08)

Key changes in v0.3.0 that affect daily use:

  1. Date filtering on every command: --since, --until, --when scope results without grep, and skip files older than the cutoff. On large session directories this cuts search time by roughly 50x.
  2. Unified search across Claude Code, AI Studio, and Gemini CLI: auto-discovered on first run, searched together by default.
  3. AISession library entry point: zero-config Python API; all methods return typed dataclasses.

demo


Install / Upgrade

uv tool install git+https://github.com/ahundt/ai_session_tools

Already installed?

uv tool upgrade ai_session_tools

Python 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_sessions

FilterSpec 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

  • --source renamed to --provider
  • --after and --before still accepted but hidden; use --since and --until
  • Summary display mode renamed to Compact

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-01

You 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 gemini

Sources 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 name

Auto-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 / -V
  • aise history: session history with --format/--provider
  • aise commands list|context: slash command discovery across sessions; shows working directory and git branch per command
  • aise messages inspect: single-session message analysis (renamed from messages analyze to avoid collision with aise analyze)
  • aise instruction-history: extract system prompt / instruction injection history
  • aise dates: date format reference
  • aise 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|compaction on messages search and messages timeline
  • --context N on messages 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 (on list, corrections, planning, commands)
  • --no-compaction: exclude compaction summaries from search results
  • --grep on messages timeline: git-log-style regex filtering
  • --detail on planning and commands: show arguments and session IDs
  • --session on corrections: scope to a single session
  • --after-index / --after-timestamp: resume search from a position
  • --format json --output <file> routing on all commands
  • --limit 0 means unlimited (previously returned zero results)
  • Config defaults: set format, max_chars, provider in config.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 only

The 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 with UnicodeEncodeError)
  • 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 uses glob.escape().
  • Sessions with no JSONL timestamp incorrectly passed date filters; falsy ts_first bypassed comparison. Now excluded when a date filter is active.
  • cross_reference_session("cli.py") matched old-cli.py; endswith() was too broad. Changed to exact Path(fp).name match.
  • 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; missing ClaudeSource adapter added.
  • aise stats --provider claude reported 0 sessions; was counting from empty recovery_dir instead 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_count always 0; now parses JSON chunk count.
  • AI Studio timestamp_first always empty; now populated from file mtime.

Display and formatting

  • aise files search showed raw ANSI escape codes instead of a rendered table.
  • aise list column widths collapsed when sessions had missing dates.
  • Terminal width defaulted to 80 when stdout was piped; now reads from stderr fd.
  • Session ID truncation was inconsistent (16 chars vs 8 chars); standardized to 8-char prefix.
  • Rich MarkupError on special characters in user content; now escaped.
  • Windows cp1252 console crash on Unicode box-drawing chars; Console factory with safe_box detection added.

Filters and dates

  • FilterSpec(since="7d") stored the raw string instead of resolving it.
  • Filter.__or__ matched everything when one side was an empty filter.
  • --limit 0 returned zero results; now means unlimited.
  • parse_date_input(None) crashed; now returns None.
  • FilterSpec.matches_datetime() gave wrong results across sources due to timezone designators and sub-second precision.

Security and PII

  • session_db.json stored absolute home directory paths; changed to ~/ paths.
  • Five analysis modules fell back to hardcoded paths; removed. Requires explicit org_dir in config.
  • ReDoS protection added to regex entry points; _check_redos_safe() detects nested quantifiers before re.compile() and falls back to literal substring matching.

Corrections accuracy

  • Skill injection false positives: SKILL.md/CLAUDE.md bodies triggered correction patterns; now detected and excluded via _is_skill_injection() heuristic.
  • UUID-era name-based detection skipped; was producing false era labels from UUID-style session names.

Config

  • Config files using old after/before keys are auto-migrated to since/until.
  • Config cache was wiped on OSError during write; in-process cache now preserved.
  • AI_SESSION_TOOLS_CONFIG env var change did not invalidate config cache.
  • Analysis pipeline ignored --config CLI flag; unified to config.py.
  • aise config and aise source with no subcommand errored; added invoke_without_command=True.
  • --format json --output routing was broken on commands list and commands context.

Claude Code Integration

After installing autorun, use
/ar:ai-session-tools (or /ar:claude-session-tools) inside Claude Code to search
and recover session history without leaving the editor. Especially useful right after
context compaction to restore previous context inline.


Full changelog |
GitHub |
Issues |
autorun plugin