git-stint 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +238 -0
- package/adapters/claude-code/hooks/git-stint-hook-pre-tool +96 -0
- package/adapters/claude-code/hooks/git-stint-hook-stop +34 -0
- package/adapters/claude-code/install.d.ts +11 -0
- package/adapters/claude-code/install.ts +16 -0
- package/bin/git-stint +2 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +268 -0
- package/dist/conflicts.d.ts +1 -0
- package/dist/conflicts.js +49 -0
- package/dist/git.d.ts +40 -0
- package/dist/git.js +149 -0
- package/dist/install-hooks.d.ts +9 -0
- package/dist/install-hooks.js +111 -0
- package/dist/manifest.d.ts +59 -0
- package/dist/manifest.js +165 -0
- package/dist/session.d.ts +19 -0
- package/dist/session.js +587 -0
- package/dist/test-session.d.ts +13 -0
- package/dist/test-session.js +130 -0
- package/package.json +52 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Rahul Chandrasekaran
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
# git-stint
|
|
2
|
+
|
|
3
|
+
[](LICENSE)
|
|
4
|
+
[](https://nodejs.org)
|
|
5
|
+
|
|
6
|
+
Session-scoped change tracking for AI coding agents. Each session gets a real git branch and worktree — isolated by default, mergeable at the end.
|
|
7
|
+
|
|
8
|
+
Built to replace GitButler for AI-agent workflows. No virtual branches, no custom merge engine, no state corruption. Just git.
|
|
9
|
+
|
|
10
|
+
## Why
|
|
11
|
+
|
|
12
|
+
AI coding agents (Claude Code, Cursor, Copilot) edit files but have no clean way to:
|
|
13
|
+
|
|
14
|
+
1. **Track what they changed** — separate agent changes from human changes
|
|
15
|
+
2. **Isolate sessions** — two parallel agents editing the same repo shouldn't conflict
|
|
16
|
+
3. **Produce clean commits** — agent work should result in reviewable, mergeable PRs
|
|
17
|
+
4. **Test in isolation** — verify one session's changes without interference
|
|
18
|
+
|
|
19
|
+
git-stint solves this with ~600 lines of TypeScript on top of standard git primitives.
|
|
20
|
+
|
|
21
|
+
## Prerequisites
|
|
22
|
+
|
|
23
|
+
- [Node.js](https://nodejs.org) 20+
|
|
24
|
+
- [git](https://git-scm.com) 2.20+ (worktree support)
|
|
25
|
+
- [`gh` CLI](https://cli.github.com) (optional, for PR creation)
|
|
26
|
+
|
|
27
|
+
## Quick Start
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install -g git-stint
|
|
31
|
+
|
|
32
|
+
# Start a session (creates branch + worktree)
|
|
33
|
+
git stint start auth-fix
|
|
34
|
+
cd .stint/auth-fix/
|
|
35
|
+
|
|
36
|
+
# Work normally — make changes, edit files...
|
|
37
|
+
|
|
38
|
+
# Commit progress (advances baseline)
|
|
39
|
+
git stint commit -m "Fix token refresh logic"
|
|
40
|
+
|
|
41
|
+
# More changes...
|
|
42
|
+
git stint commit -m "Add refresh token tests"
|
|
43
|
+
|
|
44
|
+
# Squash into a single clean commit
|
|
45
|
+
git stint squash -m "Fix auth token refresh"
|
|
46
|
+
|
|
47
|
+
# Create PR and clean up
|
|
48
|
+
git stint pr --title "Fix auth bug"
|
|
49
|
+
git stint end
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Commands
|
|
53
|
+
|
|
54
|
+
| Command | Description |
|
|
55
|
+
|---------|-------------|
|
|
56
|
+
| `git stint start [name]` | Create a new session (branch + worktree) |
|
|
57
|
+
| `git stint list` | List all active sessions |
|
|
58
|
+
| `git stint status` | Show current session state |
|
|
59
|
+
| `git stint track <file...>` | Add files to the pending list |
|
|
60
|
+
| `git stint diff` | Show uncommitted changes in worktree |
|
|
61
|
+
| `git stint commit -m "msg"` | Commit changes, advance baseline |
|
|
62
|
+
| `git stint log` | Show session commit history |
|
|
63
|
+
| `git stint squash -m "msg"` | Collapse all commits into one |
|
|
64
|
+
| `git stint merge` | Merge session into current branch (no PR) |
|
|
65
|
+
| `git stint pr [--title "..."]` | Push branch and create GitHub PR |
|
|
66
|
+
| `git stint end` | Finalize session, clean up everything |
|
|
67
|
+
| `git stint abort` | Discard session — delete all changes |
|
|
68
|
+
| `git stint undo` | Revert last commit, changes become pending |
|
|
69
|
+
| `git stint conflicts` | Check file overlap with other sessions |
|
|
70
|
+
| `git stint test [-- cmd]` | Run tests in the session worktree |
|
|
71
|
+
| `git stint test --combine A B` | Test multiple sessions merged together |
|
|
72
|
+
| `git stint prune` | Clean up orphaned worktrees/branches |
|
|
73
|
+
| `git stint install-hooks` | Install Claude Code hooks |
|
|
74
|
+
| `git stint uninstall-hooks` | Remove Claude Code hooks |
|
|
75
|
+
|
|
76
|
+
### Options
|
|
77
|
+
|
|
78
|
+
- `--session <name>` — Specify which session (auto-detected from CWD)
|
|
79
|
+
- `-m "message"` — Commit or squash message
|
|
80
|
+
- `--title "title"` — PR title
|
|
81
|
+
- `--version` — Show version number
|
|
82
|
+
|
|
83
|
+
## Claude Code Integration
|
|
84
|
+
|
|
85
|
+
git-stint includes hooks that make it work seamlessly with Claude Code:
|
|
86
|
+
|
|
87
|
+
- **PreToolUse hook**: When Claude writes/edits a file inside a session worktree, the file is automatically tracked. If Claude tries to write to the main repo while a session is active, the hook blocks the write and redirects to the worktree.
|
|
88
|
+
- **Stop hook**: When a Claude Code conversation ends, pending changes are auto-committed as a WIP checkpoint.
|
|
89
|
+
|
|
90
|
+
### Install Hooks
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# Install to project settings (.claude/settings.json)
|
|
94
|
+
git stint install-hooks
|
|
95
|
+
|
|
96
|
+
# Or install to user settings (~/.claude/settings.json)
|
|
97
|
+
git stint install-hooks --user
|
|
98
|
+
|
|
99
|
+
# To remove hooks later
|
|
100
|
+
git stint uninstall-hooks
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Workflow with Claude Code
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
# Start a session before asking Claude to work
|
|
107
|
+
git stint start my-feature
|
|
108
|
+
cd .stint/my-feature/
|
|
109
|
+
|
|
110
|
+
# Tell Claude to work on things — hooks handle tracking automatically
|
|
111
|
+
|
|
112
|
+
# When done, squash and PR
|
|
113
|
+
git stint squash -m "Implement feature X"
|
|
114
|
+
git stint pr
|
|
115
|
+
git stint end
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## How It Works
|
|
119
|
+
|
|
120
|
+
### Session Model
|
|
121
|
+
|
|
122
|
+
Each session creates:
|
|
123
|
+
- A **git branch** (`stint/<name>`) forked from HEAD
|
|
124
|
+
- A **worktree** (`.stint/<name>/`) for isolated file access
|
|
125
|
+
- A **manifest** (`.git/sessions/<name>.json`) tracking state
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
Session starts at HEAD = abc123
|
|
129
|
+
↓
|
|
130
|
+
Edit config.ts, server.ts
|
|
131
|
+
↓
|
|
132
|
+
"commit" → changeset 1 (baseline advances to new SHA)
|
|
133
|
+
↓
|
|
134
|
+
Edit server.ts (again), test.ts
|
|
135
|
+
↓
|
|
136
|
+
"commit" → changeset 2 (only NEW changes since last commit)
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
The **baseline cursor** advances on each commit. `git diff baseline..HEAD` always gives exactly the uncommitted work. No virtual branches, no custom merge engine.
|
|
140
|
+
|
|
141
|
+
### Parallel Sessions
|
|
142
|
+
|
|
143
|
+
Multiple sessions run simultaneously with full isolation:
|
|
144
|
+
|
|
145
|
+
```
|
|
146
|
+
Session A: edits config.ts, server.ts → .stint/session-a/
|
|
147
|
+
Session B: edits server.ts, constants.ts → .stint/session-b/
|
|
148
|
+
↑ overlap detected by `git stint conflicts`
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Each session has its own worktree — no interference. Conflicts resolve at PR merge time, using git's standard merge machinery.
|
|
152
|
+
|
|
153
|
+
### Testing
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
# Test a single session in its worktree
|
|
157
|
+
git stint test -- npm test
|
|
158
|
+
|
|
159
|
+
# Test multiple sessions merged together
|
|
160
|
+
git stint test --combine auth-fix perf-update -- npm test
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Combined testing creates a temporary octopus merge of the specified sessions, runs the test command, then cleans up. No permanent state changes.
|
|
164
|
+
|
|
165
|
+
## Architecture
|
|
166
|
+
|
|
167
|
+
```
|
|
168
|
+
┌─────────────┐ ┌──────────────┐ ┌────────────────┐
|
|
169
|
+
│ CLI │ │ Session │ │ Manifest │
|
|
170
|
+
│ (cli.ts) │────▶│ (session.ts) │────▶│ (manifest.ts) │
|
|
171
|
+
│ arg parsing │ │ commands │ │ JSON state │
|
|
172
|
+
└─────────────┘ └──────┬───────┘ └────────────────┘
|
|
173
|
+
│
|
|
174
|
+
┌──────▼───────┐
|
|
175
|
+
│ Git │
|
|
176
|
+
│ (git.ts) │
|
|
177
|
+
│ plumbing │
|
|
178
|
+
└──────────────┘
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
| File | Purpose | Lines |
|
|
182
|
+
|------|---------|-------|
|
|
183
|
+
| `src/git.ts` | Git command wrapper (`execFileSync`) | ~170 |
|
|
184
|
+
| `src/manifest.ts` | Session state CRUD in `.git/sessions/` | ~160 |
|
|
185
|
+
| `src/session.ts` | Core commands (start, commit, squash, pr, end...) | ~600 |
|
|
186
|
+
| `src/conflicts.ts` | Cross-session file overlap detection | ~55 |
|
|
187
|
+
| `src/test-session.ts` | Worktree-based testing + combined testing | ~140 |
|
|
188
|
+
| `src/cli.ts` | Entry point, argument parsing | ~230 |
|
|
189
|
+
|
|
190
|
+
### Design Decisions
|
|
191
|
+
|
|
192
|
+
- **Real git branches** — not virtual branches. Every git tool works: `git log`, `git diff`, lazygit, tig, VS Code.
|
|
193
|
+
- **Worktrees for isolation** — the default state is isolated. No unapply/apply dance.
|
|
194
|
+
- **JSON manifests** — stored in `.git/sessions/`. Disposable. Worst case: delete and start over.
|
|
195
|
+
- **No custom merge engine** — git's built-in merge handles everything. Source of most GitButler complexity eliminated.
|
|
196
|
+
- **`execFileSync` everywhere** — array arguments prevent shell injection. No `execSync` with string interpolation.
|
|
197
|
+
- **Atomic manifest writes** — write to `.tmp`, then `rename()`. Crash-safe.
|
|
198
|
+
|
|
199
|
+
## git-stint vs GitButler
|
|
200
|
+
|
|
201
|
+
| Aspect | git-stint | GitButler |
|
|
202
|
+
|--------|-----------|-----------|
|
|
203
|
+
| Isolation | Default (each branch IS isolated) | Opt-in (unapply other branches) |
|
|
204
|
+
| Branch storage | Real git branches | Virtual branches (TOML + SQLite) |
|
|
205
|
+
| Working dir | One branch per worktree | Permanent octopus merge overlay |
|
|
206
|
+
| Merge engine | Git's built-in | Custom hunk-level engine |
|
|
207
|
+
| Git compatibility | Full — all git tools work | Partial — writes break state |
|
|
208
|
+
| State | JSON manifests (disposable) | SQLite + TOML (can corrupt) |
|
|
209
|
+
| Code size | ~600 lines TypeScript | ~100k+ lines Rust |
|
|
210
|
+
| Dependencies | git, gh (optional) | Tauri desktop app |
|
|
211
|
+
|
|
212
|
+
git-stint is designed for AI agent workflows where sessions are independent and short-lived. GitButler is a full-featured branch management GUI for teams.
|
|
213
|
+
|
|
214
|
+
## Development
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
git clone https://github.com/rchaz/git-stint.git
|
|
218
|
+
cd git-stint
|
|
219
|
+
npm install
|
|
220
|
+
npm run build
|
|
221
|
+
npm link # Install globally for testing
|
|
222
|
+
|
|
223
|
+
# Run tests
|
|
224
|
+
npm test # Unit tests
|
|
225
|
+
npm run test:security # Security tests
|
|
226
|
+
npm run test:integration # Integration tests
|
|
227
|
+
npm run test:all # Everything
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## Contributing
|
|
231
|
+
|
|
232
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, testing, and PR guidelines.
|
|
233
|
+
|
|
234
|
+
Please note that this project is released with a [Code of Conduct](CODE_OF_CONDUCT.md). By participating, you agree to abide by its terms.
|
|
235
|
+
|
|
236
|
+
## License
|
|
237
|
+
|
|
238
|
+
MIT — see [LICENSE](LICENSE)
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# Claude Code PreToolUse hook for git-stint
|
|
4
|
+
# Called before Write/Edit/NotebookEdit tool use.
|
|
5
|
+
#
|
|
6
|
+
# Reads tool input from stdin (JSON), extracts file_path, and tracks it.
|
|
7
|
+
#
|
|
8
|
+
# Behavior:
|
|
9
|
+
# - File is inside a .stint/ worktree: tracks the file, allows the write.
|
|
10
|
+
# - File is in main repo with active session: blocks the write and tells
|
|
11
|
+
# the agent to work in the worktree directory instead.
|
|
12
|
+
# - No session active: allows the write silently.
|
|
13
|
+
#
|
|
14
|
+
|
|
15
|
+
set -euo pipefail
|
|
16
|
+
|
|
17
|
+
# Check that git-stint is available
|
|
18
|
+
if ! command -v git-stint &>/dev/null; then
|
|
19
|
+
echo "Warning: git-stint is not in PATH. Hooks will not work." >&2
|
|
20
|
+
echo "Install with: npm install -g git-stint (or npm link from the repo)" >&2
|
|
21
|
+
exit 0
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
# Read the tool input from stdin
|
|
25
|
+
INPUT=$(cat)
|
|
26
|
+
|
|
27
|
+
# Extract file_path using jq if available, fallback to grep/sed
|
|
28
|
+
if command -v jq &>/dev/null; then
|
|
29
|
+
FILE_PATH=$(echo "$INPUT" | jq -r '.file_path // .notebook_path // empty' 2>/dev/null || true)
|
|
30
|
+
else
|
|
31
|
+
FILE_PATH=$(echo "$INPUT" | grep -o '"file_path"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed 's/.*"file_path"[[:space:]]*:[[:space:]]*"//' | sed 's/"$//')
|
|
32
|
+
if [ -z "$FILE_PATH" ]; then
|
|
33
|
+
FILE_PATH=$(echo "$INPUT" | grep -o '"notebook_path"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed 's/.*"notebook_path"[[:space:]]*:[[:space:]]*"//' | sed 's/"$//')
|
|
34
|
+
fi
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
# If no file path found, allow silently
|
|
38
|
+
if [ -z "$FILE_PATH" ]; then
|
|
39
|
+
exit 0
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
# Check if the file being edited is inside a stint worktree (check the file path, not pwd)
|
|
43
|
+
# Match /.stint/<name>/ precisely — avoid false positives like /my.stint/ or /.stinted/
|
|
44
|
+
if echo "$FILE_PATH" | grep -qE '/\.stint/[^/]+/'; then
|
|
45
|
+
# File is in a stint worktree — track and allow
|
|
46
|
+
git-stint track "$FILE_PATH" 2>/dev/null || true
|
|
47
|
+
exit 0
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
# The file is NOT in a stint worktree. Check if any stint session exists.
|
|
51
|
+
SESSIONS_DIR="$(git rev-parse --git-common-dir 2>/dev/null)/sessions"
|
|
52
|
+
if [ -d "$SESSIONS_DIR" ]; then
|
|
53
|
+
# Iterate session manifests to find the best one to suggest.
|
|
54
|
+
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || true)"
|
|
55
|
+
BEST_WORKTREE=""
|
|
56
|
+
BEST_SESSION=""
|
|
57
|
+
|
|
58
|
+
for manifest in "$SESSIONS_DIR"/*.json; do
|
|
59
|
+
[ -f "$manifest" ] || continue
|
|
60
|
+
# Skip .tmp files (glob won't match, but be safe)
|
|
61
|
+
case "$manifest" in *.tmp) continue ;; esac
|
|
62
|
+
|
|
63
|
+
if command -v jq &>/dev/null; then
|
|
64
|
+
wt=$(jq -r '.worktree // empty' "$manifest" 2>/dev/null || true)
|
|
65
|
+
sn=$(jq -r '.name // empty' "$manifest" 2>/dev/null || true)
|
|
66
|
+
else
|
|
67
|
+
wt=$(grep -o '"worktree"[[:space:]]*:[[:space:]]*"[^"]*"' "$manifest" | head -1 | sed 's/.*"worktree"[[:space:]]*:[[:space:]]*"//;s/"$//')
|
|
68
|
+
sn=$(grep -o '"name"[[:space:]]*:[[:space:]]*"[^"]*"' "$manifest" | head -1 | sed 's/.*"name"[[:space:]]*:[[:space:]]*"//;s/"$//')
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
if [ -z "$BEST_WORKTREE" ] && [ -n "$wt" ]; then
|
|
72
|
+
BEST_WORKTREE="$wt"
|
|
73
|
+
BEST_SESSION="$sn"
|
|
74
|
+
fi
|
|
75
|
+
done
|
|
76
|
+
|
|
77
|
+
if [ -n "$BEST_WORKTREE" ]; then
|
|
78
|
+
# Active session exists but agent is writing to the main repo — block.
|
|
79
|
+
if [ -n "$REPO_ROOT" ]; then
|
|
80
|
+
ABS_WORKTREE="$REPO_ROOT/$BEST_WORKTREE"
|
|
81
|
+
echo "BLOCKED: You have an active stint session '${BEST_SESSION}'." >&2
|
|
82
|
+
echo "You must work in the session worktree, not the main repo." >&2
|
|
83
|
+
echo "Run: cd \"$ABS_WORKTREE\"" >&2
|
|
84
|
+
echo "Then retry your edit. The file you need is: $ABS_WORKTREE/${FILE_PATH#$REPO_ROOT/}" >&2
|
|
85
|
+
else
|
|
86
|
+
echo "BLOCKED: An active stint session exists. Work in the session worktree instead." >&2
|
|
87
|
+
echo "Run: git stint list" >&2
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
# Exit non-zero to block the tool call
|
|
91
|
+
exit 1
|
|
92
|
+
fi
|
|
93
|
+
fi
|
|
94
|
+
|
|
95
|
+
# No session active — allow the write
|
|
96
|
+
exit 0
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# Claude Code Stop hook for git-stint
|
|
4
|
+
# Called when a Claude Code session ends.
|
|
5
|
+
#
|
|
6
|
+
# Commits any pending changes as a WIP checkpoint.
|
|
7
|
+
# The session persists — user can resume or finalize later.
|
|
8
|
+
#
|
|
9
|
+
|
|
10
|
+
set -euo pipefail
|
|
11
|
+
|
|
12
|
+
# Check that git-stint is available
|
|
13
|
+
if ! command -v git-stint &>/dev/null; then
|
|
14
|
+
echo "Warning: git-stint is not in PATH. Stop hook cannot commit pending changes." >&2
|
|
15
|
+
echo "Install with: npm install -g git-stint (or npm link from the repo)" >&2
|
|
16
|
+
exit 0
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
# Commit pending work for all active sessions.
|
|
20
|
+
# Uses --json to get session names, avoiding "multiple sessions" ambiguity error.
|
|
21
|
+
SESSIONS_JSON=$(git-stint list --json 2>/dev/null || echo "[]")
|
|
22
|
+
|
|
23
|
+
if command -v jq &>/dev/null; then
|
|
24
|
+
NAMES=$(echo "$SESSIONS_JSON" | jq -r '.[].name' 2>/dev/null || true)
|
|
25
|
+
else
|
|
26
|
+
NAMES=$(echo "$SESSIONS_JSON" | grep -o '"name":"[^"]*"' | sed 's/"name":"//;s/"$//' || true)
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
if [ -n "$NAMES" ]; then
|
|
30
|
+
echo "$NAMES" | while read -r name; do
|
|
31
|
+
[ -z "$name" ] && continue
|
|
32
|
+
git-stint commit -m "WIP: session checkpoint" --session "$name" 2>/dev/null || true
|
|
33
|
+
done
|
|
34
|
+
fi
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Installs git-stint hooks into Claude Code's settings.
|
|
3
|
+
*
|
|
4
|
+
* Usage: node install.js [--project | --user]
|
|
5
|
+
*
|
|
6
|
+
* Hooks installed:
|
|
7
|
+
* PreToolUse (Write/Edit): Track files written in session worktrees
|
|
8
|
+
* Stop: Commit pending changes as WIP checkpoint
|
|
9
|
+
*/
|
|
10
|
+
declare function install(scope: "project" | "user"): void;
|
|
11
|
+
export { install };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Standalone installer script for git-stint hooks.
|
|
3
|
+
* Re-exports from src/install-hooks.ts for backward compatibility.
|
|
4
|
+
*
|
|
5
|
+
* Usage: node install.js [--project | --user]
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export { install } from "../../src/install-hooks.js";
|
|
9
|
+
|
|
10
|
+
// Run directly when executed as a script
|
|
11
|
+
import { install } from "../../src/install-hooks.js";
|
|
12
|
+
const isDirectRun = process.argv[1]?.endsWith("install.js") || process.argv[1]?.endsWith("install.ts");
|
|
13
|
+
if (isDirectRun) {
|
|
14
|
+
const scope = process.argv.includes("--user") ? "user" : "project";
|
|
15
|
+
install(scope);
|
|
16
|
+
}
|
package/bin/git-stint
ADDED
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|