From 0233e655c1cd5358b38ba5e03ee681a4a1ef22da Mon Sep 17 00:00:00 2001 From: Evan Senter Date: Sun, 11 Jan 2026 23:37:25 +0000 Subject: [PATCH 1/2] feat: Standardize MCP tool default parameters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add limit param to list_sessions and classify_sessions (default: 20) - Reduce get_session_events and get_session_messages limit: 100 → 50 - Update get_session_efficiency limit: 50 → 20 - Update find_related_sessions limit: 10 → 20 - Update guide.md documentation with new signatures Provides more consistent defaults across session-related endpoints. Co-Authored-By: Claude Opus 4.5 --- src/session_analytics/guide.md | 10 +++++----- src/session_analytics/queries.py | 15 +++++++++++---- src/session_analytics/server.py | 26 ++++++++++++++------------ 3 files changed, 30 insertions(+), 21 deletions(-) diff --git a/src/session_analytics/guide.md b/src/session_analytics/guide.md index a1492ae..833a3a5 100644 --- a/src/session_analytics/guide.md +++ b/src/session_analytics/guide.md @@ -23,9 +23,9 @@ identify permission gaps. | Tool | Purpose | |------|---------| | `get_tool_frequency(days?, project?, expand?)` | Tool usage counts with Bash/Skill/Task breakdown | -| `list_sessions(days?, project?)` | Session metadata and token totals | +| `list_sessions(days?, project?, limit?)` | Session metadata and token totals | | `get_token_usage(days?, by?, project?)` | Token usage by day, session, or model | -| `get_session_events(days?, tool?, session_id?)` | Recent events with filtering | +| `get_session_events(start?, end?, tool?, session_id?, limit?)` | Recent events with filtering | | `get_file_activity(days?, project?, limit?, collapse_worktrees?)` | File reads/edits/writes breakdown | | `get_projects(days?)` | Activity across all projects | | `get_mcp_usage(days?, project?)` | MCP server and tool usage | @@ -67,7 +67,7 @@ Use `get_tool_sequences(expand=True)` to discover expanded patterns, then `sampl | Tool | Purpose | |------|---------| -| `classify_sessions(days?, project?)` | Categorize sessions with explanation of why | +| `classify_sessions(days?, project?, limit?)` | Categorize sessions with explanation of why | Each session includes `classification_factors` explaining WHY it was categorized: - `trigger`: The threshold that was exceeded (e.g., "error_rate > 15%") @@ -94,7 +94,7 @@ Returns both core metrics (`events`, `sessions`, `errors`, `tokens`) and `effici | Tool | Purpose | |------|---------| -| `get_session_messages(days?, session_id?, entry_types?, max_message_length?)` | Messages across sessions chronologically (user + assistant by default) | +| `get_session_messages(days?, session_id?, limit?, entry_types?, max_message_length?)` | Messages across sessions chronologically (user + assistant by default) | | `search_messages(query, limit?, entry_types?)` | Full-text search across all message types (FTS5) | **entry_types**: Filter by `["user"]`, `["assistant"]`, `["tool_result"]`, `["summary"]` or any combination. @@ -108,7 +108,7 @@ Returns both core metrics (`events`, `sessions`, `errors`, `tokens`) and `effici | Tool | Purpose | |------|---------| | `detect_parallel_sessions(days?, min_overlap_minutes?)` | Find simultaneously active sessions | -| `find_related_sessions(session_id)` | Find sessions with similar patterns | +| `find_related_sessions(session_id, method?, days?, limit?)` | Find sessions with similar patterns | ### Git Integration diff --git a/src/session_analytics/queries.py b/src/session_analytics/queries.py index 2d1ed2b..3cde9ff 100644 --- a/src/session_analytics/queries.py +++ b/src/session_analytics/queries.py @@ -441,6 +441,7 @@ def query_sessions( storage: SQLiteStorage, days: int = 7, project: str | None = None, + limit: int = 20, ) -> dict: """Get session metadata. @@ -448,6 +449,7 @@ def query_sessions( storage: Storage instance days: Number of days to analyze project: Optional project path filter + limit: Maximum sessions to return Returns: Dict with session information @@ -469,8 +471,9 @@ def query_sessions( FROM sessions WHERE {where_clause} ORDER BY last_seen DESC + LIMIT ? """, - params, + (*params, limit), ) sessions = [ @@ -497,6 +500,7 @@ def query_sessions( return { "days": days, "project": project, + "limit": limit, "session_count": len(sessions), "total_entries": total_entries, "total_tool_uses": total_tools, @@ -1066,6 +1070,7 @@ def classify_sessions( storage: SQLiteStorage, days: int = 7, project: str | None = None, + limit: int = 20, ) -> dict: """Classify sessions based on their dominant activity patterns. @@ -1082,6 +1087,7 @@ def classify_sessions( storage: Storage instance days: Number of days to analyze (default: 7) project: Optional project filter + limit: Maximum sessions to return (default: 20) Returns: Dict with: @@ -1284,9 +1290,10 @@ def classify_sessions( return { "days": days, "project": project, + "limit": limit, "session_count": len(classifications), "category_distribution": category_counts, - "sessions": classifications[:50], # Limit output + "sessions": classifications[:limit], } @@ -2572,7 +2579,7 @@ def get_session_efficiency( storage: SQLiteStorage, days: int = 7, project: str | None = None, - limit: int = 50, + limit: int = 20, ) -> dict: """Analyze session efficiency: burn rate, compactions, read patterns. @@ -2588,7 +2595,7 @@ def get_session_efficiency( storage: Storage instance days: Number of days to analyze (default: 7) project: Optional project filter - limit: Maximum sessions to return (default: 50) + limit: Maximum sessions to return (default: 20) Returns: Dict with efficiency metrics per session diff --git a/src/session_analytics/server.py b/src/session_analytics/server.py index 2ffb77e..13426e2 100644 --- a/src/session_analytics/server.py +++ b/src/session_analytics/server.py @@ -98,7 +98,7 @@ def get_session_events( tool: str | None = None, project: str | None = None, session_id: str | None = None, - limit: int = 100, + limit: int = 50, ) -> dict: """Get events in a time window or for a specific session. @@ -108,7 +108,7 @@ def get_session_events( tool: Tool name filter project: Project path filter session_id: Session ID filter - limit: Max events (default: 100) + limit: Max events (default: 50) """ from datetime import datetime @@ -129,15 +129,16 @@ def get_session_events( @mcp.tool() -def list_sessions(days: int = 7, project: str | None = None) -> dict: +def list_sessions(days: int = 7, project: str | None = None, limit: int = 20) -> dict: """List all sessions with metadata. Args: days: Days to analyze (default: 7) project: Project path filter + limit: Max sessions (default: 20) """ queries.ensure_fresh_data(storage, days=days, project=project) - result = queries.query_sessions(storage, days=days, project=project) + result = queries.query_sessions(storage, days=days, project=project, limit=limit) return {"status": "ok", **result} @@ -248,7 +249,7 @@ def get_session_messages( days: float = 1, include_projects: bool = True, session_id: str | None = None, - limit: int = 100, + limit: int = 50, entry_types: list[str] | None = None, max_message_length: int = 500, ) -> dict: @@ -258,7 +259,7 @@ def get_session_messages( days: Days to look back (default: 1, supports 0.5 for 12h) include_projects: Include project info (default: True) session_id: Session ID filter - limit: Max messages (default: 100) + limit: Max messages (default: 50) entry_types: Types to include (default: ["user", "assistant"]) max_message_length: Truncate length (default: 500, 0=no limit) """ @@ -340,7 +341,7 @@ def detect_parallel_sessions(days: float = 1, min_overlap_minutes: int = 5) -> d @mcp.tool() def find_related_sessions( - session_id: str, method: str = "files", days: int = 7, limit: int = 10 + session_id: str, method: str = "files", days: int = 7, limit: int = 20 ) -> dict: """Find sessions related to a given session. @@ -348,7 +349,7 @@ def find_related_sessions( session_id: Session to find related sessions for method: 'files', 'commands', or 'temporal' (default: 'files') days: Days to search (default: 7) - limit: Max related sessions (default: 10) + limit: Max related sessions (default: 20) """ queries.ensure_fresh_data(storage, days=days) result = queries.find_related_sessions( @@ -403,15 +404,16 @@ def get_error_details(days: int = 7, tool: str | None = None, limit: int = 50) - @mcp.tool() -def classify_sessions(days: int = 7, project: str | None = None) -> dict: +def classify_sessions(days: int = 7, project: str | None = None, limit: int = 20) -> dict: """Classify sessions by activity pattern (debugging/development/research/maintenance/mixed). Args: days: Days to analyze (default: 7) project: Project filter + limit: Max sessions (default: 20) """ queries.ensure_fresh_data(storage, days=days) - result = queries.classify_sessions(storage, days=days, project=project) + result = queries.classify_sessions(storage, days=days, project=project, limit=limit) return {"status": "ok", **result} @@ -630,14 +632,14 @@ def get_large_tool_results( def get_session_efficiency( days: int = 7, project: str | None = None, - limit: int = 50, + limit: int = 20, ) -> dict: """Analyze context efficiency and burn rate across sessions. Args: days: Days to analyze (default: 7) project: Project path filter - limit: Max sessions (default: 50) + limit: Max sessions (default: 20) """ queries.ensure_fresh_data(storage, days=days) result = queries.get_session_efficiency(storage, days=days, project=project, limit=limit) From e74b8509ffc5945ebf648a3440275b598102419f Mon Sep 17 00:00:00 2001 From: Evan Senter Date: Sun, 11 Jan 2026 23:42:14 +0000 Subject: [PATCH 2/2] feat: Add CLI parity and defaults guidance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add --limit to sessions and classify CLI commands - Align CLI defaults with MCP: journey 100→50, related 10→20, bus-events 100→50, efficiency 50→20 - Add Default Parameters section to CLAUDE.md with semantic guidelines - Fix test Args classes for new limit parameter Co-Authored-By: Claude Opus 4.5 --- CLAUDE.md | 14 ++++++++++++++ src/session_analytics/cli.py | 13 ++++++++----- tests/test_cli.py | 3 +++ 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index b305b7d..ff9bb3e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -103,3 +103,17 @@ def get_tool_frequency(...): expand: Include Bash→command, Skill→name, Task→subagent breakdown """ ``` + +### Default Parameters + +Use semantic defaults based on use case, not arbitrary consistency: + +| Use Case | `days` | `limit` | Rationale | +|----------|--------|---------|-----------| +| **Pattern analysis** (sequences, frequency, trends) | `7` | `50` | Patterns need aggregated data | +| **Session lists** (list_sessions, classify, efficiency) | `7` | `20` | Sessions are large objects | +| **Recent activity** (messages, parallel) | `1` | `50` | Typically want today's context | +| **Samples** (sample_sequences) | `7` | `5` | Samples should be small | +| **Handoff context** | `0.17` | `10` | Very recent context (~4h) | + +Keep MCP and CLI defaults aligned - check both `server.py` and `cli.py` when changing defaults. diff --git a/src/session_analytics/cli.py b/src/session_analytics/cli.py index 43ff6e8..0bfa2d9 100644 --- a/src/session_analytics/cli.py +++ b/src/session_analytics/cli.py @@ -856,7 +856,7 @@ def cmd_commands(args): def cmd_sessions(args): """Show session info.""" storage = SQLiteStorage() - result = query_sessions(storage, days=args.days, project=args.project) + result = query_sessions(storage, days=args.days, project=args.project, limit=args.limit) print(format_output(result, args.json)) @@ -1112,6 +1112,7 @@ def cmd_classify(args): storage, days=args.days, project=args.project, + limit=args.limit, ) print(format_output(result, args.json)) @@ -1552,6 +1553,7 @@ def main(): sub = subparsers.add_parser("sessions", help="Show session info") sub.add_argument("--days", type=int, default=7, help="Days to analyze (default: 7)") sub.add_argument("--project", help="Project path filter") + sub.add_argument("--limit", type=int, default=20, help="Max sessions (default: 20)") sub.set_defaults(func=cmd_sessions) # tokens @@ -1611,7 +1613,7 @@ def main(): sub.add_argument( "--days", type=float, default=1, help="Days to look back (default: 1, supports 0.5 for 12h)" ) - sub.add_argument("--limit", type=int, default=100, help="Max messages (default: 100)") + sub.add_argument("--limit", type=int, default=50, help="Max messages (default: 50)") sub.add_argument("--no-projects", action="store_true", help="Exclude project info") sub.add_argument("--session-id", help="Filter to specific session ID") sub.add_argument( @@ -1649,7 +1651,7 @@ def main(): help="Relation method (default: files)", ) sub.add_argument("--days", type=int, default=7, help="Days to search (default: 7)") - sub.add_argument("--limit", type=int, default=10, help="Max results (default: 10)") + sub.add_argument("--limit", type=int, default=20, help="Max results (default: 20)") sub.set_defaults(func=cmd_related) # failures @@ -1671,6 +1673,7 @@ def main(): sub = subparsers.add_parser("classify", help="Classify sessions by activity type") sub.add_argument("--days", type=int, default=7, help="Days to analyze (default: 7)") sub.add_argument("--project", help="Project filter") + sub.add_argument("--limit", type=int, default=20, help="Max sessions (default: 20)") sub.set_defaults(func=cmd_classify) # handoff @@ -1767,7 +1770,7 @@ def main(): sub.add_argument("--days", type=int, default=7, help="Days to analyze (default: 7)") sub.add_argument("--event-type", help="Filter by event type (e.g., 'gotcha_discovered')") sub.add_argument("--repo", help="Filter by repo name") - sub.add_argument("--limit", type=int, default=100, help="Max events to return (default: 100)") + sub.add_argument("--limit", type=int, default=50, help="Max events to return (default: 50)") sub.set_defaults(func=cmd_bus_events) # Issue #69: Compaction and efficiency commands @@ -1818,7 +1821,7 @@ def main(): sub = subparsers.add_parser("efficiency", help="Show session context efficiency metrics") sub.add_argument("--days", type=int, default=7, help="Days to analyze (default: 7)") sub.add_argument("--project", help="Project path filter") - sub.add_argument("--limit", type=int, default=50, help="Max sessions to return (default: 50)") + sub.add_argument("--limit", type=int, default=20, help="Max sessions to return (default: 20)") sub.set_defaults(func=cmd_efficiency) # benchmark (Issue #63) diff --git a/tests/test_cli.py b/tests/test_cli.py index 88e2590..46b19c9 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -186,6 +186,7 @@ class Args: json = False days = 7 project = None + limit = 20 with patch("session_analytics.cli.SQLiteStorage", return_value=populated_storage): cmd_sessions(Args()) @@ -580,6 +581,7 @@ class Args: json = False days = 7 project = None + limit = 20 with patch("session_analytics.cli.SQLiteStorage", return_value=populated_storage): cmd_classify(Args()) @@ -780,6 +782,7 @@ class Args: json = False days = 7 project = None + limit = 20 with patch("session_analytics.cli.SQLiteStorage", return_value=storage): cmd_sessions(Args())