diff --git a/README.md b/README.md index fa8b4c6..76e04c7 100644 --- a/README.md +++ b/README.md @@ -1,35 +1,52 @@ # Shift Log +[![License](https://img.shields.io/badge/License-AINAL-blue.svg)](https://github.com/re-cinq/ai-native-application-license) +[![Go](https://img.shields.io/badge/Go-1.21+-00ADD8.svg)](https://go.dev) +[![Git Notes](https://img.shields.io/badge/Git%20Notes-Supported-green.svg)](https://git-scm.com/docs/git-notes) + Save, view, and search coding agent conversation history, persisted as Git Notes. -## Install +## ✨ Features + +- πŸ“ **Automatic Capture** β€” Conversations saved automatically on commits +- πŸ” **Full-text Search** β€” Search through past agent sessions +- πŸ“Š **Summarise** β€” AI-powered conversation summaries +- πŸ”„ **Resume Sessions** β€” Pick up where you left off +- 🌐 **Web Viewer** β€” Visualize conversations in browser +- 🀝 **Team Sync** β€” Share conversations across your team via Git + +## πŸš€ Quick Start + +### Installation ```bash curl -fsSL https://raw.githubusercontent.com/re-cinq/shift-log/master/scripts/install.sh | bash ``` +### Initialize in a Git Repo + ```bash -# ...In a Git repo +cd your-project shiftlog init --agent= ``` Where `` is `claude` (default), `codex`, `copilot`, `gemini`, or `opencode`. -Now work with your coding agent as you would normally. Whenever you or the agent commit, the conversation since the last commit will be attached to that commit as a Git Note. +Now work with your coding agent as normal. Whenever you or the agent commits, the conversation since the last commit will be attached as a Git Note. -## Supported Agents +## πŸ“‹ Supported Agents -| Agent | Init command | How it hooks in | -| ----------- | ------------------------------- | ------------------------------------- | -| Claude Code | `shiftlog init` (default) | `.claude/settings.json` hooks | -| Codex CLI | `shiftlog init --agent=codex` | Post-commit git hook | -| Copilot CLI | `shiftlog init --agent=copilot` | `.github/hooks/shiftlog.json` hook | -| Gemini CLI | `shiftlog init --agent=gemini` | `.gemini/settings.json` hooks | -| OpenCode | `shiftlog init --agent=opencode` | `.opencode/plugins/shiftlog.js` plugin | +| Agent | Init Command | Hook Method | +|-------|--------------|-------------| +| **Claude Code** | `shiftlog init` (default) | `.claude/settings.json` | +| **Codex CLI** | `shiftlog init --agent=codex` | Post-commit hook | +| **Copilot CLI** | `shiftlog init --agent=copilot` | `.github/hooks/shiftlog.json` | +| **Gemini CLI** | `shiftlog init --agent=gemini` | `.gemini/settings.json` | +| **OpenCode** | `shiftlog init --agent=opencode` | `.opencode/plugins/shiftlog.js` | -## Usage +## πŸ’‘ Usage -**See what conversations you have:** +**See your conversation history:** ```bash shiftlog list @@ -38,17 +55,17 @@ shiftlog list **Search through past conversations:** ```bash -shiftlog search "authentication" # Text search -shiftlog search --agent claude --branch main # Filter by metadata -shiftlog search "jwt" --regex --context 2 # Regex with context lines +shiftlog search "authentication" # Text search +shiftlog search --agent claude --branch main # Filter by metadata +shiftlog search "jwt" --regex --context 2 # Regex with context ``` -**Get a quick summary of a conversation:** +**Summarise a conversation:** ```bash -shiftlog summarise # Summarise HEAD conversation -shiftlog tldr HEAD~1 # Alias, works the same way -shiftlog tldr --focus="security" # Prioritise security-related changes +shiftlog summarise # Summarise HEAD conversation +shiftlog tldr HEAD~1 # Alias, same result +shiftlog tldr --focus="security" ``` **Resume a past session:** @@ -58,118 +75,98 @@ shiftlog resume abc123 # By commit SHA shiftlog resume HEAD~3 # By git ref ``` -**View in your browser:** +**View in browser:** ```bash shiftlog serve ``` -**Pull down conversations from a repo you cloned:** +**Sync with remote:** ```bash shiftlog sync pull +shiftlog sync push ``` -## shiftlog vs Entire - -| | [Entire](https://entire.io) | shiftlog | -| ------------------- | --------------------------- | ---------------------------------------------------------- | -| **Funding** | $60M seed round | Claude Code Max plan ($200/mo) | -| **Staffing** | 12 engineers | An imbecile spec-driving while not really paying attention | -| **Agents** | Claude Code, Gemini CLI | Claude Code, Codex CLI, Copilot CLI, Gemini CLI, OpenCode | -| **Storage** | Custom checkpoints format | Standard Git Notes | -| **Resume sessions** | No | Yes | -| **Web viewer** | No | Yes | -| **Rebase support** | No | Yes | -| **Open source** | Yes | Yes | - -## Why? - -In order to understand _how_ and _why_ a commit was made, we need to see the conversation that led to it. - -## How It Works - -Shiftlog uses [Git Notes](https://git-scm.com/docs/git-notes) to attach conversations to commits, stored under `refs/notes/shiftlog` to keep `git log` clean. When you run `shiftlog init`, it sets up hooks so: - -1. When the coding agent makes a commit, the conversation is saved automatically -2. When you make a commit during an agent session, it's saved too -3. When you push/pull, conversations sync with the remote - -No extra steps needed during your normal workflow. - -To view notes directly with git: `git log --notes=shiftlog` - -## Commands +## βš™οΈ Commands Reference -| Command | Description | -| ------------------------- | --------------------------------------- | -| `shiftlog init` | Initialize shiftlog in the current repo | -| `shiftlog list` | List commits with stored conversations | -| `shiftlog search [query]` | Search through stored conversations | -| `shiftlog show [ref]` | Show conversation history for a commit | -| `shiftlog summarise [ref]` | Summarise a conversation using your coding agent | -| `shiftlog resume ` | Resume a coding agent session from a commit | -| `shiftlog serve` | Start the web visualization server | -| `shiftlog doctor` | Diagnose shiftlog configuration issues | -| `shiftlog debug` | Toggle debug logging | -| `shiftlog sync push/pull` | Sync conversation notes with remote | -| `shiftlog remap` | Remap orphaned notes to rebased commits | +| Command | Description | +|---------|-------------| +| `shiftlog init` | Initialize shiftlog in the current repo | +| `shiftlog list` | List commits with stored conversations | +| `shiftlog search [query]` | Search through stored conversations | +| `shiftlog show [ref]` | Show conversation history for a commit | +| `shiftlog summarise [ref]` | Summarise a conversation | +| `shiftlog resume ` | Resume a coding agent session | +| `shiftlog serve` | Start the web visualization server | +| `shiftlog doctor` | Diagnose configuration issues | +| `shiftlog sync push/pull` | Sync notes with remote | +| `shiftlog remap` | Remap orphaned notes after rebase | -## Requirements +## πŸ”§ Requirements - Git -- One of the supported coding agents (Claude Code, Codex CLI, Copilot CLI, Gemini CLI, or OpenCode) +- One of: Claude Code, Codex CLI, Copilot CLI, Gemini CLI, or OpenCode -## Multi-Developer Sync +## πŸ€– How It Works -When multiple developers use shiftlog on the same repository, each person's conversation notes are synced automatically via git push/pull hooks. Notes from different developers are merged seamlessly because they typically annotate different commits. +Shiftlog uses [Git Notes](https://git-scm.com/docs/git-notes) to attach conversations to commits under `refs/notes/shiftlog`. This keeps `git log` clean while persisting valuable context. -If the remote notes ref has diverged (e.g. two developers pushed notes without pulling first), `shiftlog sync push` will reject the push and advise you to pull first: - -```bash -shiftlog sync pull # Fetches and merges remote notes -shiftlog sync push # Now succeeds +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” commit β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Claude Code β”‚ ──────────────▢│ Git β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ β”‚ + β”‚ post-commit hook β”‚ git notes + β–Ό β–Ό +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ shiftlog β”‚ ──────────────▢│ Git Note β”‚ +β”‚ capture β”‚ β”‚ refs/notes/ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ shiftlog β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` -In the rare case where two developers annotate the exact same commit SHA, both notes are preserved by concatenation β€” no data is lost. - -## Git Worktrees - -Shiftlog is worktree-safe. If you use `git worktree` to work on multiple branches simultaneously, each worktree sees only the conversations for commits on its own branch. Hooks are shared across worktrees (as git requires), but `shiftlog list` and `shiftlog show` are scoped to the current HEAD. - -## Local Rebase +## πŸ‘₯ Team Collaboration -Conversation notes automatically follow commits when you rebase. During `shiftlog init`, the `notes.rewriteRef` git config is set to `refs/notes/shiftlog`, which tells git to remap notes to the new commit SHAs during rebase. No manual steps are needed. +When multiple developers use shiftlog on the same repository, conversation notes sync automatically via git push/pull hooks. Notes are merged seamlessly because each developer typically annotates different commits. -If you initialized before this config was added, run `shiftlog init` again or set it manually: +If notes diverge: ```bash -git config notes.rewriteRef refs/notes/shiftlog +shiftlog sync pull # Fetch and merge remote notes +shiftlog sync push # Now succeeds ``` -You can verify the config is set with `shiftlog doctor`. - -## GitHub Rebase Merge +## πŸ“Œ Git Operations -When a PR is merged via GitHub's "Rebase and merge" strategy, the commits get new SHAs on the target branch. Since this happens server-side, git's `notes.rewriteRef` does not apply and notes remain keyed to the original (now-orphaned) commit SHAs. +### Worktrees +Shiftlog is worktree-safe. Each worktree sees only conversations for commits on its own branch. -Shiftlog handles this automatically. After you pull a rebase-merged PR, the post-merge hook runs `shiftlog remap`, which: +### Rebase +Notes automatically follow commits during rebase via `notes.rewriteRef`. No manual steps needed. -1. Finds notes on commits that are no longer on any branch (orphaned) -2. Uses `git patch-id` to match each orphaned commit to its rebased counterpart by diff content -3. Copies the note to the new commit SHA (the original note is also kept) +### GitHub Rebase Merge +For PRs merged via "Rebase and merge", run `shiftlog remap` after pulling to remap orphaned notes to new commit SHAs. -For this to work, the local feature branch must be deleted or pruned so the old commits become orphaned. If your GitHub repo is configured to auto-delete branches after merge, this happens naturally when you `git pull` with `fetch.prune=true` (or `git fetch --prune`). Otherwise, delete the branch manually first: +## πŸ“Š Comparison -```bash -git branch -D feature-branch -shiftlog remap -``` +| Feature | [Entire](https://entire.io) | Shift Log | +|---------|---------------------------|-----------| +| **Agents** | Claude Code, Gemini CLI | Claude, Codex, Copilot, Gemini, OpenCode | +| **Storage** | Custom checkpoints | Git Notes (standard) | +| **Resume Sessions** | ❌ | βœ… | +| **Web Viewer** | ❌ | βœ… | +| **Rebase Support** | ❌ | βœ… | +| **Open Source** | βœ… | βœ… | -You can also run `shiftlog remap` at any time β€” it reports how many notes were remapped and how many remain unmatched. Unmatched notes are left in place, not deleted. +## ❓ Why? -**Note:** Remap works with GitHub's "Rebase and merge" strategy. It does not support "Squash and merge", which combines all commits into one new commit with no 1:1 mapping to copy notes from. +To understand _how_ and _why_ a commit was made, you need to see the conversation that led to it. ShiftLog makes that possible. -## License +## πŸ“„ License [AI Native Application License (AINAL)](https://github.com/re-cinq/ai-native-application-license) β€” see [LICENSE](LICENSE). + +--- + +*README optimized with [Gingiris README Generator](https://gingiris.github.io/github-readme-generator/)*