Skip to content

feat(hooks): add Git LFS support to global git hooks#1

Open
TimeToLearnAlice wants to merge 173 commits into
masterfrom
feat/git-lfs-hooks
Open

feat(hooks): add Git LFS support to global git hooks#1
TimeToLearnAlice wants to merge 173 commits into
masterfrom
feat/git-lfs-hooks

Conversation

@TimeToLearnAlice

Copy link
Copy Markdown
Owner

Adds Git LFS support to the global git hooks:

  • Add Git LFS post-checkout call to existing branch validation hook
  • Add Git LFS pre-push call to existing push protection hook
  • Create post-commit hook with Git LFS support
  • Create post-merge hook with Git LFS support

This enables automatic LFS file handling across all repos without requiring 'git lfs install' to be run per-repo.

TimeToBuildBob and others added 30 commits December 20, 2025 08:36
* feat(precommit): add lesson metadata validation

Adds pre-commit hook that validates lesson files have proper metadata:
- Valid YAML frontmatter
- match.keywords field with at least one keyword
- Content starts with markdown heading

Also updates CONTRIBUTING.md with lesson creation guidelines.

Closes gptme#70

* fix(precommit): add pyyaml dependency for lesson validation hook

The hook uses PyYAML for parsing frontmatter but it wasn't installed
in CI since the hook used language: system. Changed to language: python
with additional_dependencies to ensure pyyaml is available.

* fix(precommit): address Greptile review feedback

- Add 'automated' status to CONTRIBUTING.md example
- Fix fragile path filtering to use is_relative_to() instead of string matching
- Fix inconsistent empty keyword handling (check empty/whitespace together)

* fix: add uv script dependency declaration for pyyaml

Addresses Greptile review feedback - script now properly declares
pyyaml dependency using uv inline script metadata format.
* feat(lsp): add Phase 5 features (inlay hints, call hierarchy)

Phase 5 LSP features:
- lsp hints <file> [start:end] - Get inlay hints (parameter names, types)
- lsp callers <file:line:col> - Find functions that call a symbol
- lsp callees <file:line:col> - Find functions called by a symbol

New dataclasses:
- InlayHint - represents inline annotations
- CallHierarchyItem - represents items in call hierarchy
- CallHierarchyCall - represents caller/callee relationships

LSP methods implemented:
- textDocument/inlayHint
- textDocument/prepareCallHierarchy
- callHierarchy/incomingCalls
- callHierarchy/outgoingCalls

Addresses Issue gptme/gptme#961

* refactor(lsp): extract _build_lsp_item_from_hierarchy_item helper

Address Greptile review feedback: DRY up duplicate lsp_item
construction in get_incoming_calls and get_outgoing_calls by
extracting common logic into helper method.

Reduces code duplication by 12 lines while improving maintainability.
…bols) (gptme#68)

This adds Phase 3 LSP features on top of the existing Phase 4-6 implementation:

New Commands:
- lsp actions <file:line:col> - Get code actions (quick fixes, refactoring)
- lsp symbols <query> - Search for symbols across workspace

Implementation:
- CodeAction and SymbolInfo dataclasses
- get_code_actions() and get_workspace_symbols() methods
- _parse_code_actions() and _parse_workspace_symbols() parsers
- Updated tool instructions and usage messages
…e lens) (gptme#73)

* feat(lsp): add Phase 6 features (semantic tokens, document links, code lens)

Phase 6 implementation adds:

1. **Semantic Tokens** (`lsp tokens <file> [start:end]`):
   - Get semantic token information for rich syntax highlighting
   - Shows token types (function, variable, class, parameter, etc.)
   - Shows token modifiers (declaration, readonly, etc.)
   - Supports optional line range filtering

2. **Document Links** (`lsp links <file>`):
   - Find clickable links in documents
   - Supports URLs, file paths, and other linkable content
   - Shows link targets and tooltips

3. **Code Lenses** (`lsp lens <file>`):
   - Get actionable annotations above code
   - Shows items like "5 references", "Run test"
   - Provides command information for each lens

New dataclasses: SemanticToken, DocumentLink, CodeLens
New LSPServer methods: get_semantic_tokens, get_document_links, get_code_lenses
New LSPManager methods: get_semantic_tokens, get_document_links, get_code_lenses
New tool commands: tokens, links, lens

Updated tool instructions to agent-focused style (consistent with Phase 4).
Updated README with Phase 6 documentation.

* fix(lsp): address review feedback for Phase 6

- Remove duplicate configuration content in README (lines 91-131)
- Fix semantic tokens range bug: use character 999 for end position
  to include the full last line when filtering by range

Fixes issues identified by Greptile review:
- Duplicate README sections
- Off-by-one error in semantic tokens range handling

* fix: address inline review comments

- Use rsplit for tokens target parsing to handle Windows paths (C:\path:10:20)
- Fix LSP range end position to use end_line with character 0 (half-open semantics)
* docs(lessons): upstream improvements from Bob's workspace

Sync lesson enhancements discovered through divergence analysis:

- check-existing-prs.md: Add 'issue has been open for a while' keyword,
  improve 'duplicate PR' → 'duplicate PR risk', add GitHub Issue Engagement link
- shell-command-chaining.md: Add Benefits section (variable scoping,
  execution overhead, logical grouping)
- browser-verification.md: Add '(from logs)' specificity, improve example
  reference

These improvements came from Bob's workspace evolution and help other agents
benefit from enhanced pattern matching and documentation.

Related: ErikBjare/bob#201 (lesson sync analysis)

* docs(lessons): add more lesson improvements from Bob

Additional lessons with generic improvements:

- python-invocation.md: Add Benefits section, PEP 394 reference link
- read-full-github-context.md: Better keywords for pattern matching,
  add Related link

Continuing lesson sync effort from ErikBjare/bob#201

* docs(lessons): add github-issue-engagement lesson

Fixes broken links in check-existing-prs.md and read-full-github-context.md
which both reference ../social/github-issue-engagement.md.

The lesson was upstreamed from Bob's workspace, providing guidance on:
- Searching for existing issues/PRs before creating new ones
- Reading full context including comments
- Updating issues/PRs after completing work
…hods (gptme#75)

* fix(lsp): add missing @DataClass decorator and LSPManager Phase 6 methods

Fixes type errors introduced in Phase 6 LSP PR:
- Add @DataClass decorator to LSPServer class (required for field() usage)
- Add Phase 6 delegation methods to LSPManager:
  - get_semantic_tokens()
  - get_document_links()
  - get_code_lenses()

These were missing, causing mypy to fail with 'unexpected keyword argument'
and 'has no attribute' errors.

Co-authored-by: Bob <bob@superuserlabs.org>

* style(lsp): remove orphaned @DataClass decorator

Fixes Greptile review comment about SemanticToken being decorated twice.
The orphaned @DataClass on line 232 was causing double decoration - now
only the correct decorator on line 236 remains.
…me#67)

* feat(lessons): add inter-agent communication and workspace review patterns

- Add inter-agent-communication.md with GitHub issues pattern
- Add cross-agent-workspace-review.md for systematic workspace analysis
- Both lessons based on successful Alice-Bob collaboration (Issue gptme#6)
- Provides concrete patterns for agent coordination and learning

* fix: replace broken lesson reference with existing read-full-github-context.md

- Replace non-existent 'GitHub Issue Engagement lesson' reference
- Reference existing 'Read Full GitHub Context' lesson which is relevant for inter-agent communication
- Fixes broken link identified in PR review comments

* ci: trigger pre-commit re-run after broken reference fix
)

* feat(imagen): add image modification support with text prompts

Implements Issue gptme#77: Add image + text modification capability to imagen plugin.

New features:
- modify_image() function for editing existing images with text prompts
- Uses Gemini's multimodal API to accept both image and text input
- Supports view parameter to display results to LLM
- Includes cost tracking for modification operations

Example usage:
  modify_image(
      image_path='avatar.png',
      prompt='change the background to a sunset beach',
      view=True
  )

Currently only Gemini supports image modification. For DALL-E,
users can use generate_variation() for variations without text guidance.

Closes gptme#77

Co-authored-by: Bob <bob@superuserlabs.org>

* fix(lessons): make agent names generic to pass check-names hook

- Replace Bob/Alice references with generic agent terms
- Update keywords to remove agent-specific names
- Ensure files end with newline for end-of-file-fixer

* fix(imagen): use correct model name for cost calculation

Greptile correctly identified that calculate_cost was using
'gemini-3-pro-image-preview' which isn't in PROVIDER_COSTS.
Changed to use 'imagen-3-fast' for cost lookup while keeping
the actual model name in record_generation for tracking purposes.

* feat(imagen): implement unified images API (Option C)

Implements Erik's preferred Option C - a unified images parameter for generate_image():
- Add images parameter to generate_image() and _generate_gemini()
- Accepts single path (str) or list of paths for multi-reference generation
- Docstring explains use cases: references, style refs, images to modify
- Parameter named 'images' (not 'reference_images') per Erik's feedback
- Updated tool instructions to document the new parameter
- Passes images through to Gemini API as multimodal contents

Co-authored-by: Bob <bob@superuserlabs.org>

* feat(imagen): add images parameter to generate_image() for multimodal generation

Per Erik's design review (Option C): unified API for image generation with references.

Changes:
- Add `images` parameter to generate_image() accepting single path or list
- Support multi-reference generation with Gemini (up to 14 images as input)
- Update _generate_gemini() to handle optional images
- Add early provider validation (raises ValueError instead of RuntimeError)
- Fix case-sensitive API key error detection

This enables:
- Single image modification: generate_image(prompt='...', images='portrait.png')
- Multi-reference generation: generate_image(prompt='...', images=['ref1.png', 'ref2.png'])

The existing modify_image() function remains for backward compatibility.
All 90 tests pass.

* refactor(imagen): remove modify_image in favor of generate_image(images=...)
Adds 'gptme Wrapped' - Spotify Wrapped style analytics for gptme usage:
- Token usage tracking (input/output/cache)
- Cost analysis by model and time period
- Usage patterns (peak hours, active days)
- Export to JSON/CSV/HTML

Also adds skill documentation explaining the storage format.
Adds wrapped_heatmap() function that displays a week-by-week activity
heatmap showing conversation frequency throughout the year, similar to
GitHub's contribution graph.
Comprehensive guide for creating gptme plugins covering:
- Tool creation with ToolSpec
- Hook registration patterns
- Command handlers
- Testing strategies
- Common patterns and troubleshooting

Based on experience creating the wrapped plugin and reviewing existing
plugins (imagen, lsp, consortium, example-hooks).
Allows running gptme-wrapped without loading into gptme:
  python -m gptme_wrapped           # Show report
  python -m gptme_wrapped heatmap   # Show heatmap
  python -m gptme_wrapped stats     # JSON stats
- Add missing configuration section to wrapped README
- Fix example-hooks to use [plugins] format (was [gptme])
- Fix warp-grep to use [plugins] format (was [tools])
- Add links to gptme.org plugin configuration docs
- Clarify user vs project level configuration
- Ensure consistent 'limit which plugins load' comment
gptme requires Python 3.10+, so the mypy pre-commit hook needs
to use at least Python 3.10 instead of defaulting to system Python.
- Specify Python 3.10 for mypy hook (gptme requires 3.10+)
- Exclude plugins/ from global mypy (handled by typecheck-packages)
- Add tomli dependency for lib package typecheck
- Add type annotations to wrapped plugin stats dicts
- Fix type ignore comment in config.py
- Apply ruff-format fixes
gptme#85)

* feat(plugins): add cc-analyze plugin for Claude Code subagent analysis

Add new plugin for spawning focused Claude Code analysis tasks from gptme.

Features:
- analyze() function to run CC with a prompt synchronously or in background
- check_session() to monitor background tasks
- kill_session() to terminate background tasks
- Supports timeout configuration
- Background mode via tmux for long-running tasks

Use cases:
- Security audits
- Code reviews
- Test coverage analysis
- Architecture documentation

Addresses ErikBjare/bob#209

* fix: update mypy language_version to python3.11

CI runners don't have python3.10 available, causing pre-commit to fail with:
'failed to find interpreter for python_spec=python3.10'

* fix(cc-analyze): use shutil.which and shlex.quote for safety

- Use shutil.which instead of subprocess 'which' for portability
- Use shlex.quote for prompt and work_dir to prevent command injection
- Addresses review feedback from automated reviewers

* fix: add tomli to mypy additional_dependencies

Mypy was failing with 'Cannot find implementation or library stub for module named tomli'
because packages/lib/src/lib/config.py imports tomli.

* fix: expand type ignore to cover import-not-found for tomli

* fix: add --disable-error-code=unused-ignore to lib typecheck

* fix: remove unused import-not-found type ignore

tomli is now available in typecheck environment, so the import-not-found
ignore is no longer needed. Keep no-redef for the conditional import.
* fix(cc-analyze): add execute function for block support

The cc_analyze tool defined block_types=['cc_analyze'] but had no execute
function, making blocks non-functional. This adds execute_cc_analyze() that:
- Parses and executes block content as Python code
- Makes analyze/check_session/kill_session functions available
- Returns results as Message objects
- Handles errors gracefully

Fixes ErikBjare/bob#209

* fix(cc-analyze): prevent duplicate execution in eval fallback

Fixes logic error identified by Greptile review:
- Before: exec() ran code, then eval() ran it AGAIN as fallback
- After: compile() checks if expression, eval() OR exec() runs once

The old code would call analyze() twice for simple expressions.
Now we detect expression vs statements BEFORE running:
- Expression: eval() once, capture return value
- Statements: exec() once, look for explicit result variable

* refactor(cc-analyze): remove block_types in favor of ipython functions

Per Erik's review feedback:
- Functions are already available via ipython (analyze, check_session, kill_session)
- No meaningful value added by separate cc_analyze block syntax
- Simplifies the tool by removing unnecessary execute function

Removes:
- block_types=['cc_analyze'] from ToolSpec
- execute_cc_analyze function
- Unused imports (Message, ConfirmFunc, print_preview)

* refactor(cc-analyze): remove block_types, use ipython functions only

Per Erik's feedback: block_types shouldn't be valid if execute is not set.
The functions (analyze, check_session, kill_session) are already available
via ipython, making the cc_analyze block syntax redundant.

Changes:
- Remove execute_cc_analyze function (no longer needed)
- Remove block_types and execute from ToolSpec
- Update all examples to use ipython blocks instead of cc_analyze blocks
- Clean up unused Message import
…ptme#87)

* fix(cc-analyze): warn when sync timeout exceeds prompt cache window

Add runtime warning when analyze() is called with timeout >240 seconds
and background=False, since prompt cache expires at 5 minutes.

Also updated tool instructions to document async patterns for long tasks.

Addresses ErikBjare/bob#212

* fix(cc-analyze): error on sync timeout >=300s, clarify cache docs

Address review feedback from ErikBjare:
- Raise ValueError when sync call timeout >=300s (5+ min) to prevent stalling
- Clarify that checking every 4 min is only needed when waiting for results
  (not if it can be handled in follow-up session)
Replace generic keywords with specific problem-trigger phrases.

Improved lessons:
- ast-grep-refactoring: sg run --pattern
- shell-output-filtering: filter output with grep head tail

Part of Bob Issue gptme#212 CC maximization work.
gptme#88)

* feat(run_loops): support multiple orgs and repos in project monitoring

- Add target_orgs (list) and target_repos (list) parameters
- discover_repositories() now iterates over all orgs and includes explicit repos
- CLI supports --org and --repo multiple times
- Uses set to avoid duplicate repos

* fix: remove hardcoded gptme default from --org option
…ng (gptme#92)

Add check_notifications() method to discover work from GitHub notifications:

Features:
- Checks unread GitHub notifications via 'gh api notifications'
- Filters for relevant reasons: mention, assign, review_requested, team_mention
- Extracts PR/issue numbers from notification URLs
- Creates WorkItems with item_type='notification'
- Tracks processed notifications to avoid duplicates

Integration:
- Called in discover_work() before per-repo checks
- Works globally across all repos (not limited to configured repos)
- Allows discovering mentions in repos not explicitly monitored

This enables the monitoring system to pick up work from any repo
where the agent is mentioned, assigned, or requested for review.

Usage:
  The monitoring script will now automatically check notifications
  and create work items for any repos where you're mentioned,
  even if those repos aren't in --org or --repo configuration.

Related to user request for notification monitoring support.
* feat(status): add generalized infrastructure status scripts

Add status monitoring scripts generalized from Bob's workspace:

- status.sh: Main status overview script
- status-systemd.sh: Systemd service status utility
- lock-status.sh: Lock status utility (optional)
- README.md: Comprehensive documentation

Features:
- Works with any agent (configurable via AGENT_NAME)
- Shows systemd service status and timers
- Optional lock status monitoring
- Color-coded output with timing information

The scripts auto-detect agent name from workspace directory
or can be configured via environment variables.

Based on Bob's workspace implementation, generalized for
community use in gptme-contrib.

Closes Miyou/thomas#1

* fix: address Greptile review comments

- Fix reference to non-existent lock-history.sh (critical)
- Add set -e to status-systemd.sh for consistency
- Implement SHOW_HEADER variable (was defined but unused)
- Complete Expected Output section in README
- Remove unused color variables (GREEN, RED, YELLOW) per shellcheck

* style: use set -euo pipefail for stricter error handling

Address Greptile review feedback about inconsistent error handling.
All scripts in the status directory now use the same strict settings
as other scripts in the repository (e.g., repo-status.sh).

Also fixes:
- Invalid for loop syntax that would fail with stricter shell options
- Removes unused GREEN color variable

* fix: remove agent-specific 'Bob' references for generic use

- Replace 'Bob's workspace' with generic comments
- Use 'alice' and 'your-agent' in examples instead of 'bob'
- Fixes pre-commit check-names hook failure

* fix: use 'myagent' instead of 'alice' in examples

'alice' is also a known agent name and blocked by check-names hook

* fix(tests): update tests for target_orgs API change

ProjectMonitoringRun constructor now uses:
- target_orgs: list[str] | None (was target_org: str)
- target_repos: list[str] | None (new)

Updated tests to use the new API.

---------

Co-authored-by: Bob <bob@superuserlabs.org>
Capture pre-commit output and only display it on failure.
This saves tokens in agent context by not spamming with
'Passed' and 'Skipped' lines for every hook.
)

Co-authored-by: Alice <TimeToLearnAlice@users.noreply.github.com>

Original work from PR gptme#76 by Alice, rebased cleanly on master.
This lesson documents the structured process for establishing
agent visual identity including brand essence, design principles,
and implementation guidelines.
…l gptme agents (gptme#95)

* feat(lessons): add autonomous session lessons for all gptme agents

- autonomous-session-structure.md: 4-phase structured approach with memory failure prevention
- autonomous-session-pivot-strategies.md: handling technical blocks with alternative value-creation
- effective-autonomous-work-execution.md: task selection and execution strategies

These lessons provide proven patterns from practical autonomous session experience
that would benefit all gptme agents operating autonomously.

* feat(lessons): add advanced AI/ML concepts category

- Add ACE (Agentic Context Engineering) framework
- Add CASCADE context management strategy
- Add GEPA (Genetic Pareto) optimization concept
- Add LLMLingua compression techniques

Creates new 'concepts' category for advanced AI/ML knowledge
that benefits all gptme agents with research-backed frameworks.

* docs(concepts): add YAML frontmatter with keywords and metadata

- Add frontmatter to gepa-genetic-pareto.md with genetic algorithm keywords
- Add frontmatter to llmlingua-compression.md with compression keywords
- Improves lesson discoverability and categorization

* docs(lessons): standardize keywords to lowercase format

- Change 'PR creation' → 'pr creation'
- Change 'Conventional Commits' → 'conventional commits'
- Improves keyword consistency across lesson system

* fix(lessons): resolve CI failures - broken links, agent names, syntax errors, YAML formatting

- Fix broken markdown links (remove circular paths, non-existent files)
- Remove agent-specific names (Bob) for generalized lessons
- Fix syntax error: tail-5 → tail -5
- Remove duplicate code blocks
- Standardize YAML frontmatter (remove category/status fields)

Addresses review feedback from Greptile and Ellipsis on PR gptme#95

* fix(lessons): remove broken links to non-existent files

- Remove references to ../../knowledge/processes/ directory (doesn't exist in gptme-contrib)
- Remove broken link to ../workflow/memory-failure-prevention.md
- Fix inline code comments referencing non-existent files
- Add missing newlines at end of files

Co-authored-by: Bob <bob@superuserlabs.org>

---------

Co-authored-by: Bob <bob@superuserlabs.org>
* feat(tasks): add --user flag to filter tasks by assigned_to

Allows generating user-specific work queues:
  uv run python3 -m tasks.generate_queue --user human

When --user is specified:
- Filters tasks by assigned_to field (matches user or 'both')
- Includes all priorities (not just high/urgent)
- Outputs to queue-generated-{user}.md

Co-authored-by: Bob <bob@superuserlabs.org>

* fix(tasks): skip GitHub issues when filtering by user

When --user flag is specified, skip GitHub issues since they use a
different assignment model (GitHub usernames via assignees field)
than local tasks (role-based assigned_to field).

This provides consistency: with --user, you get only the tasks
explicitly assigned to that user, not unrelated GitHub issues.

Addresses Greptile review comment about GitHub issues not being
filtered when using --user flag.
…e#99)

* feat(packages): add gptmail - email automation for gptme agents

Upstream gptmail from Bob's workspace (github.com/ErikBjare/bob) as the
successor to scripts/email.

Features:
- CLI tools for reading, composing, and sending emails
- Background watcher for processing unreplied emails
- Shared communication utilities (auth, rate limiting, monitoring, state)
- Integration with Gmail via IMAP/SMTP

Updates pre-commit config to exclude gptmail from root mypy (uses its own
typecheck via make typecheck-packages).

Related: ErikBjare/bob#221

* fix: remove agent-specific names from gptmail package

- Replace hardcoded 'bob@' emails with AGENT_EMAIL env var
- Replace 'Bob/Bob-sent' Gmail labels with generic INBOX/Sent
- Rename external_maildir_bob -> external_maildir_inbox
- Update examples to use generic agent@example.com
- Make documentation agent-agnostic for reuse
- Add validation to require AGENT_EMAIL env var or own_email parameter

Co-authored-by: Bob <bob@superuserlabs.org>
…chars (gptme#101)

* fix(gptmail): RFC 2047 encode Subject and From headers for non-ASCII chars

Fixes email headers with special characters like åäö being garbled.
Uses email.header.Header to properly encode non-ASCII characters
per RFC 2047 before sending via msmtp.

Addresses ErikBjare/bob#221

* fix(gptmail): add .encode() to Header objects for type safety

Convert Header objects to strings using .encode() method to satisfy
mypy type checker. Header.encode() returns the RFC 2047 encoded string
representation, which is the correct type for email message headers.

* style(gptmail): always encode From header for consistency

Apply review suggestions from Greptile:
- Always RFC 2047 encode From header (like Subject)
- Simpler code: Header() handles ASCII efficiently
- More consistent behavior across all header types
ErikBjare and others added 27 commits January 29, 2026 22:13
…e#229)

* fix(gptodo): ensure tmux sessions inherit environment variables

When running gptodo spawn, the tmux detached session would not inherit
critical environment variables (API keys like OPENAI_API_KEY, PATH, etc.)
causing gptme to exit immediately without doing any work.

This fix:
1. Explicitly exports critical API keys within the tmux session
2. Uses 'bash -l -c' to ensure login shell behavior, sourcing .profile/.bashrc
3. Properly propagates HOME, PATH, and model-specific environment variables

Fixes: gptme#228

Test results showed gptodo spawn completing instantly with no output/changes
while gptodo run (foreground) worked correctly. The difference was that
subprocess.run inherits the parent environment, but tmux detached sessions
do not reliably inherit environment variables.

* fix(gptodo): shell-escape workspace path in spawn command

Addresses review comment from greptile about potential command
injection if workspace path contains special characters.

* fix(typing): remove deprecated confirm parameter from step() and execute()

- Remove confirm parameter from tool_pushover.py execute function
- Remove confirm_func and confirm arg from discord_bot.py step() call
- These parameters were removed from gptme's API
When spawning subagents with the 'claude' backend, don't export
ANTHROPIC_API_KEY or other API keys to the tmux session.

Claude Code uses OAuth authentication for its Max subscription
(flat-fee). If ANTHROPIC_API_KEY is in the environment, Claude Code
uses it instead, resulting in:
- Metered API usage instead of subscription
- Hitting the API rate limits (429 errors)

This fix ensures:
- gptme backend: Gets all API keys (it needs them)
- claude backend: Only gets PATH, HOME, GPTME_MODEL (uses OAuth)

Fixes issue raised in gptme#228

Tested:
- With ANTHROPIC_API_KEY in env: claude CLI uses API key (429 error)
- Without ANTHROPIC_API_KEY: claude CLI uses subscription (works)
…eval (gptme#230)

* feat(plugins): add gptme-retrieval plugin for automatic context retrieval

Adds a STEP_PRE hook that automatically retrieves relevant context before
each LLM step using backends like qmd for semantic search.

Features:
- Configurable backends: qmd (default), grep, or custom command
- Multiple search modes: BM25, semantic (vsearch), or hybrid
- Score threshold filtering
- Collection-based filtering
- Flexible injection (system or hidden messages)

Configuration via [plugin.retrieval] in gptme.toml, using the new plugin
namespace support from gptme#1197.

Closes gptme/gptme#59

* feat(plugins): add gptme-retrieval plugin for automatic context retrieval

Implements retrieval hook (STEP_PRE) that automatically fetches relevant
context before each LLM step using qmd or other backends.

Features:
- Shell-based retrieval using qmd (vsearch, search, query modes)
- Config from [plugin.retrieval] namespace in gptme.toml
- Fallback grep backend
- Threshold-based filtering
- Configurable result injection (system/hidden)

Relates to gptme#59, gptme#1197

* fix(retrieval): address security review and add gptme-rag backend

- Fix shell injection vulnerability in _retrieve_custom() by using shlex.split()
  instead of shell=True (critical security fix per Greptile review)
- Add gptme-rag backend support per Erik's request
- Update qmd URL to ErikBjare/qmd fork
- Add documentation for gptme-rag in README

* chore: exclude .egg-info from version control
* feat(gptodo): add clear_keys option to spawn_agent for credential isolation

Add clear_keys parameter to spawn_agent() that explicitly unsets API keys
for backends that have their own authentication (Claude Code, Codex).

Changes:
- Add clear_keys: Optional[bool] parameter (auto-detects based on backend)
- For tmux sessions: adds 'unset VAR1 VAR2 ...' before exports
- For foreground: passes modified env dict to subprocess.run()
- Supports claude and codex backends (with their OAuth subscriptions)

This solves the issue where Claude Code would use ANTHROPIC_API_KEY from
the environment instead of its OAuth subscription, hitting rate limits.

Closes gptme#228 (API key vs OAuth issue)

Co-authored-by: Bob <bob@superuserlabs.org>

* fix(gptodo): add 'codex' to backend type annotation for forward compatibility

Addresses Greptile review feedback: the clear_keys check references 'codex'
backend (per Erik's suggestion for future use), but the type annotation
only included 'gptme' and 'claude'. This adds 'codex' to the Literal
type annotation for forward compatibility.
* feat(lessons): add persist-before-noting pattern

Triggered on phrases like 'noted for future reference' to
ensure agents actually persist insights to core files instead
of making empty promises that will be forgotten next session.

Ref: ErikBjare/bob#255

* fix(lessons): add missing status: active field to persist-before-noting

Addresses Greptile review comment about missing status field in
frontmatter for consistency with other pattern lessons.

* Apply suggestions from code review

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* Apply suggestion from @ErikBjare

---------

Co-authored-by: Erik Bjäreholt <erik@bjareho.lt>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
…on (gptme#235)

* feat(gptodo): add --changes-only flag to sync command

Helps detect stale queue entries by filtering sync output to show
only items where state has changed (out of sync or new activity).

When no changes detected, displays a clear message instead of full
table. Useful for agents to quickly check if any tracked items need
attention without re-reading entire sync output.

Ref: ErikBjare/bob#262

* fix(gptodo): show 'changed' in table title when --changes-only flag used

Addresses Greptile review comment: table title should show 'changed'
instead of 'tracked' when using --changes-only flag to match the
PR description example.
…iew state (gptme#233)

* feat(gptodo): add checker pattern, dependency tree, and ready_for_review state

Issue gptme#255 improvements inspired by Claude Code's tasks system:

1. **Checker pattern** (checker.py):
   - `gptodo checker <task>` - Run verification checks
   - `gptodo checker --poll` - Poll until completion
   - Verifies: subtask completion, dependency resolution, state validity
   - Shows valid state transitions with `gptodo transitions`

2. **Dependency tree visualization** (deptree.py):
   - `gptodo dep tree <task>` - ASCII dependency tree
   - `gptodo dep tree <task> --format mermaid` - Mermaid diagram
   - `gptodo dep check` - Detect circular dependencies
   - Shows both upstream (requires) and downstream (required_by)

3. **Better status machine** (utils.py):
   - Added `ready_for_review` state between active and done
   - State flow: backlog → todo → active → ready_for_review → done
   - Enables explicit review/verification step before completion
   - Valid transitions documented and enforced

* fix(gptodo): address Greptile review comments

- checker: exclude URL deps from total count (len(resolved)+len(unresolved) now equals total)
- deptree: fix ASCII tree connectors when direction=both (use └── for final section)
…2) (gptme#236)

* feat(ace): add Curator module for lesson lifecycle management (Phase 2)

Migrates the Curator agent from Bob's workspace to gptme-contrib.

The Curator synthesizes refined insights into delta operations for
incremental lesson updates:
- CuratorAgent: Main agent class using Claude API
- Delta/DeltaOperation: Data classes for ADD/REMOVE/MODIFY ops
- InsightStorage/StoredInsight: Insight persistence layer
- CLI interface for generate, batch, and list commands

Phase 2 of ACE plugin migration (Phase 1 merged Jan 25).

Ref: ErikBjare/bob#256

* fix(ace): address Greptile review - nested dataclass deserialization and directory check

- storage.py: Deserialize nested InsightMetadata from dict when loading JSON
- curator.py: Check lessons_dir exists before iterating to prevent FileNotFoundError
…ktree-workflow (gptme#237)

* refactor(lessons): consolidate git-remote-branch-pushing into git-worktree-workflow

- Add post-push verification section to git-worktree-workflow
- Mark git-remote-branch-pushing as deprecated with pointer
- Remove overlapping keywords to reduce context bloat

The git-worktree-workflow already covers branch tracking comprehensively.
This consolidation reduces keyword overlap that caused both lessons to
trigger on any git operation.

Fixes: ErikBjare/bob#284

* fix(lessons): remove deprecated git-remote-branch-pushing reference from git-workflow.md

Addresses Greptile review comment: git-workflow.md still referenced the
deprecated lesson at line 109. Updated to point to the consolidated
git-worktree-workflow.md which now includes push verification guidance.
Implements gptme#227 - gptodo now auto-detects the correct tasks directory
instead of always using ./tasks/ relative to cwd.

Priority order:
1. --tasks-dir CLI option (highest priority)
2. GPTODO_TASKS_DIR environment variable
3. Auto-detect by looking for workspace markers:
   a. gptme.toml (gptme workspace config - strongest signal)
   b. .git with tasks/ sibling (task workspace)
   c. .git alone (any git repo - fallback)
4. ./tasks/ relative to cwd (ultimate fallback)

This fixes the issue where running gptodo from gptme-contrib would
create tasks in gptme-contrib/tasks/ instead of the target workspace.

Changes:
- utils.py: Enhanced find_repo_root() to look for workspace markers
- cli.py: Added --tasks-dir global option (also reads GPTODO_TASKS_DIR)
- Added 6 new tests for workspace detection
…me#239)

* feat(gptodo): add structured waiting_for support with auto-check

Implements Phase 1 of issue ErikBjare/bob#278:
- Add waiting.py module with WaitCondition types (pr_ci, pr_merged, comment, time)
- Add check functions for each condition type using gh CLI
- Add 'check-waiting' CLI command to check/update waiting conditions
- Add comprehensive tests (19 tests, all passing)

This enables tasks to specify machine-checkable waiting conditions:

    waiting_for:
      type: pr_ci
      ref: "gptme/gptme#1217"

Co-authored-by: Bob <bob@superuserlabs.org>

* fix(gptodo): address Greptile review feedback

- Fix timezone handling bug in check_time() that could crash on naive timestamps
- Update unblock.py to handle structured waiting_for formats (dict/list)
- Add comprehensive tests for check_time() and check_comment() functions

The timezone fix properly handles both aware and naive datetimes by checking
tzinfo before comparison. The unblock.py integration now uses parse_waiting_for()
to handle all formats consistently.
…ptme#240)

Add 'gptodo watch' command that continuously monitors structured waiting_for
conditions and auto-clears them when resolved.

Features:
- Configurable interval (default: 5 minutes)
- Auto-fix mode (clears resolved conditions by default)
- Single-run mode (--once) for testing/cron
- Change detection across iterations
- Graceful signal handling (SIGINT/SIGTERM)

This is Phase 2 of issue ErikBjare/bob#278 - CASCADE improvements.

Part-of: ErikBjare/bob#278
…e#241)

The claude CLI's --tools option accepts variadic arguments (tools...),
which was consuming the prompt as an additional tool name instead of
passing it as the positional prompt argument.

Fixes: gptme#228

Before: claude -p --tools default 'prompt'
  -> tools=['default', 'prompt'], prompt=None
  -> Error: Input must be provided either through stdin or as a prompt argument

After: claude -p --tools default -- 'prompt'
  -> tools=['default'], prompt='prompt'
  -> Works correctly
* fix(runloops): read agent name from workspace gptme.toml

Previously, generate_base_prompt() defaulted to 'Agent' when no explicit
agent_name was passed. This caused autonomous run prompts to show
'You are Agent...' instead of 'You are Bob...' (or whatever the configured
agent name is).

The fix adds a get_agent_name() utility that reads the [agent].name
from the workspace's gptme.toml file, falling back to 'Agent' if not
configured.

Both AutonomousRun and EmailRun now use this utility to pass the correct
agent name to generate_base_prompt().

Fixes: ErikBjare/bob#288

* fix(runloops): add Python 3.10 compatibility with tomli fallback

- Add conditional import for tomllib (Python 3.11+) / tomli (Python 3.10)
- Add tomli>=2.0.0 as conditional dependency for Python < 3.11
- Handle case where neither library is available (graceful fallback)
- Fix import ordering for cleaner code structure

Fixes Python 3.10 compatibility issue identified by Greptile review.
…tme#245)

* feat(gptme-ace): add Metrics module for curation quality tracking

Phase 5 (Utilities) - first module migration.

Adds:
- MetricsDB: SQLite-based storage for curation metrics
- CurationRun, InsightQuality, LessonImpact: Data classes
- MetricsCalculator: Aggregate metrics and system health
- get_default_metrics_db: Workspace-aware DB initialization
- CLI support for quick health checks
- Comprehensive tests (12 tests)

Tracks:
- Curation run effectiveness (success rate, conversion rate)
- Insight quality (actionable, novel, by category)
- Lesson impact (uses, helpful ratio, effectiveness)
- System health status with configurable thresholds

* fix(gptme-ace): use pytest.approx for floating-point comparisons

Fixes CI failure on Python 3.10 where float arithmetic precision
differs from 3.13. The test asserted 0.7499999999999999 == 0.75
due to (0.6+0.7+0.8+0.9)/4 precision.
…nalysis (gptme#244)

* feat(gptme-ace): add Generator and Reflector modules for trajectory analysis

Add two new modules to the ACE context optimization plugin:

- TrajectoryParser: Extracts thought-action-observation chains from session logs
- GeneratorAgent: Analyzes trajectories with Claude to generate candidate insights
- Insight dataclass for structured insight representation
- Few-shot examples for quality guidance
- Duplicate detection via existing lesson awareness

- ReflectorAgent: Critiques Generator output to identify meta-patterns
- Pattern dataclass for success/failure/recurring/emergent patterns
- RefinedInsight dataclass for improved clarity and actionability
- analyze_patterns(): Identifies patterns across multiple insights
- refine_insights(): Improves insight quality based on pattern context

Both modules include CLI interfaces for standalone usage.

Note: This PR includes Generator module which was also in PR gptme#243.
Consider closing gptme#243 after merging this PR.

Part of ACE migration from packages/ace/ (Issue ErikBjare/bob#256)

* fix(ace): address Greptile review feedback

- Fix invalid model name: claude-sonnet-4-5 → claude-sonnet-4-20250514
- Add runtime check for anthropic package in GeneratorAgent.__init__
- Add logging warning when anthropic import fails (both modules)
- Improve JSON parsing robustness: handle both markdown-wrapped and raw JSON
- Make workspace path configurable with auto-detection fallback
- Fix: end_idx check (> 0 vs > start_idx) for better validation

* fix(ace): use gptme config for model instead of hardcoding

Addresses Erik's review feedback: model should follow gptme config
instead of drifting as new models are released.

Changes:
- Add _get_default_anthropic_model() helper that checks:
  1. GPTME_ACE_MODEL environment variable (override)
  2. gptme's configured default model (if Anthropic)
  3. Falls back to claude-sonnet-4-5
- Make model parameter optional (None by default)
- Update docstrings to reflect new behavior

This allows ACE modules to automatically use whatever model gptme
is configured to use.

* fix(gptme-ace): fix misplaced @DataClass decorators

The _get_default_anthropic_model() helper function was incorrectly
placed after @DataClass decorators that were meant for the following
classes (ThoughtActionObservation and Pattern).

This caused import failures with:
  AttributeError: 'function' object has no attribute '__mro__'

Fix moves the decorator to the correct class definitions.
…e#249)

* feat(gptme-ace): add Visualization CLI for ACE data exploration

Add comprehensive CLI for exploring ACE context optimization data:

**Commands:**
- `ace-viz deltas list` - List deltas by status (pending/approved/rejected)
- `ace-viz deltas show <id>` - Show detailed delta information
- `ace-viz deltas summary` - Show delta statistics
- `ace-viz metrics runs` - Show curation run history
- `ace-viz metrics quality` - Show insight quality metrics
- `ace-viz metrics impact` - Show lesson impact rankings
- `ace-viz metrics trends` - Show trends over time
- `ace-viz dashboard` - Show overview dashboard

**Features:**
- JSON output support (`-j` flag) for all commands
- Partial ID matching for delta lookups
- Configurable time periods and limits
- Human-readable and programmatic output

Part of ACE Phase 5 Utilities.

Co-authored-by: Bob <bob@superuserlabs.org>

* refactor(gptme-ace): make click a default dependency

Per review feedback: click is required for the ace-viz CLI, so it
should be a default dependency rather than an optional one under [full].
* fix(discord): filter out internal system messages from chat

Previously, messages containing 'warning' would be displayed to users,
which included internal <system_warning> token usage messages.

Changes:
- Add skip_patterns list to filter out:
  - <system_warning> tags (token usage warnings)
  - <system_info> tags (internal info)
  - 'Ran command:' prefix (execution logs)
- Remove 'warning' from error detection (keep 'error', 'failed')
- Only display actual errors to users, not internal diagnostics

Fixes ErikBjare/bob#299

* fix(discord): skip all system messages and fix step signature

Per Erik's review: skip ALL system messages instead of checking
hardcoded prefixes (brittle). System messages are internal gptme
details - if there's an actual error, the assistant will communicate
it in its response. Still track errors for metrics/logging.

Also adds required 'confirm' parameter to step() call (fixes mypy).

* fix(discord): remove deprecated confirm parameter from step() call

The confirm parameter was removed from gptme's step() function.
Step auto-confirms tool execution by default, so no confirm callback is needed.

* fix(discord): remove brittle error checking from system messages

- Don't check for 'error'/'failed' in system message content
- had_error should only indicate real request execution failures
- Tool call errors are normal/recoverable, not request failures

Per Erik's review feedback on PR gptme#250
Phase 5 utilities - Applier module:
- DeltaApplier class to apply approved deltas to lesson files
- Supports ADD, REMOVE, MODIFY delta operations
- Dry-run mode for previewing changes
- Archives applied deltas with metadata
- CLI interface for single and batch application

Part of ACE migration tracked in ErikBjare/bob#256
…tme#248)

* feat(gptme-ace): add Reviewer module for delta quality evaluation

Part of ACE Phase 5 utilities for lesson lifecycle management.

The Reviewer module:
- Loads pending deltas from deltas/pending/
- Evaluates quality against 6 criteria (relevance, clarity, actionability,
  non-duplication, accuracy, format_compliance)
- Provides weighted scoring and recommendations (approve, reject, needs_revision)
- Supports auto-approve mode for CI workflows
- CLI interface for single/batch review

Features:
- DeltaReviewer class with configurable thresholds
- ReviewResult dataclass with criteria scores and suggestions
- Default criteria with weights for balanced evaluation
- move_to_approved/move_to_rejected for workflow integration
- get_status for pipeline monitoring

Tests: 21 tests added, all passing

* fix(reviewer): address Greptile review comments

- Enforce --all flag for batch command to prevent accidental operations
- Track auto_approved for both approve AND reject actions
- Rename 'reviewer' parameter to 'reviewer_name' for clarity

Addresses review comments from Greptile.
)

* feat(gptodo): add loop command for autonomous task processing

Implements 'gptodo loop' command that:
- Finds ready tasks (no unmet dependencies)
- Executes them sequentially or in parallel
- Supports dry-run mode for preview
- Integrates with existing spawn/run infrastructure

This enables autonomous runs to churn through ready work
without manual intervention, as suggested in ErikBjare/bob#296.

Features:
- --max-tasks/-n: Limit number of tasks to process
- --parallel/-p: Run multiple agents in parallel
- --dry-run: Preview what would be executed
- --backend: Choose gptme or claude
- --model: Specify model to use
- --timeout: Per-task timeout

Example usage:
  gptodo loop                    # Process up to 5 ready tasks
  gptodo loop -n 10              # Process up to 10 tasks
  gptodo loop --dry-run          # Show what would run
  gptodo loop -p 3               # Run 3 tasks in parallel

Co-authored-by: Bob <bob@superuserlabs.org>

* fix(gptodo): spawn all tasks in parallel mode, not just first N

Fixes bug identified by Greptile where parallel mode would only spawn
`parallel` agents instead of all tasks. Now spawns all tasks as
background agents - use --max-tasks to limit total tasks processed.

The -p/--parallel flag now simply enables parallel (background) mode
vs sequential (foreground) mode. Task count is controlled by -n.
* feat(plugin): add gptodo delegation plugin for coordinator mode

Adds a gptme plugin that wraps gptodo CLI commands as Python functions,
enabling the 'coordinator-only' agent pattern.

Functions: delegate, check_agent, list_agents, list_tasks, task_status, add_task

Usage: gptme --tools gptodo,save 'coordinate work'

Refs: ErikBjare/bob#300

* feat(runloops): add team coordinator run mode

Implements the autonomous-team pattern:
- TeamRun class runs coordinator with restricted tools
- execute_gptme() now accepts 'tools' parameter for --tools flag
- CLI: 'gptme-runloops team' command

Refs: ErikBjare/bob#300

* fix(gptodo): use --active-only flag instead of --state

The gptodo CLI uses --active-only flag, not --state parameter.
This fixes the 'No such option: --state' error when calling list_tasks().

Co-authored-by: Bob <bob@superuserlabs.org>

* fix(execution): prevent command injection with shlex escaping

Use shlex.join() and shlex.quote() to properly escape command arguments
when constructing shell commands. This prevents potential command injection
if the tools parameter contains shell metacharacters.

Addresses Greptile security review feedback on PR gptme#252.
…i-pattern (gptme#251)

* docs(lesson): enhance read-full-github-context with stale context anti-pattern

Per Erik's request in ErikBjare/bob#290, added specific detection and
prevention for the 'responding to old comments' error mode:

- Added keywords: responding to old comments, not reading whole thread, replying to stale context
- Enhanced rule: read ENTIRE thread chronologically before responding
- Added detection signals for stale context responses
- New section: Anti-Pattern: Responding to Stale Context with concrete example
- New section: Correct Reading Protocol with mental checklist
- Enhanced outcome section
- Added related link to Memory Failure Prevention

* refactor(lesson): simplify and add truncation-focused keywords per review

- Add keywords for truncation patterns (--comments | head/tail)
- Move verbose anti-pattern example to companion doc reference
- Focus on what to do and why (per Erik's guidance)
- Reduce from 108 to 61 lines (44% reduction)

Addresses Erik's feedback:
- Keywords now trigger on common truncation patterns
- Removed extensive explanation (belongs in companion doc)
- Kept actionable content: rule, detection, pattern, outcome

* fix(lesson): remove broken companion doc link

The companion doc reference pointed to a path outside the gptme-contrib
repo (../../../knowledge/...) which doesn't exist. Removed the reference
since gptme-contrib doesn't use companion docs.

* refactor(lesson): simplify keywords based on inclusion statistics

Analysis from Bob's workspace (24h window):
- 'Read Full GitHub Context': 11 auto-inclusions (~2.2% trigger rate)
- 'Read PR Reviews Comprehensively': 49 inclusions (~10% trigger rate)

Root cause: Keywords like 'truncating comments output' and
'not reading the whole issue' rarely appear verbatim in prompts.

New keywords are simpler and higher-frequency:
- Command patterns: 'gh issue view', 'gh pr view', '--comments'
- Truncation triggers: '| head', '| tail'
- Context term: 'issue thread'

This matches the successful pattern from 'Read PR Reviews' lesson
which uses simple terms like 'pull request', 'pr review', 'gh api'.

* fix(lesson): restore PR review API commands per Greptile feedback

Addresses review comment that the lesson was dropping required review
context. The gh pr view --comments does NOT include review summaries
or inline file/line comments, so we need the gh api calls for complete
PR context.

* fix: use consistent <pr-number> placeholder in API commands

Addresses Greptile review comment about inconsistent placeholder naming.
The gh api commands now use <pr-number> to match the context of the
gh pr view commands that use <pr-url>.
The gptodo plugin registers functions (delegate, list_tasks, etc.) in the
ipython tool. Without ipython in COORDINATOR_TOOLS, these functions cannot
be called, causing the team run to fail.

Fixes issue ErikBjare/bob#300
- Add Git LFS post-checkout call to existing branch validation hook
- Add Git LFS pre-push call to existing push protection hook
- Create post-commit hook with Git LFS support
- Create post-merge hook with Git LFS support

Git LFS hooks are now included in the global hooks, enabling
automatic LFS file handling across all repos without requiring
'git lfs install' to be run per-repo.
- Move Git LFS post-checkout call before exit 0 (was unreachable)
- Pipe STDIN_CONTENT to Git LFS pre-push (stdin was already consumed)

Fixes issues identified by @greptile-apps[bot] in PR review.
Git LFS commands can fail in environments without:
- Git LFS installed
- Valid credentials
- LFS-enabled remotes
- Actual LFS files

These failures should not block the git operations. Make all LFS
hook calls non-blocking with '|| true' and suppress stderr.

This fixes integration test failures where test repos don't have
LFS configured.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants