agitrack 0.0.5__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 (100) hide show
  1. agitrack-0.0.5/LICENSE +201 -0
  2. agitrack-0.0.5/PKG-INFO +395 -0
  3. agitrack-0.0.5/README.md +379 -0
  4. agitrack-0.0.5/agitrack/__init__.py +37 -0
  5. agitrack-0.0.5/agitrack/__main__.py +7 -0
  6. agitrack-0.0.5/agitrack/backends/__init__.py +1 -0
  7. agitrack-0.0.5/agitrack/backends/base.py +65 -0
  8. agitrack-0.0.5/agitrack/backends/claude.py +121 -0
  9. agitrack-0.0.5/agitrack/backends/opencode.py +224 -0
  10. agitrack-0.0.5/agitrack/backends/proxy_agents.py +239 -0
  11. agitrack-0.0.5/agitrack/backends/setup.py +121 -0
  12. agitrack-0.0.5/agitrack/cli.py +388 -0
  13. agitrack-0.0.5/agitrack/commits/__init__.py +24 -0
  14. agitrack-0.0.5/agitrack/commits/actions.py +121 -0
  15. agitrack-0.0.5/agitrack/commits/message.py +461 -0
  16. agitrack-0.0.5/agitrack/config/__init__.py +7 -0
  17. agitrack-0.0.5/agitrack/config/migrate.py +64 -0
  18. agitrack-0.0.5/agitrack/config/settings.py +248 -0
  19. agitrack-0.0.5/agitrack/config/state.py +508 -0
  20. agitrack-0.0.5/agitrack/env.py +19 -0
  21. agitrack-0.0.5/agitrack/git/__init__.py +31 -0
  22. agitrack-0.0.5/agitrack/git/lock.py +129 -0
  23. agitrack-0.0.5/agitrack/git/repo.py +664 -0
  24. agitrack-0.0.5/agitrack/git/worktree.py +122 -0
  25. agitrack-0.0.5/agitrack/metrics/__init__.py +18 -0
  26. agitrack-0.0.5/agitrack/metrics/collect.py +877 -0
  27. agitrack-0.0.5/agitrack/metrics/github.py +157 -0
  28. agitrack-0.0.5/agitrack/metrics/render.py +114 -0
  29. agitrack-0.0.5/agitrack/metrics/server.py +148 -0
  30. agitrack-0.0.5/agitrack/metrics/web.py +1328 -0
  31. agitrack-0.0.5/agitrack/proxy/__init__.py +42 -0
  32. agitrack-0.0.5/agitrack/proxy/commit_engine.py +691 -0
  33. agitrack-0.0.5/agitrack/proxy/integration.py +603 -0
  34. agitrack-0.0.5/agitrack/proxy/modal.py +195 -0
  35. agitrack-0.0.5/agitrack/proxy/process.py +219 -0
  36. agitrack-0.0.5/agitrack/proxy/renderer.py +698 -0
  37. agitrack-0.0.5/agitrack/proxy/runner.py +6667 -0
  38. agitrack-0.0.5/agitrack/proxy/sandbox.py +180 -0
  39. agitrack-0.0.5/agitrack/proxy/session.py +202 -0
  40. agitrack-0.0.5/agitrack/proxy/session_names.py +248 -0
  41. agitrack-0.0.5/agitrack/proxy/terminal.py +204 -0
  42. agitrack-0.0.5/agitrack/sessions/__init__.py +23 -0
  43. agitrack-0.0.5/agitrack/sessions/identity.py +53 -0
  44. agitrack-0.0.5/agitrack/sessions/redact.py +31 -0
  45. agitrack-0.0.5/agitrack/sessions/store.py +428 -0
  46. agitrack-0.0.5/agitrack/shell/__init__.py +5 -0
  47. agitrack-0.0.5/agitrack/shell/runner.py +342 -0
  48. agitrack-0.0.5/agitrack/shell/ui.py +114 -0
  49. agitrack-0.0.5/agitrack/summaries/__init__.py +8 -0
  50. agitrack-0.0.5/agitrack/summaries/model_select.py +73 -0
  51. agitrack-0.0.5/agitrack/summaries/prompts.py +52 -0
  52. agitrack-0.0.5/agitrack/summaries/summarizer.py +310 -0
  53. agitrack-0.0.5/agitrack/transcripts/__init__.py +12 -0
  54. agitrack-0.0.5/agitrack/transcripts/claude.py +598 -0
  55. agitrack-0.0.5/agitrack/transcripts/opencode.py +547 -0
  56. agitrack-0.0.5/agitrack/transcripts/types.py +57 -0
  57. agitrack-0.0.5/agitrack/update/__init__.py +23 -0
  58. agitrack-0.0.5/agitrack/update/updater.py +452 -0
  59. agitrack-0.0.5/agitrack.egg-info/PKG-INFO +395 -0
  60. agitrack-0.0.5/agitrack.egg-info/SOURCES.txt +98 -0
  61. agitrack-0.0.5/agitrack.egg-info/dependency_links.txt +1 -0
  62. agitrack-0.0.5/agitrack.egg-info/entry_points.txt +3 -0
  63. agitrack-0.0.5/agitrack.egg-info/requires.txt +3 -0
  64. agitrack-0.0.5/agitrack.egg-info/top_level.txt +1 -0
  65. agitrack-0.0.5/pyproject.toml +73 -0
  66. agitrack-0.0.5/setup.cfg +4 -0
  67. agitrack-0.0.5/tests/test_backend_commits.py +331 -0
  68. agitrack-0.0.5/tests/test_backend_process.py +200 -0
  69. agitrack-0.0.5/tests/test_backend_setup.py +96 -0
  70. agitrack-0.0.5/tests/test_backends_and_config.py +276 -0
  71. agitrack-0.0.5/tests/test_claude_session.py +503 -0
  72. agitrack-0.0.5/tests/test_cli.py +562 -0
  73. agitrack-0.0.5/tests/test_commit_engine.py +718 -0
  74. agitrack-0.0.5/tests/test_commit_message.py +509 -0
  75. agitrack-0.0.5/tests/test_commit_message_summary.py +122 -0
  76. agitrack-0.0.5/tests/test_dashboard.py +1108 -0
  77. agitrack-0.0.5/tests/test_demo_script.py +45 -0
  78. agitrack-0.0.5/tests/test_git_notes.py +60 -0
  79. agitrack-0.0.5/tests/test_integration_service.py +799 -0
  80. agitrack-0.0.5/tests/test_lock.py +158 -0
  81. agitrack-0.0.5/tests/test_opencode_commands.py +21 -0
  82. agitrack-0.0.5/tests/test_opencode_parse.py +55 -0
  83. agitrack-0.0.5/tests/test_opencode_session.py +329 -0
  84. agitrack-0.0.5/tests/test_pre_compaction.py +158 -0
  85. agitrack-0.0.5/tests/test_proxy.py +5617 -0
  86. agitrack-0.0.5/tests/test_proxy_modal.py +461 -0
  87. agitrack-0.0.5/tests/test_proxy_session.py +112 -0
  88. agitrack-0.0.5/tests/test_rename_compat.py +181 -0
  89. agitrack-0.0.5/tests/test_sandbox.py +151 -0
  90. agitrack-0.0.5/tests/test_session_names.py +26 -0
  91. agitrack-0.0.5/tests/test_session_sharing.py +1964 -0
  92. agitrack-0.0.5/tests/test_shell.py +154 -0
  93. agitrack-0.0.5/tests/test_state.py +207 -0
  94. agitrack-0.0.5/tests/test_summarizer.py +409 -0
  95. agitrack-0.0.5/tests/test_summarizer_config.py +48 -0
  96. agitrack-0.0.5/tests/test_summary_async.py +433 -0
  97. agitrack-0.0.5/tests/test_summary_scratch.py +53 -0
  98. agitrack-0.0.5/tests/test_ui.py +25 -0
  99. agitrack-0.0.5/tests/test_update.py +642 -0
  100. agitrack-0.0.5/tests/test_worktree.py +1129 -0
agitrack-0.0.5/LICENSE ADDED
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
@@ -0,0 +1,395 @@
1
+ Metadata-Version: 2.4
2
+ Name: agitrack
3
+ Version: 0.0.5
4
+ Summary: Interactive coding-agent CLI that commits AI changes to git with traceable metadata.
5
+ Author: aGiTrack contributors
6
+ License: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/core-aix/agitrack
8
+ Project-URL: Repository, https://github.com/core-aix/agitrack
9
+ Requires-Python: >=3.10
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Requires-Dist: prompt_toolkit>=3.0.52
13
+ Requires-Dist: pyte>=0.8.2
14
+ Requires-Dist: watchdog>=6.0
15
+ Dynamic: license-file
16
+
17
+ # aGiTrack
18
+
19
+ aGiTrack stands for agent + git. It is an interactive Python CLI that wraps coding-agent command line tools and Git so agentic code changes are committed with traceable metadata.
20
+
21
+ aGiTrack supports OpenCode and Claude (Claude Code) as interchangeable backends. Every aGiTrack feature works the same regardless of the selected backend.
22
+
23
+
24
+ ## Requirements
25
+
26
+ aGiTrack needs **git** and at least one backend CLI — [Claude Code](https://docs.claude.com/en/docs/claude-code) or [OpenCode](https://opencode.ai) — on your `PATH`. The dashboard's committer view additionally uses the **GitHub CLI (`gh`)** to resolve commit authors to their GitHub logins: install it from [cli.github.com](https://cli.github.com) and run `gh auth login`. `gh` is optional — without it the dashboard still works and falls back to merging committer identities by email and no-reply login.
27
+
28
+ ## Install
29
+
30
+ ```bash
31
+ pip install agitrack
32
+ ```
33
+
34
+ This installs the `agitrack` command and the terminal UI dependency used for status bars and contextual command hints. The PyPI distribution, the importable package, and the command are all named `agitrack` (the legacy `agit` command name still works as an alias). Once installed, aGiTrack keeps itself up to date — see [Self-update](#self-update).
35
+
36
+ For local development, install from a checkout instead:
37
+
38
+ ```bash
39
+ python3 -m pip install -e .
40
+ ```
41
+
42
+
43
+ ## Usage
44
+
45
+ Run in the current repository:
46
+
47
+ ```bash
48
+ agitrack
49
+ ```
50
+
51
+ By default, `agitrack` runs in proxy mode: it launches the real backend TUI (OpenCode or Claude) in a pseudo-terminal, renders it through an internal terminal screen, and reserves a bottom status line for aGiTrack showing the session (and the base branch it merges into), the backend, the summarizer state, and the repository the agent is working on (the base repository path, home-abbreviated and elided from the left when space is tight). Press `Ctrl-G` to enter aGiTrack command mode (configurable via `menu_key` in `~/.agitrack/config.json` — see Configuration).
52
+
53
+ Run against another repository:
54
+
55
+ ```bash
56
+ agitrack --repo /path/to/repo
57
+ ```
58
+
59
+ Choose the backend (also saved as the global default for future runs):
60
+
61
+ ```bash
62
+ agitrack --backend claude
63
+ agitrack --backend opencode
64
+ ```
65
+
66
+ By default aGiTrack resumes the previous conversation for the repository. Start a fresh one instead with:
67
+
68
+ ```bash
69
+ agitrack --new-session
70
+ ```
71
+
72
+ Run without a worktree (the agent edits the current branch directly, so changes are visible live as it works):
73
+
74
+ ```bash
75
+ agitrack --no-worktree
76
+ ```
77
+
78
+ This is for single-session use: there's no isolation or auto-integration, and concurrent sessions are unsafe in this mode (starting a new session is blocked). Set `"use_worktrees": false` in `~/.agitrack/config.json` to make it the default; `--no-worktree` always wins.
79
+
80
+
81
+
82
+ On the first run, aGiTrack asks which backend should be the default (listed alphabetically, with each backend's install status). If the chosen backend's CLI is not installed, aGiTrack shows install instructions and lets you install it or pick a different one. The choice is saved in `~/.agitrack/config.json` (`default_backend`) and reused for future runs. You can also switch backends mid-session with the `agent-backend` command below.
83
+
84
+ In proxy mode (default), press `Ctrl-G`, then type one of these aGiTrack commands:
85
+
86
+ ```text
87
+ session switch / start (own worktree) / stop a live session
88
+ agent-backend switch backend (opencode|claude); shows a picker
89
+ summarizer toggle summarization on/off, set model, show status
90
+ git-base-branch switch the branch sessions integrate into
91
+ git-status show git status
92
+ git-stage review and stage untracked files
93
+ git-unstaged show intentionally unstaged files
94
+ git-user-commit create a user commit
95
+ update check for / install an aGiTrack self-update
96
+ exit exit (with confirmation)
97
+ ```
98
+
99
+ aGiTrack tracks one session per repository and stays pinned to the session it launched (so it does not drift to other sessions you open). Use the `session` command (`Ctrl-G`, then `session`) to start a new session, switch the tracked session to another existing one, or sync tracking to the most recently active session — for example after starting a new conversation inside the backend's own TUI. This works the same for all backends.
100
+
101
+ Only `session` starts with `s`, so `Ctrl-G` then `s` + Enter jumps straight to the session picker. The session menu marks each session `running` or `idle`. Git-specific commands share a `git-` prefix.
102
+
103
+
104
+
105
+ ## Dashboard
106
+
107
+ `agitrack --dashboard` (or `-d`) opens a **live, auto-refreshing web dashboard** of your repository — who and what wrote the code — served on `localhost` and opened in your browser. Every number is computed from commit metadata alone, so it's identical on every clone; nothing is sent anywhere.
108
+
109
+ ```bash
110
+ agitrack --dashboard # serve on localhost and open the browser (Ctrl-C to stop)
111
+ agitrack -d text # one-shot plain-text report instead (pipe it, paste it into an issue)
112
+ ```
113
+
114
+ ![The aGiTrack dashboard](https://raw.githubusercontent.com/core-aix/agitrack/main/docs/images/dashboard-v2.png)
115
+
116
+ - **aGiTrack-tracked AI vs non-tracked lines** — what the agents wrote (tracked by aGiTrack) versus everything else; it never claims a human wrote what the model did.
117
+ - **Filter live** — narrow the whole dashboard to one committer (merged to their GitHub ID), a backend, a model, or a time range.
118
+ - **Tokens, efficiency, and loop detection**, plus a commit log you can click to read the full message and jump to the commit on GitHub.
119
+
120
+ See [Repository dashboard](#repository-dashboard) below for the full breakdown.
121
+
122
+
123
+ ## Sharing sessions
124
+
125
+ You can share a full agent conversation with collaborators through the repo's git remote, and resume each other's sessions. It's **opt-in** — nothing is ever uploaded until you explicitly share a session. Both backends are supported: Claude shares its per-session transcript, and OpenCode shares its session via the built-in `opencode export`/`import`.
126
+
127
+ From the `session` menu (`Ctrl-G` → `session`) — where each session is also marked **⇪ shared** or **⇪ auto-share** if you've shared it:
128
+
129
+ - **Share this session** — publishes the current conversation to the remote. The first time, aGiTrack asks you to confirm; a transcript can contain file contents, command output, and secrets, so **review what's in the session before sharing** (aGiTrack also applies best-effort secret masking, but that is *not* a guarantee — don't rely on it). You can choose to keep the shared copy **updated automatically**, or re-share manually.
130
+ - **Resume a shared session** — lists teammates' sessions as `<github-id>/<name>` and continues one in a fresh session worktree.
131
+ - **Manage shared sessions** — see what *you've* shared (with "up to date" vs "local has newer turns"), push the latest turns, toggle auto-update, or unshare.
132
+
133
+ Shared sessions also appear in the [dashboard](#dashboard) under **shared sessions**. The storage model and the guarantees behind these actions are described under [Session tracking](#session-tracking).
134
+
135
+
136
+ ## How It Works
137
+
138
+ ### Backends
139
+
140
+ aGiTrack drives an external coding agent rather than calling a model directly. OpenCode and Claude (Claude Code) are interchangeable backends, and every aGiTrack feature behaves the same regardless of which is selected. The per-repository backend is recorded in state; the user-wide default lives in `~/.agitrack/config.json`.
141
+
142
+ aGiTrack recovers what to commit from the backend's own session record: `opencode export` for OpenCode, and the session transcript under `~/.claude/projects/` for Claude. In JSON mode it instead invokes the backend non-interactively per prompt and captures the final response.
143
+
144
+ ### Session tracking
145
+
146
+ aGiTrack tracks exactly one backend session per repository and stays pinned to the session it launched, so it does not drift to other conversations you open in the backend. On startup it baselines the tracked session, so token metadata and the interaction trace only cover turns that happen after aGiTrack starts watching — resuming an old conversation does not re-commit its history.
147
+
148
+ Use the `session` command to start a new session, switch the tracked session to another existing one, or sync tracking to the most recently active session (for example after starting a fresh conversation inside the backend's own TUI). The session menu marks each session `running` or `idle`. A new session is given a friendly random word as its default name (e.g. `maple`, `harbor`) — easier to remember than `session-1` and, since sessions are shared as `<github-id(s)>/<name>`, far less likely to clash with a collaborator's; you can accept it or type your own at the prompt, and rename later.
149
+
150
+ **Sharing a session across machines and collaborators** (the [Sharing sessions](#sharing-sessions) actions above) builds on the same per-session transcript, with this storage model and these guarantees. **Only sessions you explicitly share are tracked here** — a session you haven't shared stays purely local: it is never uploaded, listed, or tracked in the shared store, and nothing about it leaves your machine.
151
+
152
+ - **Only the latest copy is kept — git history never grows.** Shared sessions live on a dedicated custom ref `refs/agitrack/shared-sessions`, stored as a *single, parent-less (orphan) commit* built with `git commit-tree` and no parent. Every update (manual or auto) **rewrites** that ref to a brand-new orphan commit holding only the current snapshot. So no matter how many times a session is updated, the ref is always one commit deep — it never accumulates history or bloats the repo, and **unsharing removes the session completely** (there is no older commit anywhere that still holds it). This deliberately avoids a normal commit chain, whose whole point is to *retain* every past version — exactly what we don't want for a privacy-sensitive transcript.
153
+ - **Updates still transmit only the diff (git deltifies at the pack level, not via history).** Skipping commit history does *not* mean re-uploading the whole transcript each time. Git delta-compresses by **content similarity within a packfile**, and a push builds a *thin pack* that deltas new objects against objects the remote **already has** — independent of whether the commits share any ancestry. So an orphan-commit rewrite still pushes only the turns that changed. The one requirement is that the *previous* version still exist locally as a delta base at push time, so aGiTrack **defers reclaiming it until after the push** (rather than deleting it first, which would have forced a full re-upload every share — costly for an append-only transcript that is re-shared or auto-shared as it grows). Right after the push succeeds, the now-unreferenced previous objects are reclaimed, keeping local storage bounded to just the latest snapshot. Concurrent updates are made safe with `git push --force-with-lease` (each contributor edits only their own subtree), retrying after a sync if the lease is stale.
154
+ - **One session is one entry, named by its contributor set.** A shared session is displayed as `<id1>+<id2>/<name>` — the github ids of everyone who has shared it, sorted (so order never matters), before its name. It is stored once, keyed by its lineage origin (the first sharer's id + name), not by whoever last pushed. So when you resume a teammate's `alice/fix-parser` and share your continuation, it becomes `alice+you/fix-parser` — the **same** entry, now co-owned — rather than a second `you/fix-parser`. Moving a session back and forth between your own machines likewise keeps updating that one entry instead of spawning new names.
155
+ - **Resuming continues the same conversation locally.** Picking a shared session downloads its transcript into your local backend store (Claude's project dir, or via `opencode import`) and continues it in a fresh worktree — using whichever backend recorded it, regardless of which one you're currently on. Your turns are appended to your local copy; sharing again updates that one entry (above), guarded by newest-wins below. Choosing **Keep both** instead deliberately *forks* a separate copy under a new id — a new, independent lineage published as `<you>/<name>` of its own.
156
+ - **Auto-update rides your commits.** When a session is set to auto-update, aGiTrack re-pushes the latest turns **at commit time** (in the background, only when the content changed) rather than on a busy timer — so it won't hammer the remote. The opt-in is remembered across aGiTrack runs.
157
+ - **Newest wins — a behind machine can't rewind the shared copy.** Transcripts only grow (turns are appended), so aGiTrack compares conversation length on both ends. Sharing from a machine whose copy is *behind* the shared one is refused (it would erase newer turns), and resuming never replaces a local copy with an *older* shared one — it tells you the local one is newer and keeps it by default. This keeps the same session consistent as you move between computers, instead of a stale machine (or its auto-update) dragging everyone back to an earlier state.
158
+ - **No manual git needed.** The Resume menu and the dashboard sync the shared ref for you. (A plain `git clone`/`git fetch` does *not* pull custom refs, so teammates rely on those menus; to inspect by hand: `git ls-remote origin 'refs/agitrack/*'`.) Because it's a custom ref, not a branch or tag, **it won't appear on GitHub's web UI**.
159
+ - **Scoped and bounded.** Sessions are namespaced by the repo's root commit, so only *this* repo's sessions are ever uploaded or listed; each contributor keeps their most-recent few, with older ones auto-pruned.
160
+
161
+ ### Worktrees and branches
162
+
163
+ To let sessions run without stepping on each other or on your working tree, each aGiTrack session runs in its own git worktree under `.agitrack/worktrees/<name>`, created *detached* at the base branch — a session has no branch of its own. Work within a session is committed on per-turn branches named `agitrack/<backend>/<name>/t<turn>`, created lazily on the first commit of each turn; once a turn is integrated its branch is deleted and the worktree is detached at the new base again. All aGiTrack-managed branches live under the `agitrack/` prefix so they are easy to recognize for cleanup and never collide with your own branches.
164
+
165
+ The base working tree (the branch you launched from) is only ever advanced by **integration**: aGiTrack merges a session's pending commits back into the base branch rather than committing onto it directly. A single-writer lock ensures only one aGiTrack process auto-commits or integrates at a time, so concurrent sessions stay consistent.
166
+
167
+ ### Integration and startup recovery
168
+
169
+ When a session's commits are merged into the base branch and the merge has conflicts, the agent backend resolves them, and the resolution is recorded as an `<aGiTrack-merge>` commit listing the base commits it was resolved against.
170
+
171
+ On startup, aGiTrack reconciles worktrees left behind by previous runs: it integrates any pending commits into the base branch and then deletes the worktree. Worktrees that cannot be integrated cleanly (a conflict, or uncommitted changes) are kept so no work is lost. The backend conversation itself persists (keyed by the worktree path) and stays resumable.
172
+
173
+ ### Commit message format
174
+
175
+ aGiTrack commit messages use a consistent Markdown-style structure. The first line is the subject (prefixed with `<aGiTrack>` for agent commits — including the cover commits placed on top of backend-made commits — `<aGiTrack-merge>` for agent-resolved merges, or left plain for user commits). When summarization is enabled the summary leads the message: its first line is the subject and the rest is the first paragraph of the body. The rest of the body is organized into `#` sections — `# Prompts` (when a summary takes the subject), `# Interaction Trace`, `# aGiTrack Metadata` — with `## User` / `## Agent` subsections inside the interaction trace. Commits are written with `git commit -F -` (no editor), so the `#` lines are preserved rather than stripped as git comments. Secrets and terminal escape sequences are masked out of subjects and trace bodies before committing.
176
+
177
+ Because the conversation is recorded in commit messages, aGiTrack shows a privacy warning at startup — never enter passwords, API keys, or other sensitive information in the chat — which must be acknowledged to continue (skipped when there is no terminal to acknowledge from).
178
+
179
+ ### Summarization
180
+
181
+ When summarization is enabled (the default), aGiTrack runs a second LLM stream alongside the coding session to preserve design context that would otherwise be lost to session compaction or terse commit subjects:
182
+
183
+ - **Commit summaries** — each agent commit gets an LLM-written summary of what changed and why. The summary leads the commit message: its first line becomes the subject and the rest follows as the first paragraph of the body (the prompts that used to head the message move to `# Prompts`); it is also stored as a git note in the `agitrack/commit-summary` namespace.
184
+ - **Session summaries** — a rolling narrative of the session (goals, architectural decisions, design evolution) is updated on every commit and attached as a git note in the `agitrack/session-summary` namespace.
185
+ - **Pre-compaction capture** — when you run `/compact` in the backend, aGiTrack first exports the full session transcript and folds it into the session summary, so compaction does not lose the conversation's context.
186
+
187
+ Because summaries are git notes, they travel with the repository and can be read independently of commit messages:
188
+
189
+ ```bash
190
+ git notes --ref agitrack/commit-summary show <commit>
191
+ git notes --ref agitrack/session-summary show <commit>
192
+ ```
193
+
194
+ Summarization never blocks the session: commits are created immediately with a prompt-based subject, the summary is computed on a background worker (the status line shows "aGiTrack is summarizing commit ..."), and the commit message is then amended in place. The amend only happens while it is safe — the commit is still the latest, unintegrated, and nothing new is staged; integration waits for the summary up to `summary_wait_seconds` and then proceeds, in which case the summary is recorded in git notes only. The metadata records the summarization cost next to the session's own usage (`summary_model`, `summary_tokens_input`, `summary_tokens_output`).
195
+
196
+ The status bar shows whether summarization is active (`sum:on` / `sum:off`). Use the `summarizer` command (`Ctrl-G`, then `summarizer`, or `:summarizer` in JSON mode) to toggle it (`summarizer on|off`), set the summarization model (`summarizer model`), or show the current status; changes persist to the repository-local `.agitrack/config.json` (see Configuration).
197
+
198
+
199
+ ### Commit Behavior
200
+
201
+ - Tracked modifications and deletions are staged with `git add -u`.
202
+ - New untracked files require confirmation before staging.
203
+ - Declined untracked files are remembered in repository-local `.agitrack/state.json`.
204
+ - Agent commits use the `<aGiTrack>` tag and include the full interaction trace since the last code-changing commit.
205
+ - Agent commit metadata includes context token count and generated token usage accumulated since the last code-changing commit.
206
+ - Token figures are read directly from the backend's session transcript (each assistant message's reported usage) and broken out by category: `input`, `output`, `cache_read`, `cache_write`, and (when the backend reports it) `reasoning`. For Claude, the recorded output count already includes extended-thinking and tool-call tokens. Sub-agent/sidechain turns are counted separately under the matching `subagent_*` categories rather than dropped. Each category is recorded only when the backend reports a non-zero value, so backends that omit a field (e.g. OpenCode does not expose sub-agent usage) simply have no line for it.
207
+ - The categories are **non-overlapping**: `output` counts only the main agent's generated tokens, and `subagent_output` counts only sub-agent generated tokens — neither includes the other, so nothing is double-counted. For a grand total of generated tokens, sum the matching pairs yourself (e.g. `output + subagent_output`, and `reasoning + subagent_reasoning` for OpenCode). The input side counts every token exactly once: `input` is all *fresh* input processed since the last commit — the uncached remainder plus the cache-creation tokens (so a first run's input reflects the full context instead of looking near zero next to the cache) — with `cache_write` kept as the "of which was written to the cache" breakdown. `cache_read` stays separate because those tokens were already counted as input when first processed; they are replayed from the cache and billed at a different rate.
208
+ - The figures should still be treated as a lower bound: any consumption the backend does not record in the transcript (e.g. internal compaction, retried requests, or usage a provider omits) is not captured, so actual tokens consumed may be higher than reported.
209
+ - Proxy mode baselines the continued backend session on startup so token metadata only includes turns after aGiTrack starts tracking new changes.
210
+ - Proxy mode preserves the backend's selected model in commit metadata when it can be read from session data.
211
+ - User commits use the user-provided subject and include aGiTrack metadata.
212
+ - Commits are created only when staged changes exist.
213
+ - If the backend commits on its own (e.g. the agent runs `git commit` itself, or a hook does), aGiTrack never rewrites those commits — their hashes stay exactly what the agent may already have reported in PR or issue comments. Instead, once the turn finishes, aGiTrack adds a *cover commit* on top carrying the interaction trace and metadata: a merge-shaped commit in the GitHub PR merge style, whose tree is the backend head's tree and whose parents are the turn's start and the backend's head, so `git log --first-parent` reads turn-by-turn while the backend's own commits remain reachable via the second parent. The `covered_commits` metadata line records the hashes of the backend-made commits the cover accounts for; when aGiTrack also has uncommitted changes to commit, its own (regular) commit carries that line instead.
214
+
215
+ ### Repository dashboard
216
+
217
+ `agitrack --dashboard` (or `-d`) opens a live web dashboard of repository metrics computed entirely from the aGiTrack metadata in commit messages — no extra state, so the numbers are identical on every clone. It is served on `localhost`, opens in your browser, and **auto-refreshes** (the page polls the server, which recomputes from `git log` on each request), so you can watch metrics update as an agent commits. Press Ctrl-C to stop.
218
+
219
+ - **Coverage**: how many commits are aGiTrack-tracked (agent commits, backend-made commits covered by an aGiTrack cover commit, agent-resolved merges, user commits, and aGiTrack's own integration merges) versus non-tracked.
220
+ - **Code changes**: lines added/removed split two ways — **aGiTrack-tracked AI** (agent commits + the backend-made commits an aGiTrack cover commit accounts for + agent-resolved merges) and **non-tracked** (everything else: user commits, plain commits with no aGiTrack metadata, and squash/PR-merge commits whose message concatenates several metadata blocks and so can't be cleanly attributed). There is deliberately no "human" category — even a user-made commit can contain lines an agent produced off the record, so the only honest claim is whether aGiTrack tracked the lines as AI. Cover commits are merges and contribute no line counts of their own, so a turn's lines are never double-counted.
221
+ - **aGiTrack-ops**: the integration merge commits aGiTrack makes itself (e.g. bringing base into a session branch) are shown as their own class, not lumped into non-tracked. They carry no diff, so they add no lines.
222
+ - **Squashed commits**: when several aGiTrack commits are squashed into one (a squash- or PR-merge concatenates their metadata blocks — git flattens this even across multiple rounds of squashing), the dashboard parses every original back out, so their tokens and per-model/backend usage are still counted instead of lost in the aggregate. In the web commit log such a commit is tagged `⧉ N squashed` and expands on click into its original commits, each itself expandable to its full message.
223
+ - **Tokens**: totals per category (input, output, reasoning, cache read/write, sub-agents, summarizer) and an efficiency ratio — AI-changed lines per 1k output tokens.
224
+ - **Breakdowns** by backend, by model (a cover commit's bucket includes the lines of the backend-made commits it covers), and by committer. Committer identities are merged to **GitHub IDs** via the `gh` CLI when available (every commit GitHub knows is keyed by its real login); without `gh` it falls back to merging by email and no-reply login. Each committer's lines are split into the aGiTrack-tracked AI they drove versus non-tracked.
225
+ - **Possible loops**: runs of three or more consecutive turns with near-identical prompts (or the same prompt repeated within one turn's trace), with the output tokens they consumed — a sign the conversation is going in circles.
226
+
227
+ The web page (styled like the [project page](https://github.com/core-aix/agitrack/tree/main/docs)) lets you **filter live** — narrow the whole dashboard to one committer or view the entire team, slice by backend or model, or restrict to a **time range** (presets or a custom from/to). The server recomputes the metrics for each filter, and the **commit log is paginated** (fetched a page at a time), so the browser never holds the whole history — memory stays bounded no matter how big the repo is. Each log line shows per-line token metrics; clicking a line opens the full commit message **rendered as Markdown** with a link to the commit on GitHub, and a squash expands into its original commits (each itself expandable). Agent commits also record when the AI-driven conversation started and ended (`agent_started_at` / `agent_ended_at` in the metadata block).
228
+
229
+ `agitrack --dashboard text` (or `-d text`) prints the same metrics as a one-shot plain-text report instead of serving — handy for piping or pasting into an issue.
230
+
231
+ The dashboard is read-only in either form: it never commits, never prompts, and skips the privacy acknowledgment.
232
+
233
+ ### Self-update
234
+
235
+ aGiTrack keeps itself current. On startup, and then about every five minutes while you work, it checks whether a newer aGiTrack is available:
236
+
237
+ - **Source-linked install** (the editable `pip install -e .` from a git checkout): it compares three commit hashes — the one the **running** process loaded, the checkout's **local** `HEAD`, and the **remote** target's tip — and offers an update whenever either the local disk or the remote carries newer code. The remote target is the current branch's upstream, or, when the branch tracks nothing (aGiTrack runs on session worktree branches), `origin`'s default branch. When you pick `update` from the menu it runs a **fresh** check on the spot, so a teammate's push or a just-pulled local update is reflected immediately rather than waiting for the next periodic check.
238
+ - **Package install** (a wheel from a package index): it compares the installed version with the latest published one.
239
+
240
+ If an update exists, aGiTrack prompts you at startup and shows a notice during a session (run the `update` command from the `Ctrl-G` menu to act on it). When you accept, aGiTrack waits until **every session has finished and all commits are integrated**, installs the update, then restarts itself automatically. It never interrupts a merge: while any session is resolving a merge/conflict, the notice is held back and an accepted update is deferred until the merge is done. A source update **merges** the upstream branch into the checkout — a clean checkout fast-forwards and a diverged one (your own commits, or aGiTrack's session integrations) gets a normal merge — so it pulls in new code without discarding local work; if the checkout has uncommitted changes it's skipped with a message, and if the merge hits a genuine conflict aGiTrack aborts it (leaving the source clean) and tells you automatic update isn't possible until you resolve it. When only the running process is behind the on-disk code, no download happens — aGiTrack just restarts to load it. Choose "Stop checking for updates" — or set `"check_for_updates": false` in `~/.agitrack/config.json` — to turn the checks off; tune the cadence with `timings.update_check_seconds`.
241
+
242
+
243
+ Proxy mode launches the backend's native TUI directly and recovers session metadata for automatic agent commits — via `opencode export` for OpenCode, or by reading the session transcript under `~/.claude/projects/` for Claude.
244
+
245
+ ## Advanced Usage
246
+
247
+ Show aGiTrack diagnostic messages:
248
+
249
+ ```bash
250
+ agitrack --verbose
251
+ ```
252
+
253
+ Use the structured JSON fallback mode:
254
+
255
+ ```bash
256
+ agitrack --mode json
257
+ ```
258
+
259
+ JSON mode invokes the backend non-interactively for each prompt (`opencode run --format json` or `claude -p --output-format json`) so aGiTrack can capture the final response and create traceable commits.
260
+
261
+ In JSON mode, plain text is sent to the active agent backend:
262
+
263
+ ```text
264
+ > fix the parser bug
265
+ ```
266
+
267
+ JSON mode aGiTrack commands use `:` so backend-native `/` input is not intercepted:
268
+
269
+ ```text
270
+ :help show commands
271
+ :status show git status
272
+ :user-commit create a user commit
273
+ :stage review and stage untracked files
274
+ :unstaged show intentionally unstaged files
275
+ :agent-backend <backend> switch backend (opencode|claude)
276
+ :exit exit
277
+ ```
278
+
279
+ In JSON mode, aGiTrack shows a bottom status bar with the active backend, target repo, model, and unstaged-new-file count. Typing `:` shows aGiTrack command completions. Typing `/` shows common backend command completions, and slash commands are forwarded to the backend rather than handled by aGiTrack.
280
+
281
+ ### Scripted runs and the demo
282
+
283
+ `--prompt` runs JSON mode fully scripted: each prompt is sent to the backend in order (lines starting with `:` are aGiTrack commands), every turn that changes files becomes a commit, and aGiTrack exits when the prompts are done.
284
+
285
+ ```bash
286
+ agitrack --repo path/to/repo --backend claude \
287
+ --prompt "add input validation to parse()" \
288
+ --prompt ":status" \
289
+ --permission-mode acceptEdits
290
+ ```
291
+
292
+ Scripted runs never block on a question: the privacy warning is printed without waiting for acknowledgment, and new untracked files are staged automatically (with a notice) instead of being reviewed interactively. The same non-interactive defaults apply when prompts are piped to `agitrack --mode json` on stdin. Note that headless Claude needs permission to edit files — forward `--permission-mode acceptEdits` (or your preferred permission flags) through aGiTrack as shown above; OpenCode's `run` mode edits by default.
293
+
294
+ `scripts/demo.sh` is a self-contained showcase built on this: it creates a fresh repository in a temporary directory, has the agent write a small program and its tests through aGiTrack, and leaves the repository behind so you can inspect the `<aGiTrack>` commit history or continue interactively.
295
+
296
+ ```bash
297
+ scripts/demo.sh # drive the demo with claude
298
+ scripts/demo.sh --backend opencode # ... or with opencode
299
+ scripts/demo.sh --model haiku --dir /tmp/agitrack-demo
300
+ ```
301
+
302
+ ### Forwarding arguments to the backend
303
+
304
+ aGiTrack does not reduce the backend's own functionality: any argument it doesn't recognize is forwarded verbatim to the backend CLI (`claude` / `opencode`).
305
+
306
+ ```bash
307
+ agitrack --backend opencode --port 12345 # --port 12345 goes to opencode
308
+ ```
309
+
310
+ Use `--` to forward an argument that aGiTrack also defines (e.g. `--verbose`), or to pass a bare prompt:
311
+
312
+ ```bash
313
+ agitrack -- --verbose "fix the bug" # everything after -- goes to the backend
314
+ ```
315
+
316
+ aGiTrack's own flags (`--repo`, `--verbose`, `--mode`, `--backend`, `--new-session`, `--no-worktree`) bind to aGiTrack when they appear before `--`. Note that aGiTrack manages session selection itself, so forwarding session flags (`--resume`, `--session-id`, `--session`, `--continue`) may interfere with its session tracking — it warns when you do.
317
+
318
+ Help follows the same model: `agitrack --help` (or `-h`) prints aGiTrack's own options followed by the active backend's help, so one command documents both layers. To run only the backend's help, forward it explicitly: `agitrack -- --help`.
319
+
320
+
321
+
322
+ ## Configuration
323
+
324
+ Repository-local configuration can be stored in `.agitrack/config.json`:
325
+
326
+ ```json
327
+ {
328
+ "trace_turn_limit": 5,
329
+ "summarization_enabled": true,
330
+ "summarization_model": null
331
+ }
332
+ ```
333
+
334
+ `trace_turn_limit` controls the maximum number of recent user turns included in an agent commit body. The default is `5`.
335
+
336
+ `summarization_enabled` (default `true`) toggles the LLM summarization stream (see Summarization above). `summarization_model` sets the model the summarizer asks the backend to use; leave it unset (`null`) to use the backend's default model. Both keys can also be set user-wide in `~/.agitrack/config.json`; the repository-local value wins, and the `summarizer` command writes its changes here.
337
+
338
+ User-wide settings live in `~/.agitrack/config.json` (override the directory with `AGITRACK_CONFIG_DIR`):
339
+
340
+ ```json
341
+ {
342
+ "default_backend": "opencode",
343
+ "menu_key": "ctrl-g",
344
+ "sandbox": true,
345
+ "use_worktrees": true,
346
+ "timings": {
347
+ "base_poll_seconds": 3.0
348
+ }
349
+ }
350
+ ```
351
+
352
+ `default_backend` (`opencode` or `claude`) is used for repositories that have no backend recorded yet. It is updated whenever you pass `--backend` or switch backends with `agent-backend`.
353
+
354
+ `sandbox` (default `true`) confines the agent's writes to its own session worktree (via `sandbox-exec` on macOS), keeping the base repository and sibling worktrees read-only to the agent. Set it to `false` to disable confinement; when sandboxing is unavailable, aGiTrack instead warns when the base repository is edited while a session runs.
355
+
356
+ `use_worktrees` (default `true`) controls whether sessions run in isolated worktrees. Set it to `false` to run the agent directly on the current branch by default — the same behavior as `--no-worktree` (which always wins over the config). See the `--no-worktree` notes under Usage for the trade-offs.
357
+
358
+ `menu_key` sets the key that opens aGiTrack's command menu in proxy mode. The default is `ctrl-g`; any `ctrl-<letter>` works except keys the terminal or aGiTrack already uses (`ctrl-c` exit flow, `ctrl-h` Backspace, `ctrl-i` Tab, `ctrl-j`/`ctrl-m` Enter). An invalid value falls back to `ctrl-g`, so a typo can never lock you out of the menu. The status line and aGiTrack's messages show whichever key is configured.
359
+
360
+ `timings` tunes aGiTrack's polling and debounce intervals (all in seconds). Specify only the keys you want to change; anything omitted — or set to a non-positive / non-numeric value — keeps its default:
361
+
362
+ | Key | Default | What it controls |
363
+ | --- | --- | --- |
364
+ | `base_poll_seconds` | `3.0` | How often the base branch is re-checked for commits made outside aGiTrack (so worktrees pick them up). |
365
+ | `background_poll_seconds` | `2.0` | How often an idle background session is serviced (committed / integrated). |
366
+ | `file_stable_seconds` | `8.0` | Quiet period after a file change before an auto-commit. |
367
+ | `child_idle_seconds` | `4.0` | No backend output for this long counts as idle. |
368
+ | `parse_cooldown_seconds` | `10.0` | Minimum gap between agent-turn parses. |
369
+ | `base_edit_check_seconds` | `3.0` | How often aGiTrack warns about edits to the base repo when the sandbox is unavailable. |
370
+ | `cwd_check_seconds` | `3.0` | How often aGiTrack checks for the Claude resume-cwd drift bug. |
371
+ | `base_drift_check_seconds` | `2.0` | How often aGiTrack checks whether the base repo was switched to another branch outside aGiTrack. |
372
+ | `summary_wait_seconds` | `45.0` | How long integration waits for a background commit summary before proceeding without it. |
373
+
374
+
375
+ ## Contributing
376
+
377
+ Install dependencies and the optional git hooks:
378
+
379
+ ```bash
380
+ uv sync --group dev
381
+ make install-hooks
382
+ ```
383
+
384
+ This installs two hooks:
385
+
386
+ - **commit** — `ruff` (lint + format) and basic file hygiene, so commits stay fast.
387
+ - **push** — the full CI-equivalent gate (`ruff`, `mypy` vs the baseline, tests + coverage), so a push that would break CI fails locally first.
388
+
389
+ Run the same full gate by hand at any time:
390
+
391
+ ```bash
392
+ make check # or: ./scripts/check.sh
393
+ ```
394
+
395
+ This is the definition of "done" for a change — it mirrors CI exactly (`.github/workflows/ci.yml`).