{"id":39331820,"url":"https://github.com/jonmagic/scripts","last_synced_at":"2026-01-18T02:02:59.706Z","repository":{"id":294328325,"uuid":"985441925","full_name":"jonmagic/scripts","owner":"jonmagic","description":"I organize my life with markdown and these scripts help me work quickly and seamlessly.","archived":false,"fork":false,"pushed_at":"2025-11-08T23:54:52.000Z","size":412,"stargazers_count":8,"open_issues_count":8,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-09T01:14:37.233Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jonmagic.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-05-17T19:12:49.000Z","updated_at":"2025-11-08T23:54:47.000Z","dependencies_parsed_at":"2025-06-30T01:24:11.210Z","dependency_job_id":"7fa638ec-9de3-488f-9a80-3adc5bd93ed9","html_url":"https://github.com/jonmagic/scripts","commit_stats":null,"previous_names":["jonmagic/scripts"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jonmagic/scripts","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonmagic%2Fscripts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonmagic%2Fscripts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonmagic%2Fscripts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonmagic%2Fscripts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jonmagic","download_url":"https://codeload.github.com/jonmagic/scripts/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonmagic%2Fscripts/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28526560,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-18T00:39:45.795Z","status":"online","status_checked_at":"2026-01-18T02:00:07.578Z","response_time":98,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-18T02:02:59.625Z","updated_at":"2026-01-18T02:02:59.671Z","avatar_url":"https://github.com/jonmagic.png","language":"Ruby","readme":"# scripts\n\nI organize my life with markdown and these scripts help me work quickly and seamlessly.\n\nOne weekly note sets the plan, and conversations, captured as transcripts, are archived, summarized with AI, and linked to long-running notes by person or group. These scripts reduce friction at every step: from capturing insights to surfacing them when needed.\n\nI organize my notes to map to my processes:\n\n```\nNotes/\n├── Weekly Notes/  # One file per week, e.g. \"Week of 2024-05-19.md\"\n├── Meeting Notes/  # One file per person or group, contents by date descending\n├── Transcripts/YYYY-MM-DD/  # Raw transcripts, incrementally numbered\n├── Executive Summaries/YYYY-MM-DD/  # LLM summaries for each transcript\n├── ...\n```\n\nThis structure supports a semantically searchable, AI-augmented note system, fast to navigate, easy to sync, and version-control friendly.\n\n## Setup\n\nBefore using the scripts in this repo, run the bootstrap script to ensure required dependencies (like Homebrew, fzf, and llm) are installed:\n\n```sh\nbin/bootstrap\n```\n\n## Instructions\n\nThis repo uses the terms **porcelain** and **plumbing** to describe its scripts, similar to how git distinguishes between user-facing and lower-level commands:\n\n- **Porcelain**: User-friendly scripts intended for direct use.\n  - [Archive Meeting](#archive-meeting)\n  - [Create Weekly Note](#create-weekly-note)\n  - [Extract Topics](#extract-topics)\n  - [Fetch GitHub Conversation](#fetch-github-conversation)\n  - [Fetch GitHub Conversations](#fetch-github-conversations)\n  - [GitHub Conversations Research Agent](#github-conversations-research-agent)\n  - [Index Summary](#index-summary)\n  - [Index Summaries](#index-summaries)\n  - [Summarize GitHub Conversation](#summarize-github-conversation)\n  - [Prepare Commit](#prepare-commit)\n  - [Prepare Pull Request](#prepare-pull-request)\n- **Plumbing**: Lower-level scripts intended to be used by other scripts or for advanced workflows.\n  - [Search GitHub Conversations](#search-github-conversations)\n  - [Select Folder](#select-folder)\n  - [Vector Upsert](#vector-upsert)\n  - [Semantic Search GitHub Conversations](#semantic-search-github-conversations)\n\n### Aliases\n\nThe raw scripts are useful but require a lot of typing so I recommend adding aliases to your shell configuration to make things easier. For example, here are my aliases (which can be added to your `.bashrc` or `.zshrc`):\n\n```sh\nalias cwn='/path/to/create-weekly-note --template-path /path/to/Templates/Week\\ of\\ \\{\\{date\\}\\}.md --target-dir /path/to/Weekly\\ Notes/'\nalias am='/path/to/archive-meeting --transcripts-dir ~/Documents/Zoom/ --target-dir /path/to --executive-summary-prompt-path /path/to/zoom-transcript-executive-summary.md --detailed-notes-prompt-path /path/to/transcript-meeting-notes.md'\nalias commit='/path/to/prepare-commit --commit-message-prompt-path /path/to/commit-message.md'\nalias fgc='/path/to/fetch-github-conversation'\nalias et='/path/to/extract-topics --topics-prompt-path /path/to/topic-extraction.txt'\nalias es='llm -f /path/to/github-conversation-executive-summary.md'\nalias idx='/path/to/index-summary --executive-summary-prompt-path /path/to/github-conversation-executive-summary.md --topics-prompt-path /path/to/topic-extraction.txt --collection github-conversations --skip-if-up-to-date'\nalias bidx='/path/to/index-summaries --executive-summary-prompt-path /path/to/github-conversation-executive-summary.md --topics-prompt-path /path/to/topic-extraction.txt --collection github-conversations --cache-path ./cache --skip-if-up-to-date'\nalias ppr='/path/to/prepare-pull-request --base-branch main --pr-body-prompt-path /path/to/pull-request-body.md'\nalias research='/path/to/github-conversations-research-agent --collection github-conversations --fast-model gpt-4.1 --reasoning-model o3 --verbose'\n```\n\nAll of the referenced prompts can be found here: https://github.com/jonmagic/prompts\n\n## Porcelain Commands\n\n### Archive Meeting\n\nThis script helps you archive a meeting by combining transcripts and chat logs, generating an executive summary, generating detailed meeting notes (as if you took notes in the meeting), and updating notes. It guides you through selecting the folder with the transcript(s), processes the files, and updates your markdown notes with wikilinks to the transcript, summary, and detailed notes.\n\n**Usage:**\n\n```sh\n/path/to/archive-meeting \\\n  --transcripts-dir /path/to/Zoom/ \\\n  --target-dir /path/to/Notes/ \\\n  --executive-summary-prompt-path /path/to/meeting-summary.txt \\\n  --detailed-notes-prompt-path /path/to/meeting-detailed-notes.txt\n```\n\n### Create Weekly Note\n\nThis script helps you quickly create a new weekly note from a template and place it in your notes directory.\n\n**Usage:**\n\n```sh\n/path/to/create-weekly-note --template-path /path/to/weekly/notes/template.md --target-dir /path/to/weekly/notes\n```\n\n### Fetch GitHub Conversation\n\nFetch and export GitHub issue, pull request, or discussion data as structured JSON. This script retrieves all relevant data from a GitHub issue, pull request, or discussion using the GitHub CLI (`gh`). It outputs a single JSON object containing the main conversation and all comments, suitable for archiving or further processing. Supports caching to avoid redundant API calls.\n\n**Usage:**\n\n```sh\n/path/to/fetch-github-conversation \u003cgithub_conversation_url\u003e \\\n  [--cache-path \u003ccache_root\u003e] [--updated-at \u003ciso8601\u003e]\n```\n\n- `\u003cgithub_conversation_url\u003e`: A GitHub issue, pull request, or discussion URL (e.g. `https://github.com/octocat/Hello-World/issues/42`)\n- `owner/repo/type/number`: Alternative input form (e.g. `octocat/Hello-World/issues/42`)\n- `--cache-path \u003ccache_root\u003e`: (Optional) Root directory for caching. Data is stored as `conversations/\u003cowner\u003e/\u003crepo\u003e/\u003ctype\u003e/\u003cnumber\u003e.json` under this path.\n- `--updated-at \u003ctimestamp\u003e`: (Optional) Only fetch if the remote conversation is newer than this ISO8601 timestamp (or the cached data).\n\n**Examples:**\n\nFetch and print a GitHub issue:\n\n```sh\n/path/to/fetch-github-conversation https://github.com/octocat/Hello-World/issues/42\n```\n\nFetch and cache a pull request, only if updated:\n\n```sh\n/path/to/fetch-github-conversation octocat/Hello-World/pull/123 --cache-path ./cache --updated-at 2024-05-01T00:00:00Z\n```\n\nThe script will abort with an error message if the input is not recognized or if any command fails.\n\n### Fetch GitHub Conversations\n\nFetch and export GitHub issue, pull request, or discussion data for multiple URLs at once. This script uses `fetch-github-conversation` under the hood to process multiple GitHub conversations, accepting URLs either from stdin (piped) or from a file. It supports both plain text URLs and JSON input from `search-github-conversations`, automatically using updated_at timestamps for efficient caching. It passes through all CLI options to the underlying script and streams JSON output to stdout.\n\n**Usage:**\n\n```sh\n/path/to/fetch-github-conversations [options] \u003cfile_path\u003e\n# or\ncommand | /path/to/fetch-github-conversations [options]\n```\n\n- `\u003cfile_path\u003e`: Path to file containing GitHub URLs (plain text, one per line) or JSON data\n- Options are passed through to `fetch-github-conversation`:\n  - `--cache-path \u003ccache_root\u003e`: (Optional) Root directory for caching\n  - `--updated-at \u003ctimestamp\u003e`: (Optional) Only fetch if newer than this ISO8601 timestamp\n\n**Input Formats:**\n\n1. **Plain text URLs**: One URL per line (existing format)\n2. **JSON from search-github-conversations**: Array of objects with `url` and `updated_at` fields\n\n**Examples:**\n\nFetch multiple conversations from a plain text file:\n\n```sh\n/path/to/fetch-github-conversations urls.txt\n```\n\nFetch from stdin with plain text URLs:\n\n```sh\necho \"https://github.com/octocat/Hello-World/issues/42\" | /path/to/fetch-github-conversations --cache-path ./cache\n```\n\n**Pipeline with search-github-conversations** (recommended workflow):\n\n```sh\n# Search for conversations and fetch them with automatic timestamp optimization\n/path/to/search-github-conversations 'repo:octocat/Hello-World created:\u003e2025' | \\\n  /path/to/fetch-github-conversations --cache-path ./cache\n```\n\n**Complete workflow example** (search → fetch → summarize → index):\n\n```sh\n# Step 1: Search for recent conversations\n/path/to/search-github-conversations 'repo:octocat/Hello-World created:\u003e2025' \u003e recent_conversations.json\n\n# Step 2: Fetch full conversation data with caching\ncat recent_conversations.json | /path/to/fetch-github-conversations --cache-path ./cache\n\n# Step 3: Extract URLs and generate summaries\ncat recent_conversations.json | jq -r '.[].url' | while read url; do\n  /path/to/summarize-github-conversation \"$url\" \\\n    --executive-summary-prompt-path /path/to/summary-prompt.txt \\\n    --cache-path ./cache\ndone\n\n# Step 4: Index summaries for semantic search\ncat recent_conversations.json | jq -r '.[].url' | while read url; do\n  /path/to/index-summary \"$url\" \\\n    --executive-summary-prompt-path /path/to/summary-prompt.txt \\\n    --topics-prompt-path /path/to/topics-prompt.txt \\\n    --collection github-conversations \\\n    --cache-path ./cache \\\n    --skip-if-up-to-date\ndone\n```\n\nFetch multiple conversations with global timestamp check:\n\n```sh\n/path/to/fetch-github-conversations --cache-path ./cache --updated-at 2024-05-01T00:00:00Z urls.txt\n```\n\n**Key Benefits of JSON Input:**\n\nWhen using JSON input from `search-github-conversations`, each conversation is fetched with its individual `updated_at` timestamp, providing optimal caching efficiency. This means conversations that haven't been updated since the last fetch will be served from cache, while only recently updated conversations will make new API calls.\n\nThe script continues processing even if individual URLs fail and outputs error messages to stderr for any failures.\n\n### GitHub Conversations Research Agent\n\nAI workflow that answers a question by semantically searching your GitHub conversations. It generates clarifying questions in your editor, repeats research up to a set depth, and outputs a final Markdown report citing all sources. This script implements a multi-turn research agent that combines semantic search, LLM-powered analysis, and interactive clarification to provide comprehensive answers about GitHub conversations.\n\n**Usage:**\n\n```sh\n/path/to/github-conversations-research-agent \"QUESTION\" --collection COLLECTION [options]\n```\n\n- `\"QUESTION\"`: **(Required)** The research question you want answered (positional argument)\n- `--collection COLLECTION`: **(Required)** Qdrant collection name containing indexed GitHub conversations\n- `--limit N`: Max results per search (default: 5)\n- `--max-depth N`: Max deep-research passes (default: 2)\n- `--editor-file PATH`: Use fixed file instead of Tempfile for clarifying questions\n- `--clarifying-qa PATH`: Path to file with clarifying Q\u0026A to bypass interactive step\n- `--search-modes MODE1,MODE2`: Search modes to use: semantic, keyword (default: semantic,keyword)\n- `--cache-path PATH`: Root path for caching fetched data\n- `--verbose`: Show debug logs and progress information\n- `--fast-model MODEL`: Fast LLM model for light reasoning tasks like generating clarifying questions and search queries (default: ENV['FAST_LLM_MODEL'] or llm default)\n- `--reasoning-model MODEL`: Reasoning LLM model for complex analysis like final report generation (default: ENV['LLM_MODEL'] or llm default)\n- `--parallel`: Use parallel processing for better performance (default: false)\n\n**Prerequisites:**\n\n- `llm` CLI installed and configured\n- Qdrant server running with indexed GitHub conversation summaries\n- `EDITOR` environment variable set (e.g., `export EDITOR=nano`)\n- `bin/semantic-search-github-conversations`, `bin/search-github-conversations`, and `bin/fetch-github-conversation` available\n\n**Search Modes:**\n\n- **semantic**: Uses semantic search with vector similarity against indexed conversation summaries\n- **keyword**: Uses keyword search via GitHub's search API through `bin/search-github-conversations`\n- **Combined modes**: When both are specified (default), the agent uses both search strategies and combines results\n\n**Workflow:**\n\n1. **Initial Research**: Performs search against your collection using configured search modes to find relevant conversations\n2. **Clarifying Questions**: Generates up to 4 clarifying questions and opens them in your editor\n3. **Deep Research**: Based on your answers, performs iterative searches up to `--max-depth` times\n4. **Final Report**: Generates a comprehensive Markdown report citing all GitHub conversations used\n\n**Examples:**\n\nBasic research with verbose output:\n\n```sh\n/path/to/github-conversations-research-agent \"Why did issue #456 go stale?\" --collection github-conversations --verbose\n```\n\nFocused research with custom parameters:\n\n```sh\n/path/to/github-conversations-research-agent \"What are the main challenges with our CI/CD pipeline?\" --collection github-conversations --limit 5 --max-depth 2\n```\n\nResearch using a fixed editor file:\n\n```sh\n/path/to/github-conversations-research-agent \"How do we handle authentication in the API?\" --collection github-conversations --editor-file /tmp/research-questions.md\n```\n\nResearch with pre-written clarifying questions (bypassing interactive step):\n\n```sh\n/path/to/github-conversations-research-agent \"What are the security implications of the new API?\" --collection github-conversations --clarifying-qa /path/to/research-clarifications.md\n```\n\nDual-model research with gpt-4.1 for fast reasoning and o3 for complex analysis:\n\n```sh\n/path/to/github-conversations-research-agent \"What are the main challenges with our CI/CD pipeline?\" --collection github-conversations --fast-model gpt-4.1 --reasoning-model o3\n```\n\nUse only semantic search:\n\n```sh\n/path/to/github-conversations-research-agent \"authentication issues\" --collection github-conversations --search-modes semantic\n```\n\nUse only keyword search:\n\n```sh\n/path/to/github-conversations-research-agent \"repo:owner/repo is:issue label:bug\" --collection github-conversations --search-modes keyword\n```\n\nResearch with caching enabled:\n\n```sh\n/path/to/github-conversations-research-agent \"database performance optimization\" --collection github-conversations --cache-path ./data\n```\n\n**Sample Output:**\n\nThe script produces a structured Markdown report like:\n\n```markdown\n# Executive Summary\n\nBased on the analysis of 12 GitHub conversations, issue #456 went stale due to...\n\n# Key Findings\n\n- Primary blocker: Missing consensus on implementation approach\n- Contributing factors: Resource allocation conflicts, unclear requirements\n- Related issues: #234, #567 experienced similar patterns\n\n# Detailed Analysis\n\n## Implementation Challenges\n...\n\n# Sources\n\n- https://github.com/owner/repo/issues/456\n- https://github.com/owner/repo/pull/789\n- https://github.com/owner/repo/discussions/234\n```\n\n**Logging:**\n\nThe script uses structured logging with two levels:\n\n- **Default (INFO level)**: Shows high-level progress and milestones. Typically ≤20 lines for a 2-iteration query.\n- **Verbose mode (`--verbose`)**: Enables DEBUG level logging with detailed search results, conversation metadata, and command execution details. Expect ≥100 lines of output.\n\nThe search operations are performed by `bin/semantic-search-github-conversations` and `bin/search-github-conversations` rather than direct API calls, ensuring consistency with other tools in this repository.\n\n### Summarize GitHub Conversation\n\nGenerate an executive summary of a GitHub issue, pull request, or discussion using the `llm` CLI and a required prompt file. This script fetches or loads a cached conversation (using `fetch-github-conversation`), extracts the text content, and uses the `llm` CLI to generate a summary using the provided prompt file. Optionally, it saves the summary as a JSON file in the cache.\n\n**Usage:**\n\n```sh\n/path/to/summarize-github-conversation \u003cgithub_conversation_url\u003e --executive-summary-prompt-path \u003cprompt_path\u003e [--cache-path \u003ccache_root\u003e] [--updated-at \u003ciso8601\u003e]\n```\n\n- `\u003cgithub_conversation_url\u003e`: A GitHub issue, pull request, or discussion URL (e.g. `https://github.com/octocat/Hello-World/issues/42`)\n- `owner/repo/type/number`: Alternative input form (e.g. `octocat/Hello-World/issues/42`)\n- `--executive-summary-prompt-path \u003cprompt_path\u003e`: **(Required)** Path to the prompt file to use for the executive summary. The prompt file should contain instructions for the LLM; the conversation text will be appended as input.\n- `--cache-path \u003ccache_root\u003e`: (Optional) Root directory for caching. Summary is stored as `summaries/\u003cowner\u003e/\u003crepo\u003e/\u003ctype\u003e/\u003cnumber\u003e.json` under this path.\n- `--updated-at \u003ctimestamp\u003e`: (Optional) Only fetch if the remote conversation is newer than this ISO8601 timestamp (or the cached data).\n\n**Examples:**\n\nSummarize a GitHub issue:\n\n```sh\n/path/to/summarize-github-conversation https://github.com/octocat/Hello-World/issues/42 --executive-summary-prompt-path /path/to/github-summary.txt\n```\n\nSummarize and cache a pull request, only if updated:\n\n```sh\n/path/to/summarize-github-conversation octocat/Hello-World/pull/123 --executive-summary-prompt-path /path/to/github-summary.txt --cache-path ./cache --updated-at 2024-05-01T00:00:00Z\n```\n\nThe script will abort with an error message if the input is not recognized, if the prompt path is not provided, or if any command fails.\n\n### Extract Topics\n\nExtract key thematic topics or labels from a GitHub conversation using the `llm` CLI and a prompt file. This script fetches or loads a cached GitHub conversation (using `fetch-github-conversation`), extracts the text content, and uses the `llm` CLI to identify and extract thematic topics using the provided prompt file. Topics are returned as a JSON array of strings. Optionally, it saves the topics as a JSON file in the cache and can limit the number of topics extracted.\n\n**Usage:**\n\n```sh\n/path/to/extract-topics \u003cgithub_conversation_url\u003e --topics-prompt-path \u003cprompt_path\u003e [--cache-path \u003ccache_root\u003e] [--updated-at \u003ciso8601\u003e] [--max-topics \u003cnumber\u003e]\n```\n\n- `\u003cgithub_conversation_url\u003e`: A GitHub issue, pull request, or discussion URL (e.g. `https://github.com/octocat/Hello-World/issues/42`)\n- `owner/repo/type/number`: Alternative input form (e.g. `octocat/Hello-World/issues/42`)\n- `--topics-prompt-path \u003cprompt_path\u003e`: **(Required)** Path to the prompt file to use for topic extraction. The prompt file should contain instructions for the LLM; the conversation text will be appended as input.\n- `--cache-path \u003ccache_root\u003e`: (Optional) Root directory for caching. Topics are stored as `topics/\u003cowner\u003e/\u003crepo\u003e/\u003ctype\u003e/\u003cnumber\u003e.json` under this path.\n- `--updated-at \u003ctimestamp\u003e`: (Optional) Only fetch if the remote conversation is newer than this ISO8601 timestamp (or the cached data).\n- `--max-topics \u003cnumber\u003e`: (Optional) Maximum number of topics to extract from the conversation.\n\n**Output Format:**\n\nThe script outputs a JSON array of strings to STDOUT, for example:\n```json\n[\"performance\", \"authentication\", \"database\", \"caching\", \"bug-fix\"]\n```\n\n**Examples:**\n\nExtract topics from a GitHub issue:\n\n```sh\n/path/to/extract-topics https://github.com/octocat/Hello-World/issues/42 --topics-prompt-path /path/to/topic-extraction.txt\n```\n\nExtract and cache topics from a pull request, limiting to 5 topics:\n\n```sh\n/path/to/extract-topics octocat/Hello-World/pull/123 --topics-prompt-path /path/to/topic-extraction.txt --cache-path ./cache --max-topics 5\n```\n\nThe script will abort with an error message if the input is not recognized, if the prompt path is not provided, or if any command fails.\n\n### Index Summary\n\nIndex a GitHub conversation summary in a vector database (Qdrant) for semantic search. This script orchestrates the complete pipeline: fetching conversation data, generating a summary, extracting topics, building metadata, and storing the summary as a vector embedding in Qdrant. It combines the functionality of `fetch-github-conversation`, `summarize-github-conversation`, `extract-topics`, and `vector-upsert` into a single workflow.\n\n**Usage:**\n\n```sh\n/path/to/index-summary \u003cgithub_conversation_url\u003e \\\n  --executive-summary-prompt-path \u003csummary_prompt_path\u003e \\\n  --topics-prompt-path \u003ctopics_prompt_path\u003e \\\n  --collection \u003ccollection_name\u003e \\\n  [options]\n```\n\n- `\u003cgithub_conversation_url\u003e`: A GitHub issue, pull request, or discussion URL (e.g. `https://github.com/octocat/Hello-World/issues/42`)\n- `--executive-summary-prompt-path \u003cpath\u003e`: **(Required)** Path to the prompt file for generating executive summaries\n- `--topics-prompt-path \u003cpath\u003e`: **(Required)** Path to the prompt file for extracting topics\n- `--collection \u003cname\u003e`: **(Required)** Qdrant collection name where the vector will be stored\n- `--cache-path \u003cpath\u003e`: (Optional) Root directory for caching conversation data and processing results\n- `--updated-at \u003ctimestamp\u003e`: (Optional) Only process if the remote conversation is newer than this ISO8601 timestamp\n- `--model \u003cmodel\u003e`: (Optional) Embedding model to use for vector generation\n- `--qdrant-url \u003curl\u003e`: (Optional) Qdrant server URL (default: http://localhost:6333)\n- `--max-topics \u003cnumber\u003e`: (Optional) Maximum number of topics to extract\n- `--skip-if-up-to-date`: (Optional) Skip indexing if vector exists and is up-to-date based on updated_at timestamp\n\n**Metadata Fields:**\n\nThe script creates a flat JSON metadata payload that includes:\n- `url`, `owner`, `repo`, `type`, `number`, `title`, `author`, `state`\n- `created_at`, `updated_at`, `closed_at` (if applicable), `indexed_at`\n- `topics` (comma-separated list)\n- Type-specific fields:\n  - Issues: `labels`, `milestone`\n  - Pull Requests: `merged`, `merged_at`, `base_branch`, `head_branch`\n  - Discussions: `category`, `answered`\n\n**Examples:**\n\nIndex a GitHub issue summary:\n\n```sh\n/path/to/index-summary https://github.com/octocat/Hello-World/issues/42 \\\n  --executive-summary-prompt-path /path/to/summary-prompt.txt \\\n  --topics-prompt-path /path/to/topics-prompt.txt \\\n  --collection github-conversations\n```\n\nIndex with caching, custom model, and timestamp optimization:\n\n```sh\n/path/to/index-summary octocat/Hello-World/pull/123 \\\n  --executive-summary-prompt-path /path/to/summary-prompt.txt \\\n  --topics-prompt-path /path/to/topics-prompt.txt \\\n  --collection github-conversations \\\n  --cache-path ./cache \\\n  --model text-embedding-3-small \\\n  --skip-if-up-to-date\n```\n\n**Requirements:**\n- A running Qdrant server (default: localhost:6333)\n- Valid LLM API credentials configured with the `llm` CLI\n- All prompt files must exist and be readable\n\n### Index Summaries\n\nBulk index multiple GitHub conversations into Qdrant for semantic search. This script orchestrates bulk indexing by running `index-summary` on each URL from either a file or stdin. It supports both plain text URLs and JSON input with updated_at timestamps for efficient caching.\n\n**Usage:**\n\n```sh\n./path/to/index-summaries [options] \u003cfile_path\u003e\n# or\ncommand | ./path/to/index-summaries [options]\n```\n\n- `\u003cfile_path\u003e`: Path to file containing GitHub URLs (plain text, one per line) or JSON data\n- All options are passed through to `index-summary`\n\n**Required Options:**\n\n- `--executive-summary-prompt-path \u003cpath\u003e`: Path to the prompt file for generating executive summaries\n- `--topics-prompt-path \u003cpath\u003e`: Path to the prompt file for extracting topics\n- `--collection \u003cname\u003e`: Qdrant collection name where vectors will be stored\n\n**Optional Options:**\n\n- `--cache-path \u003cpath\u003e`: Root directory for caching conversation data and processing results\n- `--updated-at \u003ctimestamp\u003e`: Only process if remote conversation is newer (overrides JSON timestamps)\n- `--model \u003cmodel\u003e`: Embedding model to use for vector generation\n- `--qdrant-url \u003curl\u003e`: Qdrant server URL (default: http://localhost:6333)\n- `--max-topics \u003cnumber\u003e`: Maximum number of topics to extract\n- `--skip-if-up-to-date`: Skip indexing if vector exists and is up-to-date\n\n**Input Formats:**\n\n1. **Plain text URLs**: One URL per line\n2. **JSON from search-github-conversations**: Array of objects with `url` and `updated_at` fields\n\n**Examples:**\n\nBulk index from a plain text file:\n\n```sh\n./path/to/index-summaries \\\n  --executive-summary-prompt-path ./prompts/executive-summary.txt \\\n  --topics-prompt-path ./prompts/topics.txt \\\n  --collection github-conversations \\\n  urls.txt\n```\n\nBulk index from search results with automatic timestamp optimization:\n\n```sh\n./path/to/search-github-conversations 'repo:octocat/Hello-World created:\u003e2025' | \\\n  ./path/to/index-summaries \\\n    --executive-summary-prompt-path ./prompts/summary.txt \\\n    --topics-prompt-path ./prompts/topics.txt \\\n    --collection github-conversations \\\n    --cache-path ./cache \\\n    --skip-if-up-to-date\n```\n\n**Complete workflow example** (search → bulk index):\n\n```sh\n# Step 1: Search for recent conversations and bulk index them\n./path/to/search-github-conversations 'repo:octocat/Hello-World created:\u003e2025' | \\\n  ./path/to/index-summaries \\\n    --executive-summary-prompt-path /path/to/summary-prompt.txt \\\n    --topics-prompt-path /path/to/topics-prompt.txt \\\n    --collection github-conversations \\\n    --cache-path ./cache \\\n    --skip-if-up-to-date\n```\n\n**Key Benefits:**\n\n- **Bulk processing**: Process multiple conversations in a single command\n- **Automatic timestamp optimization**: When using JSON input, each conversation uses its individual `updated_at` timestamp for optimal caching\n- **Error resilience**: Continues processing even if individual URLs fail, with errors logged to stderr\n- **JSON output**: Streams JSON objects to stdout for successful indexing operations\n- **Pipeline-friendly**: Designed to work seamlessly with `search-github-conversations`\n\n**Output Format:**\n\nFor each successfully indexed conversation, outputs a JSON object:\n\n```json\n{\"url\":\"https://github.com/owner/repo/issues/42\",\"status\":\"indexed\"}\n```\n\nThe script continues processing even if individual URLs fail and outputs error messages to stderr for any failures.\n\n### Prepare Commit\n\nThis script helps you generate a semantic commit message for your staged changes using an LLM. It copies the staged diff to your clipboard, prompts you for commit type and optional scope, and generates a commit message using the provided prompt template. You can review and regenerate the message as needed before committing. The final commit message is copied to your clipboard and pre-filled in the git commit editor.\n\n\u003e [!NOTE]\n\u003e If a file named `commit-message-guidelines.txt` exists in the directory where you run `prepare-commit`, its contents will be included in the LLM context (after the prompt template and before the commit type/scope header). This allows you to provide project specific commit message guidelines that will help the LLM generate better commit messages.\n\n**Usage:**\n\n```sh\n/path/to/prepare-commit \\\n  --commit-message-prompt-path /path/to/commit-prompt.txt \\\n  [--llm-model MODEL]\n```\n\n### Prepare Pull Request\n\nThis script helps you generate a pull request title and body based on commits between your current branch and the base branch. It uses an LLM to analyze your commit messages and diffs to generate a meaningful PR description. You can review and edit both the title and body before creating the PR using the GitHub CLI. If you choose not to create the PR immediately, the title and body are copied to your clipboard for later use.\n\n**Usage:**\n\n```sh\n/path/to/prepare-pull-request \\\n  --base-branch main \\\n  --pr-body-prompt-path /path/to/pr-prompt.txt \\\n  [--llm-model MODEL]\n```\n\n- `--base-branch`: The name of the base branch to compare against (e.g., main, master, develop)\n- `--pr-body-prompt-path`: Path to the prompt file for generating the PR body\n- `--llm-model`: (Optional) Specify a specific LLM model to use\n\n## Plumbing Commands\n\n### Search GitHub Conversations\n\nSearch GitHub conversations (issues, pull requests, discussions) using a GitHub search query string and the GraphQL API. This script aggregates search results and returns minimal metadata for each conversation, making it ideal for use in pipelines with other tools like `fetch-github-conversation`.\n\n**Usage:**\n\n```sh\n/path/to/search-github-conversations '\u003csearch_query\u003e'\n```\n\n- `\u003csearch_query\u003e`: A GitHub search query string using standard GitHub search syntax\n\n**Key Features:**\n\n- **Automatic type detection**: Inspects query for `is:issue`, `is:pr`, `is:discussion` modifiers to determine what to search\n- **Fallback search**: If no type specified, searches both issues/PRs and discussions automatically\n- **Pagination**: Handles pagination up to 1000 items per conversation type\n- **Consistent output**: Returns JSON array with `updated_at` and `url` for each result\n- **Sorted results**: Results are sorted by `updated_at` in descending order (most recent first)\n\n**Examples:**\n\nSearch for pull requests only:\n\n```sh\n/path/to/search-github-conversations 'repo:octocat/Hello-World is:pr created:\u003e2025'\n```\n\nSearch for all conversation types in a specific date range:\n\n```sh\n/path/to/search-github-conversations 'repo:octocat/Hello-World created:2025-01-01..2025-06-30'\n```\n\nSearch for discussions only:\n\n```sh\n/path/to/search-github-conversations 'repo:octocat/Hello-World is:discussion'\n```\n\nSearch across multiple repositories:\n\n```sh\n/path/to/search-github-conversations 'org:octocat is:issue state:open created:\u003e2025'\n```\n\nSearch with specific labels or keywords:\n\n```sh\n/path/to/search-github-conversations 'repo:octocat/Hello-World is:issue label:bug,enhancement in:title,body performance'\n```\n\n**Example Output:**\n\n```json\n[\n  {\n    \"updated_at\": \"2025-06-20T09:42:11Z\",\n    \"url\": \"https://github.com/octocat/Hello-World/issues/123\"\n  },\n  {\n    \"updated_at\": \"2025-06-18T14:23:05Z\",\n    \"url\": \"https://github.com/octocat/Hello-World/pull/456\"\n  },\n  {\n    \"updated_at\": \"2025-06-15T10:00:00Z\",\n    \"url\": \"https://github.com/octocat/Hello-World/discussions/789\"\n  }\n]\n```\n\n**Requirements:**\n- The `gh` CLI must be installed and authenticated\n- Valid GitHub search query syntax\n\n**Error Handling:**\n- Aborts with clear error message for invalid queries\n- Aborts if `gh` CLI is not authenticated\n- Handles GraphQL API errors and rate limits\n\n### Select Folder\n\nThis script takes a target directory as an argument and returns the 10 names of the most recently updated folders in that directory. It then lets you select a folder using arrow keys or fuzzy search (via `fzf`) and returns the full path of the selected folder.\n\n**Usage:**\n\n```sh\n/path/to/select-folder --target-dir /path/to/target\n```\n\n### Vector Upsert\n\nGeneric tool for embedding arbitrary text and upserting vectors with metadata into Qdrant collections. This is a low-level plumbing script that handles the embedding generation and Qdrant integration, designed to be used by higher-level orchestration scripts like `index-summary` or in custom workflows.\n\n**Usage:**\n\n```sh\necho \"text to embed\" | /path/to/vector-upsert \\\n  --collection \u003ccollection_name\u003e \\\n  --metadata '\u003cflat_json_object\u003e' \\\n  [options]\n```\n\n- `--collection \u003cname\u003e`: **(Required)** Qdrant collection name where the vector will be stored\n- `--metadata \u003cjson\u003e`: **(Required)** Flat JSON metadata object with optional arrays of primitive values (no nested objects)\n- `--vector-id-key \u003ckey\u003e`: (Optional) Key in metadata that contains the main text for ID generation (default: use stdin content)\n- `--model \u003cmodel\u003e`: (Optional) Embedding model to use (default: text-embedding-3-small)\n- `--qdrant-url \u003curl\u003e`: (Optional) Qdrant server URL (default: http://localhost:6333)\n- `--skip-if-up-to-date \u003ctimestamp_key\u003e`: (Optional) Skip upserting if vector exists and timestamp in specified metadata key is up-to-date\n\n**Key Features:**\n\n- **Flat JSON validation**: Metadata must be a flat JSON object with optional arrays of primitive values (strings, numbers, booleans, null); the script will abort if nested objects or arrays containing nested structures are detected\n- **Stable vector IDs**: Generates deterministic SHA-256 hashes for consistent vector identification\n- **Auto-collection creation**: Creates Qdrant collections automatically if they don't exist\n- **Error handling**: Clear error messages for embedding failures, Qdrant connectivity issues, and validation errors\n\n**Examples:**\n\nEmbed a simple text with metadata:\n\n```sh\necho \"This is a summary of a GitHub issue\" | /path/to/vector-upsert \\\n  --collection github-issues \\\n  --metadata '{\"url\": \"https://github.com/owner/repo/issues/123\", \"title\": \"Bug report\", \"author\": \"username\"}'\n```\n\nEmbed with array metadata (topics, labels, etc.):\n\n```sh\necho \"Summary of feature discussion\" | /path/to/vector-upsert \\\n  --collection github-conversations \\\n  --metadata '{\"url\": \"https://github.com/owner/repo/issues/456\", \"topics\": [\"performance\", \"caching\", \"database\"], \"labels\": [\"enhancement\", \"priority-high\"]}'\n```\n\nUse a specific embedding model and Qdrant server:\n\n```sh\necho \"Document content\" | /path/to/vector-upsert \\\n  --collection documents \\\n  --metadata '{\"title\": \"Document Title\", \"category\": \"technical\"}' \\\n  --model text-embedding-3-large \\\n  --qdrant-url http://remote-qdrant:6333\n```\n\nUse timestamp-based optimization to skip upserting if content is up-to-date:\n\n```sh\necho \"Updated summary text\" | /path/to/vector-upsert \\\n  --collection summaries \\\n  --metadata '{\"url\": \"unique-identifier\", \"updated_at\": \"2024-05-15T10:30:00Z\", \"source\": \"github\"}' \\\n  --skip-if-up-to-date updated_at\n```\n\nSpecify which metadata field to use for ID generation:\n\n```sh\necho \"Summary text\" | /path/to/vector-upsert \\\n  --collection summaries \\\n  --metadata '{\"html_url\": \"unique-identifier\", \"summary\": \"Summary text\", \"source\": \"github\"}' \\\n  --vector-id-key html_url\n```\n\n**Error Conditions:**\n\nThe script will abort with clear error messages for:\n- Missing required arguments (`--collection`, `--metadata`)\n- Invalid JSON or nested objects/arrays in `--metadata` (arrays of primitives are allowed)\n- Empty text input via stdin\n- Embedding generation failures (invalid model, API issues)\n- Qdrant connectivity or API errors\n- Missing dependencies (`llm`, `curl`)\n\n### Semantic Search GitHub Conversations\n\nExecutes semantic search against conversation summaries stored in Qdrant. This plumbing command embeds a user query using the `llm` CLI and searches for the most similar conversations using vector similarity with support for metadata filtering.\n\n**Usage:**\n\n```sh\n/path/to/semantic-search-github-conversations [options] \"free-text query\"\n```\n\n**Options:**\n\n- `-c, --collection NAME`: Qdrant collection name (default: summaries)\n- `-f, --filter KEY:VALUE`: Filter by metadata (repeatable for multiple filters)\n- `-n, --limit N`: Maximum number of results to return (default: 10)\n- `--score-threshold N`: Minimum similarity score threshold (0.0-1.0)\n- `--order-by FIELD_DIR`: Order by field and direction (e.g., 'created_at desc')\n- `--url URL`: Qdrant base URL (default: http://localhost:6333)\n- `--format FORMAT`: Output format - yaml (default) or json\n- `-v, --verbose`: Dump request/response JSON for debugging\n- `-h, --help`: Show help message\n\n**Filter Syntax:**\n\nMultiple `--filter` flags with the same key are OR-combined, while different keys are AND-combined:\n\n```bash\n# Exact matches\n--filter repo:rails/rails\n--filter owner:github\n--filter type:issue\n--filter state:open\n--filter number:123\n\n# Date ranges (YYYY-MM-DD format)\n--filter created_after:2025-01-01\n--filter created_before:2025-06-30\n--filter updated_after:2025-01-01\n--filter updated_before:2025-06-30\n--filter indexed_after:2025-01-01\n--filter indexed_before:2025-06-30\n\n# Substring matches\n--filter title:security\n--filter author:octocat\n\n# Topic matching\n--filter topics:security\n--filter topics:bug\n```\n\n**Examples:**\n\nBasic semantic search:\n\n```sh\n/path/to/semantic-search-github-conversations \"authentication vulnerability\"\n```\n\nSearch with repository and topic filters:\n\n```sh\n/path/to/semantic-search-github-conversations -n 5 \\\n  --filter repo:rails/rails \\\n  --filter topics:security \\\n  --filter topics:bug \\\n  --filter created_after:2025-01-01 \\\n  --filter created_before:2025-06-30 \\\n  \"credential leak mitigation\"\n```\n\nSearch with custom ordering (most recent first):\n\n```sh\n/path/to/semantic-search-github-conversations \\\n  --order-by \"created_at desc\" \\\n  --filter repo:octocat/Hello-World \\\n  \"performance optimization\"\n```\n\nOutput as JSON for pipeline processing:\n\n```sh\n/path/to/semantic-search-github-conversations --format json \\\n  --filter repo:octocat/Hello-World \\\n  \"performance optimization\" | jq '.[].payload.url'\n```\n\nDebug Qdrant requests and responses:\n\n```sh\n/path/to/semantic-search-github-conversations --verbose \\\n  --collection github-summaries \\\n  --url http://localhost:6333 \\\n  \"database performance issues\"\n```\n\n**Combined Filter + Text Query (GitHub Conversations Research Agent):**\n\nThe research agent automatically extracts qualifiers from queries and combines them with semantic search:\n\n```sh\n./path/to/github-conversations-research-agent \"repo:octocat/Hello-World caching bug\" --collection github-conversations --verbose\n```\n\nThis will:\n1. Extract `repo:octocat/Hello-World` qualifier and convert it to `--filter repo:octocat/Hello-World`\n2. Strip the qualifier from the query, leaving `caching bug` for semantic embedding\n3. Combine both in the underlying `semantic-search-github-conversations` call\n\nSimilarly for author qualifiers:\n\n```sh\n./path/to/github-conversations-research-agent \"author:octocat authentication vulnerability\" --collection github-conversations\n```\n\nMultiple qualifiers are supported:\n\n```sh\n./path/to/github-conversations-research-agent \"repo:rails/rails author:dhh performance optimization\" --collection github-conversations\n```\n\n**Output Format:**\n\nDefault YAML output shows structured data with:\n- `id`: Unique point identifier from Qdrant\n- `score`: Similarity score (0.0-1.0)\n- `payload`: Complete metadata including URL, title, summary, labels, topics, etc.\n\nJSON output (`--format json`) returns the same structure as a JSON array, compatible with other pipeline scripts and tools like `jq`.\n\n**Requirements:**\n- `llm` CLI with embedding model support\n- Running Qdrant server with indexed conversation summaries\n- Conversations must be indexed using `index-summary` or `index-summaries`\n\n**Error Handling:**\n- Exits 1 with usage message if no query provided\n- Exits 1 with error message for embedding failures or Qdrant connectivity issues\n- Uses verbose mode to troubleshoot request/response JSON\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on contributing to this project.\n\n## Contributors\n\n- [jonmagic](https://github.com/jonmagic)\n\n## License\n\nThis project is licensed under the [ISC License](LICENSE).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonmagic%2Fscripts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjonmagic%2Fscripts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonmagic%2Fscripts/lists"}