messygit 0.2.1__tar.gz → 0.3.1__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.
@@ -0,0 +1 @@
1
+ {}
@@ -0,0 +1,64 @@
1
+ # Architecture
2
+
3
+ This document describes the purpose of each file in the `messygit` project.
4
+
5
+ ## Root
6
+
7
+ | File | Purpose |
8
+ | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
9
+ | `pyproject.toml` | Package metadata, dependencies (`anthropic`, `click`), build system (hatchling), and the `messygit` console script entrypoint. |
10
+ | `README.md` | User-facing documentation: install, usage, commands, and development instructions. |
11
+ | `.gitignore` | Keeps `.venv/`, `__pycache__/`, `dist/`, and `*.egg-info/` out of version control. |
12
+ | `.github/workflows/publish.yml` | GitHub Actions workflow for publishing the package. |
13
+
14
+ ## `messygit/` (Python package)
15
+
16
+ | File | Purpose |
17
+ | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
18
+ | `__init__.py` | Marks the directory as a Python package (empty). |
19
+ | `cli.py` | Interactive REPL entrypoint. Displays an ASCII banner, runs a prompt loop, and dispatches commands: `add`, `commit`, `push`, `config`, `show`, `suggest`, `help`, `quit`/`exit`. Orchestrates all other modules. Includes a threaded `Spinner` for loading animations. |
20
+ | `git.py` | All subprocess calls to `git`. Reads staged diffs (`git diff --cached -U0`), parses them into a compact changed-lines format, filters noise files, handles the large-diff fallback (stat summary + top-N most-changed files), and runs `git add`, `git commit`, and `git push`. |
21
+ | `llm.py` | Anthropic SDK integration. Creates the client with the resolved API key, calls `messages.create`, extracts the text response, and maps SDK exceptions (`AuthenticationError`, `PermissionDeniedError`, `BadRequestError`, billing 402) into user-friendly error classes. Also exposes helpers reused by `agent/agent.py`. |
22
+ | `config.py` | API key storage and resolution. Reads/writes `~/.messygit/config.json`, checks the `ANTHROPIC_API_KEY` env var, validates keys are non-empty, masks keys for display, and defines all user-facing error messages and exception classes. |
23
+ | `prompts.py` | System prompts and user prompt builder. Contains the Conventional Commits instructions (`COMMIT_SYSTEM_PROMPT`), the suggestion agent instructions (`SUGGESTION_SYSTEM_PROMPT`), and `build_user_prompt` which wraps staged changes into the user message sent to Claude. |
24
+
25
+ ## `messygit/agent/` (agentic tool-use subpackage)
26
+
27
+ | File | Purpose |
28
+ | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
29
+ | `tool.py` | `Tool` dataclass wrapping a Python callable with a name, description, and parameter schema. Provides `run()` to invoke the function and `to_schema()` to emit an Anthropic-compatible tool definition. |
30
+ | `tools.py` | Concrete tool instances available to agents: `run_git_tool` (allowlisted read-only git commands), `read_file_tool`, `list_directory_tool`, and `search_code_tool` (`git grep`). |
31
+ | `agent.py` | Generic agentic loop. Sends messages to Claude with tool definitions, processes `tool_use` response blocks by dispatching to matching `Tool` instances, appends results, and iterates up to `max_iterations`. Handles API errors identically to `llm.py`. |
32
+
33
+ ## Data flow
34
+
35
+ ```
36
+ User runs `messygit` → interactive REPL
37
+
38
+ ├── "add <files>" ──► git.py (git add)
39
+ ├── "push" ──► git.py (git push)
40
+ ├── "config <key>" ──► config.py (save API key)
41
+ ├── "show" ──► config.py (display masked key)
42
+
43
+ ├── "commit" ──► git.py (read staged diff, apply token budget)
44
+ │ │
45
+ │ ▼
46
+ │ llm.py (send context to Claude)
47
+ │ │ │
48
+ │ │ ├── config.py (resolve API key)
49
+ │ │ └── prompts.py (COMMIT_SYSTEM_PROMPT + user prompt)
50
+ │ ▼
51
+ │ cli.py (display message, prompt Y/n/e)
52
+ │ │
53
+ │ ▼
54
+ │ git.py (git commit -m "...")
55
+
56
+ └── "suggest" ──► agent/agent.py (agentic loop)
57
+ │ │
58
+ │ ├── config.py (resolve API key)
59
+ │ ├── prompts.py (SUGGESTION_SYSTEM_PROMPT)
60
+ │ └── agent/tools.py (run_git, read_file, list_directory)
61
+
62
+ cli.py (display suggestion)
63
+ ```
64
+
@@ -0,0 +1,215 @@
1
+ Metadata-Version: 2.4
2
+ Name: messygit
3
+ Version: 0.3.1
4
+ Summary: An AI-powered interactive git CLI with agentic tools for commits, code suggestions, and workflow automation.
5
+ License-Expression: MIT
6
+ Requires-Python: >=3.10
7
+ Requires-Dist: anthropic>=0.39.0
8
+ Requires-Dist: click>=8.0
9
+ Requires-Dist: rich>=13.0
10
+ Description-Content-Type: text/markdown
11
+
12
+ # messygit
13
+
14
+ **messygit** is an interactive CLI that turns messy git workflows into clean Conventional Commits — stage, commit, push, and get AI-powered project suggestions, all from one interface powered by [Claude](https://www.anthropic.com/api).
15
+
16
+ ## Why use it
17
+
18
+ - **Interactive REPL** — one command drops you into a persistent session where you can stage, commit, push, and more without leaving.
19
+ - **AI commit messages** — sends your staged diff to Claude and suggests a clean Conventional Commits subject line.
20
+ - **Project suggestions** — an AI agent inspects your repo and recommends concrete next steps.
21
+ - **Token usage & cost** — tracks the tokens each session uses and shows a rough cost estimate, with a one-command jump to billing.
22
+ - **Themed UI** — a colored startup animation and prompt you can recolor with the `theme` command.
23
+ - **Safe by default** — only the staged diff is sent to the model. Your API key is never printed in full.
24
+
25
+ ## Requirements
26
+
27
+ - **Python** 3.10 or newer
28
+ - **Git** (run inside a repository)
29
+ - An **Anthropic API key** with access to the Messages API
30
+
31
+ ## Installation
32
+
33
+ ```bash
34
+ pip install messygit
35
+ ```
36
+
37
+ ### Install from source
38
+
39
+ ```bash
40
+ cd messygit
41
+ python -m venv .venv
42
+ source .venv/bin/activate # Windows: .venv\Scripts\activate
43
+ pip install -e .
44
+ ```
45
+
46
+ ## API key
47
+
48
+ messygit resolves the key in this order:
49
+
50
+ 1. Environment variable **`ANTHROPIC_API_KEY`**
51
+ 2. Config file **`~/.messygit/config.json`**
52
+
53
+ You can set the key from within the messygit interface:
54
+
55
+ ```
56
+ messygit > config YOUR_ANTHROPIC_API_KEY
57
+ ```
58
+
59
+ ## Usage
60
+
61
+ ```bash
62
+ messygit
63
+ ```
64
+
65
+ This drops you into the interactive interface — an animated banner followed by a
66
+ status dashboard, then the prompt:
67
+
68
+ ```
69
+ mmm mmmm eeeeeee sssssss sssssss yy yy ggggggg ii tttttttt
70
+ mm mm mm mm ee ss ss yy yy gg ii tt
71
+ mm mmm mm eeeee sssssss sssssss yy gg ggg ii tt
72
+ mm mm ee ss ss yy gg gg ii tt
73
+ mm mm eeeeeee sssssss sssssss yy ggggg ii tt
74
+
75
+ repo messygit ⎇ main
76
+ status 3 staged · 2 modified
77
+ api key sk-ant-a...x3f2 (config)
78
+ model Haiku 4.5 $1 in · $5 out / 1M
79
+ tokens 0 used this session
80
+ ────────────────────────────────────────────────────────────
81
+ Type help for commands · quit to exit
82
+
83
+ messygit (main) ❯
84
+ ```
85
+
86
+ ### Commands
87
+
88
+ Commands are grouped on the `help` screen:
89
+
90
+ **git**
91
+
92
+ | Command | Description |
93
+ |---------|-------------|
94
+ | `add <file>` or `add .` | Stage files for commit |
95
+ | `commit` | Generate an AI commit message from staged changes, then commit / cancel / edit |
96
+ | `push` | Push commits to remote |
97
+
98
+ **messyagent**
99
+
100
+ | Command | Description |
101
+ |---------|-------------|
102
+ | `suggest` | Get AI-powered next-step suggestions for your project |
103
+
104
+ **account**
105
+
106
+ | Command | Description |
107
+ |---------|-------------|
108
+ | `config <key>` | Save your Anthropic API key to `~/.messygit/config.json` |
109
+ | `show` | Display a masked API key and its source |
110
+ | `model` or `model <name>` | Switch the Claude model (run `model` to list models and pricing) |
111
+ | `tokens` | Show this session's token usage and estimated cost, and open the billing console |
112
+
113
+ **app**
114
+
115
+ | Command | Description |
116
+ |---------|-------------|
117
+ | `todo` | Open your todo list in `$EDITOR` (saved to `~/.messygit/todo.md`) |
118
+ | `theme` or `theme <name>` | Change the UI color (run `theme` to list presets) |
119
+ | `help` | List available commands |
120
+ | `quit` / `exit` | Exit messygit |
121
+
122
+ ### Typical flow
123
+
124
+ ```
125
+ messygit > add .
126
+ Staged everything
127
+
128
+ messygit > commit
129
+ feat(cli): add interactive REPL with ASCII banner
130
+ Commit with this message? [y/n/e] y
131
+
132
+ messygit > push
133
+ ```
134
+
135
+ > Tip: run `suggest` for AI next-step ideas, or `theme` to recolor the UI.
136
+
137
+ ### Commit message style
138
+
139
+ The model follows **Conventional Commits**: `type(scope): description`
140
+
141
+ Allowed types: `feat`, `fix`, `docs`, `style`, `refactor`, `test`, `chore`. Subjects are one line, imperative, lowercase, no trailing period.
142
+
143
+ ### Token usage & cost
144
+
145
+ messygit tracks the tokens used by AI commands (`commit`, `suggest`) for the current session and shows a running total after each call. Run `tokens` for a breakdown and a one-key jump to the Anthropic billing console:
146
+
147
+ ```
148
+ messygit > tokens
149
+ ╭─ token usage ─────────────────────────────╮
150
+ │ used 8,420 tokens │
151
+ │ 6,200 in · 2,220 out │
152
+ │ requests 2 │
153
+ │ est cost ≈ $0.02 │
154
+ ╰───────────────────────────────────────────╯
155
+ ```
156
+
157
+ The cost is a **rough estimate** at the selected model's [pricing](https://www.anthropic.com/pricing). The Anthropic API does not expose remaining account credits, so usage and cost are measured per session only.
158
+
159
+ ### Choosing a model
160
+
161
+ messygit defaults to **Claude Haiku 4.5** (fast and cheap). Use `model` to list the available models and their token pricing, or `model <name>` to switch (your choice persists in `~/.messygit/config.json`):
162
+
163
+ ```
164
+ messygit > model
165
+ Available models — usage: model <name>
166
+ ● haiku Haiku 4.5 $1 in · $5 out / 1M (current)
167
+ sonnet Sonnet 4.6 $3 in · $15 out / 1M
168
+ opus Opus 4.8 $5 in · $25 out / 1M
169
+
170
+ messygit > model opus
171
+ ! Opus 4.8 costs more than Haiku 4.5 ($5 in · $25 out / 1M vs $1 in · $5 out / 1M). Token usage will be billed at the higher rate.
172
+ Switch anyway? [y/N]:
173
+ ```
174
+
175
+ Switching to a **more expensive** model prompts for confirmation first. The session cost estimate prices each request at the model used for it, so it stays accurate even if you switch mid-session.
176
+
177
+ ## Publishing to PyPI
178
+
179
+ This project uses GitHub Actions with [PyPI trusted publishing](https://docs.pypi.org/trusted-publishers/) — no API tokens needed in your repo.
180
+
181
+ ### One-time setup
182
+
183
+ 1. Go to your project on [pypi.org](https://pypi.org/manage/project/messygit/settings/publishing/)
184
+ 2. Add a **Trusted Publisher**:
185
+ - **Owner:** your GitHub username
186
+ - **Repository:** `messygit`
187
+ - **Workflow name:** `publish.yml`
188
+ - **Environment:** leave blank
189
+
190
+ ### To release a new version
191
+
192
+ 1. Bump `version` in `pyproject.toml`
193
+ 2. Commit and push
194
+ 3. Create a GitHub release:
195
+
196
+ ```bash
197
+ git tag v0.2.0
198
+ git push origin v0.2.0
199
+ ```
200
+
201
+ 4. Go to GitHub → Releases → Draft a new release → select the tag → Publish
202
+
203
+ The workflow at `.github/workflows/publish.yml` will automatically build and upload to PyPI.
204
+
205
+ ### Manual publish (without CI)
206
+
207
+ ```bash
208
+ rm -rf dist/
209
+ python -m build
210
+ twine upload dist/*
211
+ ```
212
+
213
+ ## License
214
+
215
+ MIT (see `pyproject.toml`).
@@ -0,0 +1,204 @@
1
+ # messygit
2
+
3
+ **messygit** is an interactive CLI that turns messy git workflows into clean Conventional Commits — stage, commit, push, and get AI-powered project suggestions, all from one interface powered by [Claude](https://www.anthropic.com/api).
4
+
5
+ ## Why use it
6
+
7
+ - **Interactive REPL** — one command drops you into a persistent session where you can stage, commit, push, and more without leaving.
8
+ - **AI commit messages** — sends your staged diff to Claude and suggests a clean Conventional Commits subject line.
9
+ - **Project suggestions** — an AI agent inspects your repo and recommends concrete next steps.
10
+ - **Token usage & cost** — tracks the tokens each session uses and shows a rough cost estimate, with a one-command jump to billing.
11
+ - **Themed UI** — a colored startup animation and prompt you can recolor with the `theme` command.
12
+ - **Safe by default** — only the staged diff is sent to the model. Your API key is never printed in full.
13
+
14
+ ## Requirements
15
+
16
+ - **Python** 3.10 or newer
17
+ - **Git** (run inside a repository)
18
+ - An **Anthropic API key** with access to the Messages API
19
+
20
+ ## Installation
21
+
22
+ ```bash
23
+ pip install messygit
24
+ ```
25
+
26
+ ### Install from source
27
+
28
+ ```bash
29
+ cd messygit
30
+ python -m venv .venv
31
+ source .venv/bin/activate # Windows: .venv\Scripts\activate
32
+ pip install -e .
33
+ ```
34
+
35
+ ## API key
36
+
37
+ messygit resolves the key in this order:
38
+
39
+ 1. Environment variable **`ANTHROPIC_API_KEY`**
40
+ 2. Config file **`~/.messygit/config.json`**
41
+
42
+ You can set the key from within the messygit interface:
43
+
44
+ ```
45
+ messygit > config YOUR_ANTHROPIC_API_KEY
46
+ ```
47
+
48
+ ## Usage
49
+
50
+ ```bash
51
+ messygit
52
+ ```
53
+
54
+ This drops you into the interactive interface — an animated banner followed by a
55
+ status dashboard, then the prompt:
56
+
57
+ ```
58
+ mmm mmmm eeeeeee sssssss sssssss yy yy ggggggg ii tttttttt
59
+ mm mm mm mm ee ss ss yy yy gg ii tt
60
+ mm mmm mm eeeee sssssss sssssss yy gg ggg ii tt
61
+ mm mm ee ss ss yy gg gg ii tt
62
+ mm mm eeeeeee sssssss sssssss yy ggggg ii tt
63
+
64
+ repo messygit ⎇ main
65
+ status 3 staged · 2 modified
66
+ api key sk-ant-a...x3f2 (config)
67
+ model Haiku 4.5 $1 in · $5 out / 1M
68
+ tokens 0 used this session
69
+ ────────────────────────────────────────────────────────────
70
+ Type help for commands · quit to exit
71
+
72
+ messygit (main) ❯
73
+ ```
74
+
75
+ ### Commands
76
+
77
+ Commands are grouped on the `help` screen:
78
+
79
+ **git**
80
+
81
+ | Command | Description |
82
+ |---------|-------------|
83
+ | `add <file>` or `add .` | Stage files for commit |
84
+ | `commit` | Generate an AI commit message from staged changes, then commit / cancel / edit |
85
+ | `push` | Push commits to remote |
86
+
87
+ **messyagent**
88
+
89
+ | Command | Description |
90
+ |---------|-------------|
91
+ | `suggest` | Get AI-powered next-step suggestions for your project |
92
+
93
+ **account**
94
+
95
+ | Command | Description |
96
+ |---------|-------------|
97
+ | `config <key>` | Save your Anthropic API key to `~/.messygit/config.json` |
98
+ | `show` | Display a masked API key and its source |
99
+ | `model` or `model <name>` | Switch the Claude model (run `model` to list models and pricing) |
100
+ | `tokens` | Show this session's token usage and estimated cost, and open the billing console |
101
+
102
+ **app**
103
+
104
+ | Command | Description |
105
+ |---------|-------------|
106
+ | `todo` | Open your todo list in `$EDITOR` (saved to `~/.messygit/todo.md`) |
107
+ | `theme` or `theme <name>` | Change the UI color (run `theme` to list presets) |
108
+ | `help` | List available commands |
109
+ | `quit` / `exit` | Exit messygit |
110
+
111
+ ### Typical flow
112
+
113
+ ```
114
+ messygit > add .
115
+ Staged everything
116
+
117
+ messygit > commit
118
+ feat(cli): add interactive REPL with ASCII banner
119
+ Commit with this message? [y/n/e] y
120
+
121
+ messygit > push
122
+ ```
123
+
124
+ > Tip: run `suggest` for AI next-step ideas, or `theme` to recolor the UI.
125
+
126
+ ### Commit message style
127
+
128
+ The model follows **Conventional Commits**: `type(scope): description`
129
+
130
+ Allowed types: `feat`, `fix`, `docs`, `style`, `refactor`, `test`, `chore`. Subjects are one line, imperative, lowercase, no trailing period.
131
+
132
+ ### Token usage & cost
133
+
134
+ messygit tracks the tokens used by AI commands (`commit`, `suggest`) for the current session and shows a running total after each call. Run `tokens` for a breakdown and a one-key jump to the Anthropic billing console:
135
+
136
+ ```
137
+ messygit > tokens
138
+ ╭─ token usage ─────────────────────────────╮
139
+ │ used 8,420 tokens │
140
+ │ 6,200 in · 2,220 out │
141
+ │ requests 2 │
142
+ │ est cost ≈ $0.02 │
143
+ ╰───────────────────────────────────────────╯
144
+ ```
145
+
146
+ The cost is a **rough estimate** at the selected model's [pricing](https://www.anthropic.com/pricing). The Anthropic API does not expose remaining account credits, so usage and cost are measured per session only.
147
+
148
+ ### Choosing a model
149
+
150
+ messygit defaults to **Claude Haiku 4.5** (fast and cheap). Use `model` to list the available models and their token pricing, or `model <name>` to switch (your choice persists in `~/.messygit/config.json`):
151
+
152
+ ```
153
+ messygit > model
154
+ Available models — usage: model <name>
155
+ ● haiku Haiku 4.5 $1 in · $5 out / 1M (current)
156
+ sonnet Sonnet 4.6 $3 in · $15 out / 1M
157
+ opus Opus 4.8 $5 in · $25 out / 1M
158
+
159
+ messygit > model opus
160
+ ! Opus 4.8 costs more than Haiku 4.5 ($5 in · $25 out / 1M vs $1 in · $5 out / 1M). Token usage will be billed at the higher rate.
161
+ Switch anyway? [y/N]:
162
+ ```
163
+
164
+ Switching to a **more expensive** model prompts for confirmation first. The session cost estimate prices each request at the model used for it, so it stays accurate even if you switch mid-session.
165
+
166
+ ## Publishing to PyPI
167
+
168
+ This project uses GitHub Actions with [PyPI trusted publishing](https://docs.pypi.org/trusted-publishers/) — no API tokens needed in your repo.
169
+
170
+ ### One-time setup
171
+
172
+ 1. Go to your project on [pypi.org](https://pypi.org/manage/project/messygit/settings/publishing/)
173
+ 2. Add a **Trusted Publisher**:
174
+ - **Owner:** your GitHub username
175
+ - **Repository:** `messygit`
176
+ - **Workflow name:** `publish.yml`
177
+ - **Environment:** leave blank
178
+
179
+ ### To release a new version
180
+
181
+ 1. Bump `version` in `pyproject.toml`
182
+ 2. Commit and push
183
+ 3. Create a GitHub release:
184
+
185
+ ```bash
186
+ git tag v0.2.0
187
+ git push origin v0.2.0
188
+ ```
189
+
190
+ 4. Go to GitHub → Releases → Draft a new release → select the tag → Publish
191
+
192
+ The workflow at `.github/workflows/publish.yml` will automatically build and upload to PyPI.
193
+
194
+ ### Manual publish (without CI)
195
+
196
+ ```bash
197
+ rm -rf dist/
198
+ python -m build
199
+ twine upload dist/*
200
+ ```
201
+
202
+ ## License
203
+
204
+ MIT (see `pyproject.toml`).
@@ -15,8 +15,9 @@ from ..config import (
15
15
  resolve_api_key,
16
16
  )
17
17
  from ..llm import _is_insufficient_balance_or_billing, _insufficient_balance_user_message, _text_from_message
18
+ from ..models import current_model
19
+ from ..usage import SESSION_USAGE
18
20
 
19
- DEFAULT_MODEL = "claude-haiku-4-5-20251001"
20
21
  DEFAULT_MAX_TOKENS = 4096
21
22
 
22
23
  class Agent:
@@ -29,19 +30,21 @@ class Agent:
29
30
  def run(self, user_input: str) -> str:
30
31
  """Run the agent."""
31
32
  client = Anthropic(api_key=resolve_api_key())
33
+ model = current_model()
32
34
  messages = []
33
35
  try:
34
36
  messages.append({"role": "user", "content": user_input})
35
37
  response = None
36
38
  for i in range(self.max_iterations):
37
39
  response = client.messages.create(
38
- model=DEFAULT_MODEL,
40
+ model=model.id,
39
41
  max_tokens=DEFAULT_MAX_TOKENS,
40
42
  tools=[t.to_schema() for t in self.tools],
41
43
  tool_choice={"type": "auto"},
42
44
  system=self.system_prompt,
43
45
  messages=messages,
44
46
  )
47
+ SESSION_USAGE.record(response.usage, model)
45
48
  messages.append({"role": "assistant", "content": response.content})
46
49
 
47
50
  tool_use_blocks = [b for b in response.content if b.type == "tool_use"]