gitdirector 1.5.2__tar.gz → 1.6.0__tar.gz

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.
Files changed (58) hide show
  1. {gitdirector-1.5.2 → gitdirector-1.6.0}/PKG-INFO +91 -47
  2. gitdirector-1.6.0/README.md +267 -0
  3. {gitdirector-1.5.2 → gitdirector-1.6.0}/pyproject.toml +1 -7
  4. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/cli.py +8 -1
  5. gitdirector-1.6.0/src/gitdirector/commands/capture.py +86 -0
  6. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/commands/cd.py +2 -1
  7. gitdirector-1.6.0/src/gitdirector/commands/completion.py +41 -0
  8. gitdirector-1.6.0/src/gitdirector/commands/gd_send.py +54 -0
  9. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/commands/gd_tmux.py +20 -6
  10. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/commands/help.py +11 -2
  11. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/commands/info.py +2 -1
  12. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/commands/tui/__init__.py +4 -0
  13. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/commands/tui/app.py +250 -58
  14. gitdirector-1.6.0/src/gitdirector/commands/tui/app_groups.py +106 -0
  15. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/commands/tui/app_panels.py +8 -3
  16. gitdirector-1.6.0/src/gitdirector/commands/tui/app_repos.py +405 -0
  17. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/commands/tui/app_sessions.py +67 -3
  18. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/commands/tui/app_ui.py +19 -7
  19. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/commands/tui/constants.py +25 -7
  20. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/commands/tui/panel_view.py +0 -6
  21. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/commands/tui/screens/__init__.py +4 -1
  22. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/commands/tui/screens/diff.py +81 -20
  23. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/commands/tui/screens/diff_files.py +12 -0
  24. gitdirector-1.6.0/src/gitdirector/commands/tui/screens/groups.py +30 -0
  25. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/commands/tui/screens/panels.py +26 -16
  26. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/commands/tui/screens/repos.py +34 -89
  27. gitdirector-1.6.0/src/gitdirector/commands/tui/screens/session_actions.py +110 -0
  28. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/commands/tui/screens/sessions.py +76 -2
  29. gitdirector-1.6.0/src/gitdirector/commands/tui/table_text.py +35 -0
  30. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/commands/tui/terminal_widget.py +54 -17
  31. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/commands/unlink.py +7 -1
  32. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/config.py +78 -13
  33. gitdirector-1.6.0/src/gitdirector/github_credential_helper.py +36 -0
  34. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/integrations/tmux/core.py +410 -75
  35. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/integrations/tmux/monitor.py +92 -39
  36. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/integrations/tmux/panels.py +226 -102
  37. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/repo.py +77 -7
  38. gitdirector-1.5.2/README.md +0 -222
  39. gitdirector-1.5.2/src/gitdirector/commands/tui/app_repos.py +0 -267
  40. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/__init__.py +0 -0
  41. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/commands/__init__.py +0 -0
  42. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/commands/autoclean.py +0 -0
  43. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/commands/link.py +0 -0
  44. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/commands/listt.py +0 -0
  45. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/commands/pull.py +0 -0
  46. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/commands/status.py +0 -0
  47. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/commands/tui/diff_renderer.py +0 -0
  48. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/commands/tui/panels.py +0 -0
  49. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/commands/tui/screens/_shared.py +0 -0
  50. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/commands/tui/screens/commit.py +0 -0
  51. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/commands/tui/terminal_caps.py +0 -0
  52. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/info.py +0 -0
  53. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/integrations/__init__.py +0 -0
  54. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/integrations/tmux/__init__.py +0 -0
  55. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/manager.py +0 -0
  56. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/storage.py +0 -0
  57. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/ui_theme.py +0 -0
  58. {gitdirector-1.5.2 → gitdirector-1.6.0}/src/gitdirector/version_check.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: gitdirector
3
- Version: 1.5.2
3
+ Version: 1.6.0
4
4
  Summary: A terminal based control plane for developers working across multiple repositories. Launch multiple AI coding agents, multiple tmux sessions and track changes across all your repos in one place.
5
5
  Keywords: git,repository,manager,cli,synchronization,batch
6
6
  Author: Anito Anto
@@ -24,7 +24,6 @@ Requires-Dist: rich>=12.0
24
24
  Requires-Dist: textual>=8.2.1
25
25
  Requires-Dist: tiktoken>=0.5.0
26
26
  Requires-Dist: pyte>=0.8.2
27
- Requires-Dist: black>=23.0 ; extra == 'dev'
28
27
  Requires-Dist: pytest>=7.0 ; extra == 'dev'
29
28
  Requires-Dist: pytest-asyncio>=0.23 ; extra == 'dev'
30
29
  Requires-Dist: pytest-cov>=4.0 ; extra == 'dev'
@@ -49,7 +48,7 @@ A terminal based control plane for developers working across multiple repositori
49
48
 
50
49
  If you work across more than a handful of repositories, the overhead adds up fast. Jumping between terminals to check states, pull changes, and babysit agents is friction you don't need.
51
50
 
52
- GitDirector gives you a single cockpit for all of it. See every repo's status, Drop into any of them. Run AI agents in parallel, each isolated in its own tmux session, while you monitor everything from the dashboard. Less tab-switching, more shipping.
51
+ GitDirector gives you a single cockpit for all of it. See every repo's status, drop into any of them. Run AI agents in parallel, each isolated in its own tmux session, while you monitor everything from the dashboard. Less tab-switching, more shipping.
53
52
 
54
53
  ## Installation
55
54
 
@@ -65,19 +64,22 @@ If you find GitDirector useful, please star this repository on GitHub, we need m
65
64
 
66
65
  ## Usage
67
66
 
68
- | Command | Description |
69
- | -------------------------------------------- | ------------------------------------------------------ |
70
- | `gitdirector console` | Open the interactive TUI dashboard |
71
- | `gitdirector link PATH [--discover]` | Link a repository or discover all under a path |
72
- | `gitdirector unlink PATH\|NAME [--discover]` | Unlink a repository by path, name, or all under a path |
73
- | `gitdirector list` | List all tracked repositories with live status |
74
- | `gitdirector status` | Show repositories with staged/unstaged files |
75
- | `gitdirector pull` | Pull latest changes for all tracked repositories |
76
- | `gitdirector cd NAME` | Open or switch to a tmux session for a repository |
77
- | `gitdirector autoclean` | Remove broken repository links from tracking |
78
- | `gitdirector info PATH\|NAME [--full]` | Show file statistics for a repository |
79
- | `gitdirector gd-tmux PATH\|NAME "command"` | Create a gd tmux session and run a command in it |
80
- | `gitdirector help` | Show help |
67
+ | Command | Description |
68
+ | ---------------------------------------------------------- | ------------------------------------------------------ |
69
+ | `gitdirector console` | Open the interactive TUI dashboard |
70
+ | `gitdirector link PATH [--discover]` | Link a repository or discover all under a path |
71
+ | `gitdirector unlink PATH\|NAME [--discover]` | Unlink a repository by path, name, or all under a path |
72
+ | `gitdirector list` | List all tracked repositories with live status |
73
+ | `gitdirector status` | Show repositories with staged/unstaged files |
74
+ | `gitdirector pull [--yes]` | Pull latest changes for all tracked repositories |
75
+ | `gitdirector cd NAME` | Open or switch to a tmux session for a repository |
76
+ | `gitdirector autoclean` | Remove broken repository links from tracking |
77
+ | `gitdirector info PATH\|NAME [--full]` | Show file statistics for a repository |
78
+ | `gitdirector gd-tmux PATH\|NAME "command" [--description TEXT]` | Create a gd tmux session and run a command in it |
79
+ | `gitdirector gd-capture SESSION [--lines N] [--full]` | Print the scrollback of a live gd tmux session |
80
+ | `gitdirector gd-send SESSION [TEXT] [--enter\|--key C-c]` | Send text or Ctrl-C to a live gd tmux session |
81
+ | `gitdirector completion SHELL` | Print shell completion setup for bash, zsh, or fish |
82
+ | `gitdirector help` | Show help |
81
83
 
82
84
  ### link
83
85
 
@@ -97,10 +99,12 @@ Opens a full interactive TUI dashboard.
97
99
  Features:
98
100
 
99
101
  - Live table with sync state, branch, changes, last commit, and active tmux sessions
102
+ - Tabs for `[1] Repositories`, `[2] Sessions`, and `[3] Panels`
100
103
  - `j`/`k` or arrow keys to navigate
101
- - `/` to filter repositories by name or path
102
- - `s` to cycle sort by any column
104
+ - `/` to filter the active tab
105
+ - `s` to sort the active table
103
106
  - `i` to show repository info (file count, lines, tokens, max depth, top file types)
107
+ - `g` on the Repositories tab to open Git operations: status, timeline, branches, remotes, pull, and push
104
108
  - `r` to refresh all statuses
105
109
  - Press `enter` on any repository to open an action menu:
106
110
  - **New tmux session** — create and attach a session for the repository
@@ -108,6 +112,9 @@ Features:
108
112
  - **Attach existing session** — switch to any already-running tmux session
109
113
  - **Launch AI agent** — open OpenCode, Claude Code, GitHub Copilot, Codex, or Pi in a new tmux session
110
114
  - **Remove session** — kill a running tmux session
115
+ - **Repository groups** appear directly in the Repositories tab when linked repositories share the same parent directory. Group rows can be expanded/collapsed with `space`; press `enter` on a group to start, attach, remove, or launch AI-agent sessions rooted at that parent directory.
116
+ - **Sessions tab** (press `2`) lists every active `gd/*` tmux session with its status, purpose, repository, **description**, and full session name. The description column is free-form text stored on the session (default `"-"`), with a width that scales to your terminal and wraps long text. Highlight a row and press `d` to edit its description.
117
+ - **Panels tab** (press `3`) manages reusable tmux panel layouts. Press `n` to create a panel, or `enter` on a panel to open, reconfigure, rename, or delete it.
111
118
 
112
119
  ### unlink
113
120
 
@@ -157,8 +164,16 @@ Shows repositories with uncommitted changes (staged and/or unstaged files). Prin
157
164
 
158
165
  ### pull
159
166
 
167
+ ```bash
168
+ gitdirector pull # prompts before pulling
169
+ gitdirector pull --yes # skip confirmation
170
+ gitdirector pull -y # short form
171
+ ```
172
+
160
173
  Pulls all tracked repositories concurrently using fast-forward only on each repository's current branch (`git pull --ff-only origin <current-branch>`). Reports success or failure per repository.
161
174
 
175
+ By default, `pull` asks for confirmation after listing the repositories it will update. Use `--yes` / `-y` for non-interactive runs.
176
+
162
177
  ### cd
163
178
 
164
179
  ```bash
@@ -182,14 +197,23 @@ Opens a [tmux](https://github.com/tmux/tmux) session rooted at the repository di
182
197
  gitdirector gd-tmux my-repo "npm test"
183
198
  gitdirector gd-tmux /path/to/my-repo "make build"
184
199
  gitdirector gd-tmux my-repo 'echo "hello world"'
200
+ gitdirector gd-tmux my-repo "opencode" --description "OpenCode: refactor auth middleware"
185
201
  ```
186
202
 
187
- Creates a new gd tmux session rooted at the given repository, runs the supplied command inside it, and attaches the session. The session is created using the same code path the TUI's **Launch AI agent** menu uses: it is a real `gd/{repo}/{command}/{N}` session, visible in the Sessions tab of `gitdirector console`, and it self-destructs when the command exits.
203
+ Creates a new gd tmux session rooted at the given repository, runs the supplied command inside it, and returns immediately without attaching. The session is a real `gd/{repo}/shell/{N}` session, visible in the Sessions tab of `gitdirector console`, and it self-destructs when the command exits. `N` is allocated as one higher than the highest currently running matching shell session number.
188
204
 
189
205
  - `PATH|NAME` — accept either an absolute path to a tracked repository or its basename, with the same disambiguation rules as `gitdirector unlink`.
190
206
  - `"command"` — the shell command to run inside the new session. Pass it quoted so the shell hands the whole string to gitdirector; quotes and arguments are preserved verbatim.
207
+ - `--description` / `-d` — optional. Free-text description stored on the session and shown in the Sessions tab. Accepts both `--description "text"` and `--description=text` forms. When omitted, the column displays `"-"`.
208
+
209
+ The full session name (e.g. `gd/myrepo/shell/1`) is printed to stdout right after the background session is created, so scripts and agents can capture it for later use with `gd-capture`:
210
+
211
+ ```bash
212
+ SESSION=$(gitdirector gd-tmux /path/to/repo opencode --description "OpenCode: refactor auth")
213
+ gitdirector gd-capture "$SESSION" --lines 100
214
+ ```
191
215
 
192
- The command is the same as opening the repo in the console, picking **Launch AI agent** from the action menu, and entering the command — but you can do it from any shell without entering the TUI first. The new session shows up in the Sessions tab immediately.
216
+ Use this from any shell to start a background command without entering the TUI first. The new session shows up in the Sessions tab immediately. Inside the TUI, highlight any session row and press `d` to edit its description.
193
217
 
194
218
  ### autoclean
195
219
 
@@ -199,44 +223,43 @@ gitdirector autoclean
199
223
 
200
224
  Scans the tracked repositories in `~/.gitdirector/config.yaml` for paths that no longer exist on disk and removes them from the config. Lists any broken links for review and asks for confirmation before deleting them.
201
225
 
202
- ## Note for AI coding agents
203
-
204
- If you are an AI coding agent reading this project: when the user asks you to run a long-lived process inside a tracked repository — a dev server, a frontend bundler, a backend API, a watcher, a database, a test runner with a long timeout, or anything else that does not exit on its own — **do not run it in the foreground**. A foreground process will block your shell for the rest of the session and the user will not be able to interact with you.
226
+ ### gd-capture
205
227
 
206
- Use `gitdirector gd-tmux` to launch the process in a detached gd tmux session that the user can monitor and tear down themselves. The session shows up in the Sessions tab of `gitdirector console`, auto-cleans up when the process exits, and supports path-or-name lookup the same way every other gitdirector command does.
228
+ ```bash
229
+ gitdirector gd-capture gd/myrepo/shell/1 # last 200 lines
230
+ gitdirector gd-capture gd/myrepo/shell/1 --lines 50 # last 50 lines
231
+ gitdirector gd-capture gd/myrepo/shell/1 --full # entire scrollback
232
+ ```
207
233
 
208
- **Always prefer the absolute path over the repo name.** The by-name lookup matches the *directory name on disk* verbatim (via `Path.name`) case-sensitive, dots and spaces included — and is ambiguous if two tracked repos share the same basename. When in doubt, look up the path with `gitdirector list` and use the absolute path. Quoting a path is fine; an absolute path is never ambiguous.
234
+ Prints the current scrollback of a live `gd/*` tmux session to stdout (plain text, pipeable into `grep`/`less`/etc.). The argument is the full session name as shown in the TUI Sessions tab. It must match the `gd/<repo>/<purpose>/<N>` shape; sessions created by `gd-tmux` use `gd/<repo>/shell/<N>`.
209
235
 
210
- Examples:
236
+ **Only running sessions can be captured.** `gd-tmux` sessions self-destruct when their command exits (success or failure), so for any *finished* session you have to have redirected the command's own output to a file:
211
237
 
212
238
  ```bash
213
- # Frontend dev server in the user's web repo — use the absolute path
214
- gitdirector gd-tmux /Users/me/projects/webapp "npm run dev"
215
-
216
- # Backend API in the api repo
217
- gitdirector gd-tmux /Users/me/projects/api "uvicorn app.main:app --reload --port 8000"
239
+ gitdirector gd-tmux myrepo "make test 2>&1 | tee /tmp/run.log"
240
+ ```
218
241
 
219
- # A long-running integration test with output captured to a log
220
- gitdirector gd-tmux /Users/me/projects/myrepo "pytest -x -v 2>&1 | tee /tmp/test.log"
242
+ The session is gone the moment the command exits; the scrollback lives on only as the bytes the process actually wrote.
221
243
 
222
- # A watcher or build loop
223
- gitdirector gd-tmux /Users/me/projects/myrepo "npm run watch"
244
+ ### gd-send
224
245
 
225
- # A repo whose directory name contains a space — quote both the path and the command
226
- gitdirector gd-tmux "/Users/me/projects/My Repo" "npm run dev"
246
+ ```bash
247
+ gitdirector gd-send gd/myrepo/opencode/1 "continue and run the tests"
248
+ gitdirector gd-send gd/myrepo/shell/1 "npm test" --enter
249
+ gitdirector gd-send gd/myrepo/shell/1 --key C-c
227
250
  ```
228
251
 
229
- The by-name form is supported for ergonomic use by humans in interactive shells, but agents should default to the absolute path to avoid any chance of matching the wrong repo.
252
+ Sends input to a live `gd/*` tmux session. The session argument must be the full session name shown in the TUI Sessions tab, for example `gd/myrepo/shell/1`.
253
+
254
+ - `TEXT` is pasted into the active pane. It does not press Enter unless `--enter` is provided.
255
+ - `--enter` presses Enter after pasting `TEXT`, useful for running shell commands.
256
+ - `--key C-c` sends Ctrl-C to the active pane, useful for stopping a running foreground process without killing the tmux session.
230
257
 
231
- Rules of thumb:
258
+ Accepted `--key` values: `C-c`.
232
259
 
233
- - **Use the absolute path.** It is unambiguous and survives the user renaming or moving the directory. The by-name form is convenient shorthand, not a slug — it is the raw directory name, case-sensitive.
234
- - **Repo names with spaces, dots, or punctuation are matched verbatim** when you do use the by-name form. A repo at `/Users/me/My Repo` is matched by `"My Repo"`, not by `My` or `Repo`. Quote the name to keep the shell from splitting it.
235
- - **Quoting the command matters.** The command string is handed to `sh -lc` inside the new session, so write it as a single quoted string. `'echo "hi"'` (single-quote outer, double-quote inner) is the safest pattern for embedded double quotes.
236
- - **Path separators in the command are fine.** Commands like `python /path/to/script.py` or `find . -name foo/bar` work; the command is embedded verbatim into the inner shell, while the session-name label is auto-sanitized.
237
- - **The session self-destructs** when the command exits (success or failure), so you do not need to clean it up.
238
- - **If you need to capture output**, redirect it to a file in the command itself (`> /tmp/out 2>&1`) and read the file later — the session is gone once the command exits.
239
- - **If the user asks you to stop a running process**, kill the matching session: `gitdirector console` → Sessions tab, or directly with `tmux kill-session -t =<session-name>`.
260
+ ## For AI coding agents
261
+
262
+ If you are an AI coding agent (Claude Code, OpenCode, GitHub Copilot, Codex, Pi, or any other tool that drives a shell on the user's behalf), the rules for integrating with the user's GitDirector workflow — including `gd-tmux` background sessions, `gd-capture`, and the mandatory `--description` flag — live in [`LLMS.md`](./LLMS.md). Read that file end-to-end before running any commands.
240
263
 
241
264
  ## Configuration
242
265
 
@@ -248,8 +271,19 @@ repositories:
248
271
  - /path/to/repo2
249
272
  max_workers: 10 # optional, valid range 1-32, default 10
250
273
  theme: rose-pine # optional, default rose-pine
274
+ github_username: your-github-username # optional
275
+ github_PAT: github_pat_or_classic_pat # optional
251
276
  ```
252
277
 
278
+ ### GitHub PAT fallback
279
+
280
+ GitDirector first runs git commands using your normal local git credentials. If a git command fails with an authentication error and both `github_username` and `github_PAT` are configured, GitDirector retries the command with a temporary Git credential helper for `https://github.com` remotes.
281
+
282
+ - This only applies to HTTPS GitHub remotes.
283
+ - SSH remotes still use your normal SSH key/agent setup.
284
+ - The PAT is stored in plaintext in `~/.gitdirector/config.yaml`; use an appropriately scoped token and protect that file.
285
+ - The PAT is not passed on the command line or shown in TUI command output.
286
+
253
287
  ### Available Themes
254
288
 
255
289
  `textual-dark`, `textual-light`, `nord`, `gruvbox`, `catppuccin-mocha`, `textual-ansi`, `dracula`, `tokyo-night`, `monokai`, `flexoki`, `catppuccin-latte`, `catppuccin-frappe`, `catppuccin-macchiato`, `solarized-light`, `solarized-dark`, `rose-pine`, `rose-pine-moon`, `rose-pine-dawn`, `atom-one-dark`, `atom-one-light`
@@ -258,7 +292,17 @@ theme: rose-pine # optional, default rose-pine
258
292
 
259
293
  - Python 3.10+
260
294
  - Git
261
- - [tmux](https://github.com/tmux/tmux) ≥ 3.2a (for `gitdirector cd`)
295
+ - [tmux](https://github.com/tmux/tmux) ≥ 3.2a (for `gitdirector cd`, `gitdirector console` sessions, `gitdirector gd-tmux`, `gitdirector gd-capture`, and `gitdirector gd-send`)
296
+
297
+ ## Shell completion
298
+
299
+ Generate shell completions for `bash`, `zsh`, or `fish`. Completion includes subcommands, options, and linked repository names for repo-target commands.
300
+
301
+ ```bash
302
+ eval "$(gitdirector completion bash)"
303
+ eval "$(gitdirector completion zsh)"
304
+ gitdirector completion fish | source
305
+ ```
262
306
 
263
307
  ## License
264
308
 
@@ -0,0 +1,267 @@
1
+ # GitDirector
2
+
3
+ A terminal based control plane for developers working across multiple repositories. Launch multiple AI coding agents, multiple tmux sessions and track changes across all your repos in one place.
4
+
5
+ ## Why GitDirector?
6
+
7
+ If you work across more than a handful of repositories, the overhead adds up fast. Jumping between terminals to check states, pull changes, and babysit agents is friction you don't need.
8
+
9
+ GitDirector gives you a single cockpit for all of it. See every repo's status, drop into any of them. Run AI agents in parallel, each isolated in its own tmux session, while you monitor everything from the dashboard. Less tab-switching, more shipping.
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ pip install gitdirector
15
+ ```
16
+
17
+ Requires Python 3.10+.
18
+
19
+ ## Support
20
+
21
+ If you find GitDirector useful, please star this repository on GitHub, we need more stars to qualify for inclusion in Homebrew. Your support helps a lot, thank you!
22
+
23
+ ## Usage
24
+
25
+ | Command | Description |
26
+ | ---------------------------------------------------------- | ------------------------------------------------------ |
27
+ | `gitdirector console` | Open the interactive TUI dashboard |
28
+ | `gitdirector link PATH [--discover]` | Link a repository or discover all under a path |
29
+ | `gitdirector unlink PATH\|NAME [--discover]` | Unlink a repository by path, name, or all under a path |
30
+ | `gitdirector list` | List all tracked repositories with live status |
31
+ | `gitdirector status` | Show repositories with staged/unstaged files |
32
+ | `gitdirector pull [--yes]` | Pull latest changes for all tracked repositories |
33
+ | `gitdirector cd NAME` | Open or switch to a tmux session for a repository |
34
+ | `gitdirector autoclean` | Remove broken repository links from tracking |
35
+ | `gitdirector info PATH\|NAME [--full]` | Show file statistics for a repository |
36
+ | `gitdirector gd-tmux PATH\|NAME "command" [--description TEXT]` | Create a gd tmux session and run a command in it |
37
+ | `gitdirector gd-capture SESSION [--lines N] [--full]` | Print the scrollback of a live gd tmux session |
38
+ | `gitdirector gd-send SESSION [TEXT] [--enter\|--key C-c]` | Send text or Ctrl-C to a live gd tmux session |
39
+ | `gitdirector completion SHELL` | Print shell completion setup for bash, zsh, or fish |
40
+ | `gitdirector help` | Show help |
41
+
42
+ ### link
43
+
44
+ ```bash
45
+ gitdirector link /path/to/repo
46
+ gitdirector link /path/to/folder --discover # recursively find and link all repos
47
+ ```
48
+
49
+ ### console
50
+
51
+ ```bash
52
+ gitdirector console
53
+ ```
54
+
55
+ Opens a full interactive TUI dashboard.
56
+
57
+ Features:
58
+
59
+ - Live table with sync state, branch, changes, last commit, and active tmux sessions
60
+ - Tabs for `[1] Repositories`, `[2] Sessions`, and `[3] Panels`
61
+ - `j`/`k` or arrow keys to navigate
62
+ - `/` to filter the active tab
63
+ - `s` to sort the active table
64
+ - `i` to show repository info (file count, lines, tokens, max depth, top file types)
65
+ - `g` on the Repositories tab to open Git operations: status, timeline, branches, remotes, pull, and push
66
+ - `r` to refresh all statuses
67
+ - Press `enter` on any repository to open an action menu:
68
+ - **New tmux session** — create and attach a session for the repository
69
+ - **Review Diff** — open a two-pane viewer for uncommitted changes (left: file list with GitHub-style status pills and +/- counts; right: per-file unified diff with GitHub-dark syntax highlighting, line numbers, and green/red backgrounds for added/removed lines). Navigate files with `j`/`k`, `n`/`p`, `g`/`G`, or `]`/`[`. Switch the focused panel with `tab`. `r` refreshes, `esc` closes.
70
+ - **Attach existing session** — switch to any already-running tmux session
71
+ - **Launch AI agent** — open OpenCode, Claude Code, GitHub Copilot, Codex, or Pi in a new tmux session
72
+ - **Remove session** — kill a running tmux session
73
+ - **Repository groups** appear directly in the Repositories tab when linked repositories share the same parent directory. Group rows can be expanded/collapsed with `space`; press `enter` on a group to start, attach, remove, or launch AI-agent sessions rooted at that parent directory.
74
+ - **Sessions tab** (press `2`) lists every active `gd/*` tmux session with its status, purpose, repository, **description**, and full session name. The description column is free-form text stored on the session (default `"-"`), with a width that scales to your terminal and wraps long text. Highlight a row and press `d` to edit its description.
75
+ - **Panels tab** (press `3`) manages reusable tmux panel layouts. Press `n` to create a panel, or `enter` on a panel to open, reconfigure, rename, or delete it.
76
+
77
+ ### unlink
78
+
79
+ ```bash
80
+ gitdirector unlink /path/to/repo # unlink by full path
81
+ gitdirector unlink my-repo # unlink by repository name
82
+ gitdirector unlink /path/to/folder --discover # unlink all repos under a path
83
+ ```
84
+
85
+ If multiple tracked repositories share the same name, `gitdirector` will refuse and list the conflicting paths so you can use the full path instead.
86
+
87
+ ### info
88
+
89
+ ```bash
90
+ gitdirector info /path/to/repo # by path
91
+ gitdirector info my-repo # by name
92
+ gitdirector info my-repo --full # show all file extensions
93
+ ```
94
+
95
+ Shows file statistics for a repository:
96
+
97
+ - Total file count, line count, token count, and max directory depth
98
+ - Top 10 file types by count with line and token breakdowns (use `--full` to show all)
99
+ - Files without extensions grouped as `(no ext)`
100
+ - Remaining types grouped as `others`
101
+ - Binary files show `-` for lines and tokens
102
+ - All operations respect `.gitignore` at every level
103
+
104
+ Also available in the TUI console by pressing `i` on a selected repository.
105
+
106
+ ### list
107
+
108
+ Displays a live table of all tracked repositories with:
109
+
110
+ - Sync state: `up to date`, `ahead`, `behind`, `diverged`, or `unknown`
111
+ - Current branch
112
+ - Staged/unstaged changes
113
+ - Last commit (relative time)
114
+ - Tracked file size
115
+ - Path
116
+
117
+ Checks run concurrently (default: 10 workers, configurable from 1 to 32).
118
+
119
+ ### status
120
+
121
+ Shows repositories with uncommitted changes (staged and/or unstaged files). Prints a summary of total, clean, and changed repo counts.
122
+
123
+ ### pull
124
+
125
+ ```bash
126
+ gitdirector pull # prompts before pulling
127
+ gitdirector pull --yes # skip confirmation
128
+ gitdirector pull -y # short form
129
+ ```
130
+
131
+ Pulls all tracked repositories concurrently using fast-forward only on each repository's current branch (`git pull --ff-only origin <current-branch>`). Reports success or failure per repository.
132
+
133
+ By default, `pull` asks for confirmation after listing the repositories it will update. Use `--yes` / `-y` for non-interactive runs.
134
+
135
+ ### cd
136
+
137
+ ```bash
138
+ gitdirector cd my-repo
139
+ ```
140
+
141
+ Opens a [tmux](https://github.com/tmux/tmux) session rooted at the repository directory, or switches to it if a session for that repo already exists.
142
+
143
+ - **Inside tmux** — switches the current client to the target session.
144
+ - **Outside tmux** — replaces the current process with `tmux attach-session`, handing the terminal over to tmux.
145
+
146
+ > **Requires tmux to be installed on your system.**
147
+ >
148
+ > macOS: `brew install tmux`
149
+ > Debian/Ubuntu: `sudo apt install tmux`
150
+ > Arch: `sudo pacman -S tmux`
151
+
152
+ ### gd-tmux
153
+
154
+ ```bash
155
+ gitdirector gd-tmux my-repo "npm test"
156
+ gitdirector gd-tmux /path/to/my-repo "make build"
157
+ gitdirector gd-tmux my-repo 'echo "hello world"'
158
+ gitdirector gd-tmux my-repo "opencode" --description "OpenCode: refactor auth middleware"
159
+ ```
160
+
161
+ Creates a new gd tmux session rooted at the given repository, runs the supplied command inside it, and returns immediately without attaching. The session is a real `gd/{repo}/shell/{N}` session, visible in the Sessions tab of `gitdirector console`, and it self-destructs when the command exits. `N` is allocated as one higher than the highest currently running matching shell session number.
162
+
163
+ - `PATH|NAME` — accept either an absolute path to a tracked repository or its basename, with the same disambiguation rules as `gitdirector unlink`.
164
+ - `"command"` — the shell command to run inside the new session. Pass it quoted so the shell hands the whole string to gitdirector; quotes and arguments are preserved verbatim.
165
+ - `--description` / `-d` — optional. Free-text description stored on the session and shown in the Sessions tab. Accepts both `--description "text"` and `--description=text` forms. When omitted, the column displays `"-"`.
166
+
167
+ The full session name (e.g. `gd/myrepo/shell/1`) is printed to stdout right after the background session is created, so scripts and agents can capture it for later use with `gd-capture`:
168
+
169
+ ```bash
170
+ SESSION=$(gitdirector gd-tmux /path/to/repo opencode --description "OpenCode: refactor auth")
171
+ gitdirector gd-capture "$SESSION" --lines 100
172
+ ```
173
+
174
+ Use this from any shell to start a background command without entering the TUI first. The new session shows up in the Sessions tab immediately. Inside the TUI, highlight any session row and press `d` to edit its description.
175
+
176
+ ### autoclean
177
+
178
+ ```bash
179
+ gitdirector autoclean
180
+ ```
181
+
182
+ Scans the tracked repositories in `~/.gitdirector/config.yaml` for paths that no longer exist on disk and removes them from the config. Lists any broken links for review and asks for confirmation before deleting them.
183
+
184
+ ### gd-capture
185
+
186
+ ```bash
187
+ gitdirector gd-capture gd/myrepo/shell/1 # last 200 lines
188
+ gitdirector gd-capture gd/myrepo/shell/1 --lines 50 # last 50 lines
189
+ gitdirector gd-capture gd/myrepo/shell/1 --full # entire scrollback
190
+ ```
191
+
192
+ Prints the current scrollback of a live `gd/*` tmux session to stdout (plain text, pipeable into `grep`/`less`/etc.). The argument is the full session name as shown in the TUI Sessions tab. It must match the `gd/<repo>/<purpose>/<N>` shape; sessions created by `gd-tmux` use `gd/<repo>/shell/<N>`.
193
+
194
+ **Only running sessions can be captured.** `gd-tmux` sessions self-destruct when their command exits (success or failure), so for any *finished* session you have to have redirected the command's own output to a file:
195
+
196
+ ```bash
197
+ gitdirector gd-tmux myrepo "make test 2>&1 | tee /tmp/run.log"
198
+ ```
199
+
200
+ The session is gone the moment the command exits; the scrollback lives on only as the bytes the process actually wrote.
201
+
202
+ ### gd-send
203
+
204
+ ```bash
205
+ gitdirector gd-send gd/myrepo/opencode/1 "continue and run the tests"
206
+ gitdirector gd-send gd/myrepo/shell/1 "npm test" --enter
207
+ gitdirector gd-send gd/myrepo/shell/1 --key C-c
208
+ ```
209
+
210
+ Sends input to a live `gd/*` tmux session. The session argument must be the full session name shown in the TUI Sessions tab, for example `gd/myrepo/shell/1`.
211
+
212
+ - `TEXT` is pasted into the active pane. It does not press Enter unless `--enter` is provided.
213
+ - `--enter` presses Enter after pasting `TEXT`, useful for running shell commands.
214
+ - `--key C-c` sends Ctrl-C to the active pane, useful for stopping a running foreground process without killing the tmux session.
215
+
216
+ Accepted `--key` values: `C-c`.
217
+
218
+ ## For AI coding agents
219
+
220
+ If you are an AI coding agent (Claude Code, OpenCode, GitHub Copilot, Codex, Pi, or any other tool that drives a shell on the user's behalf), the rules for integrating with the user's GitDirector workflow — including `gd-tmux` background sessions, `gd-capture`, and the mandatory `--description` flag — live in [`LLMS.md`](./LLMS.md). Read that file end-to-end before running any commands.
221
+
222
+ ## Configuration
223
+
224
+ Config is stored at `~/.gitdirector/config.yaml`.
225
+
226
+ ```yaml
227
+ repositories:
228
+ - /path/to/repo1
229
+ - /path/to/repo2
230
+ max_workers: 10 # optional, valid range 1-32, default 10
231
+ theme: rose-pine # optional, default rose-pine
232
+ github_username: your-github-username # optional
233
+ github_PAT: github_pat_or_classic_pat # optional
234
+ ```
235
+
236
+ ### GitHub PAT fallback
237
+
238
+ GitDirector first runs git commands using your normal local git credentials. If a git command fails with an authentication error and both `github_username` and `github_PAT` are configured, GitDirector retries the command with a temporary Git credential helper for `https://github.com` remotes.
239
+
240
+ - This only applies to HTTPS GitHub remotes.
241
+ - SSH remotes still use your normal SSH key/agent setup.
242
+ - The PAT is stored in plaintext in `~/.gitdirector/config.yaml`; use an appropriately scoped token and protect that file.
243
+ - The PAT is not passed on the command line or shown in TUI command output.
244
+
245
+ ### Available Themes
246
+
247
+ `textual-dark`, `textual-light`, `nord`, `gruvbox`, `catppuccin-mocha`, `textual-ansi`, `dracula`, `tokyo-night`, `monokai`, `flexoki`, `catppuccin-latte`, `catppuccin-frappe`, `catppuccin-macchiato`, `solarized-light`, `solarized-dark`, `rose-pine`, `rose-pine-moon`, `rose-pine-dawn`, `atom-one-dark`, `atom-one-light`
248
+
249
+ ## Requirements
250
+
251
+ - Python 3.10+
252
+ - Git
253
+ - [tmux](https://github.com/tmux/tmux) ≥ 3.2a (for `gitdirector cd`, `gitdirector console` sessions, `gitdirector gd-tmux`, `gitdirector gd-capture`, and `gitdirector gd-send`)
254
+
255
+ ## Shell completion
256
+
257
+ Generate shell completions for `bash`, `zsh`, or `fish`. Completion includes subcommands, options, and linked repository names for repo-target commands.
258
+
259
+ ```bash
260
+ eval "$(gitdirector completion bash)"
261
+ eval "$(gitdirector completion zsh)"
262
+ gitdirector completion fish | source
263
+ ```
264
+
265
+ ## License
266
+
267
+ MIT
@@ -4,7 +4,7 @@ build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "gitdirector"
7
- version = "1.5.2"
7
+ version = "1.6.0"
8
8
  description = "A terminal based control plane for developers working across multiple repositories. Launch multiple AI coding agents, multiple tmux sessions and track changes across all your repos in one place."
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -41,7 +41,6 @@ dependencies = [
41
41
 
42
42
  [project.optional-dependencies]
43
43
  dev = [
44
- "black>=23.0",
45
44
  "pytest>=7.0",
46
45
  "pytest-asyncio>=0.23",
47
46
  "pytest-cov>=4.0",
@@ -64,7 +63,6 @@ managed = true
64
63
 
65
64
  [dependency-groups]
66
65
  dev = [
67
- "black>=23.0",
68
66
  "pytest>=7.0",
69
67
  "pytest-asyncio>=0.23",
70
68
  "pytest-cov>=4.0",
@@ -73,10 +71,6 @@ dev = [
73
71
  "ruff>=0.1.0",
74
72
  ]
75
73
 
76
- [tool.black]
77
- line-length = 100
78
- target-version = ["py310", "py311", "py312"]
79
-
80
74
  [tool.ruff]
81
75
  line-length = 100
82
76
  target-version = "py310"
@@ -8,8 +8,11 @@ from .commands import (
8
8
  _path_text,
9
9
  _status_text,
10
10
  autoclean,
11
+ capture,
11
12
  cd,
13
+ completion,
12
14
  console,
15
+ gd_send,
13
16
  gd_tmux,
14
17
  help,
15
18
  info,
@@ -41,7 +44,8 @@ class _HelpGroup(click.Group):
41
44
  @click.group(cls=_HelpGroup, invoke_without_command=True)
42
45
  @click.pass_context
43
46
  def cli(ctx):
44
- print_update_notice()
47
+ if not ctx.resilient_parsing and ctx.invoked_subcommand != "completion":
48
+ print_update_notice()
45
49
  if ctx.invoked_subcommand is None:
46
50
  show_help()
47
51
 
@@ -57,6 +61,9 @@ tui.register(cli)
57
61
  autoclean.register(cli)
58
62
  info.register(cli)
59
63
  gd_tmux.register(cli)
64
+ capture.register(cli)
65
+ gd_send.register(cli)
66
+ completion.register(cli)
60
67
 
61
68
 
62
69
  def main():