patch-code 0.1.0__py3-none-any.whl

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 (153) hide show
  1. patch/__init__.py +3 -0
  2. patch/__main__.py +4 -0
  3. patch/analytics.py +268 -0
  4. patch/args.py +949 -0
  5. patch/args_formatter.py +227 -0
  6. patch/coders/__init__.py +34 -0
  7. patch/coders/architect_coder.py +48 -0
  8. patch/coders/architect_prompts.py +40 -0
  9. patch/coders/ask_coder.py +9 -0
  10. patch/coders/ask_prompts.py +41 -0
  11. patch/coders/base_coder.py +2485 -0
  12. patch/coders/base_prompts.py +60 -0
  13. patch/coders/chat_chunks.py +64 -0
  14. patch/coders/context_coder.py +53 -0
  15. patch/coders/context_prompts.py +75 -0
  16. patch/coders/editblock_coder.py +657 -0
  17. patch/coders/editblock_fenced_coder.py +10 -0
  18. patch/coders/editblock_fenced_prompts.py +143 -0
  19. patch/coders/editblock_func_coder.py +141 -0
  20. patch/coders/editblock_func_prompts.py +27 -0
  21. patch/coders/editblock_prompts.py +172 -0
  22. patch/coders/editor_diff_fenced_coder.py +9 -0
  23. patch/coders/editor_diff_fenced_prompts.py +11 -0
  24. patch/coders/editor_editblock_coder.py +8 -0
  25. patch/coders/editor_editblock_prompts.py +18 -0
  26. patch/coders/editor_whole_coder.py +8 -0
  27. patch/coders/editor_whole_prompts.py +10 -0
  28. patch/coders/help_coder.py +16 -0
  29. patch/coders/help_prompts.py +46 -0
  30. patch/coders/patch_coder.py +706 -0
  31. patch/coders/patch_prompts.py +159 -0
  32. patch/coders/search_replace.py +757 -0
  33. patch/coders/shell.py +37 -0
  34. patch/coders/single_wholefile_func_coder.py +102 -0
  35. patch/coders/single_wholefile_func_prompts.py +27 -0
  36. patch/coders/udiff_coder.py +429 -0
  37. patch/coders/udiff_prompts.py +113 -0
  38. patch/coders/udiff_simple.py +14 -0
  39. patch/coders/udiff_simple_prompts.py +25 -0
  40. patch/coders/wholefile_coder.py +144 -0
  41. patch/coders/wholefile_func_coder.py +134 -0
  42. patch/coders/wholefile_func_prompts.py +27 -0
  43. patch/coders/wholefile_prompts.py +64 -0
  44. patch/commands.py +1712 -0
  45. patch/copypaste.py +72 -0
  46. patch/deprecated.py +126 -0
  47. patch/diffs.py +128 -0
  48. patch/docs/__init__.py +1 -0
  49. patch/docs/analytics.md +28 -0
  50. patch/docs/config.md +43 -0
  51. patch/docs/git.md +22 -0
  52. patch/docs/install.md +54 -0
  53. patch/docs/models.md +59 -0
  54. patch/docs/troubleshooting.md +23 -0
  55. patch/docs/usage.md +47 -0
  56. patch/dump.py +29 -0
  57. patch/editor.py +147 -0
  58. patch/exceptions.py +113 -0
  59. patch/format_settings.py +26 -0
  60. patch/gui.py +545 -0
  61. patch/help.py +118 -0
  62. patch/history.py +143 -0
  63. patch/io.py +1191 -0
  64. patch/linter.py +304 -0
  65. patch/llm.py +47 -0
  66. patch/main.py +1274 -0
  67. patch/mdstream.py +243 -0
  68. patch/models.py +1338 -0
  69. patch/onboarding.py +428 -0
  70. patch/openrouter.py +128 -0
  71. patch/prompts.py +61 -0
  72. patch/queries/tree-sitter-language-pack/arduino-tags.scm +5 -0
  73. patch/queries/tree-sitter-language-pack/bash-tags.scm +8 -0
  74. patch/queries/tree-sitter-language-pack/c-tags.scm +9 -0
  75. patch/queries/tree-sitter-language-pack/chatito-tags.scm +16 -0
  76. patch/queries/tree-sitter-language-pack/clojure-tags.scm +7 -0
  77. patch/queries/tree-sitter-language-pack/commonlisp-tags.scm +122 -0
  78. patch/queries/tree-sitter-language-pack/cpp-tags.scm +15 -0
  79. patch/queries/tree-sitter-language-pack/csharp-tags.scm +26 -0
  80. patch/queries/tree-sitter-language-pack/d-tags.scm +26 -0
  81. patch/queries/tree-sitter-language-pack/dart-tags.scm +92 -0
  82. patch/queries/tree-sitter-language-pack/elisp-tags.scm +5 -0
  83. patch/queries/tree-sitter-language-pack/elixir-tags.scm +54 -0
  84. patch/queries/tree-sitter-language-pack/elm-tags.scm +19 -0
  85. patch/queries/tree-sitter-language-pack/gleam-tags.scm +41 -0
  86. patch/queries/tree-sitter-language-pack/go-tags.scm +42 -0
  87. patch/queries/tree-sitter-language-pack/java-tags.scm +20 -0
  88. patch/queries/tree-sitter-language-pack/javascript-tags.scm +88 -0
  89. patch/queries/tree-sitter-language-pack/lua-tags.scm +34 -0
  90. patch/queries/tree-sitter-language-pack/matlab-tags.scm +10 -0
  91. patch/queries/tree-sitter-language-pack/ocaml-tags.scm +115 -0
  92. patch/queries/tree-sitter-language-pack/ocaml_interface-tags.scm +98 -0
  93. patch/queries/tree-sitter-language-pack/pony-tags.scm +39 -0
  94. patch/queries/tree-sitter-language-pack/properties-tags.scm +5 -0
  95. patch/queries/tree-sitter-language-pack/python-tags.scm +14 -0
  96. patch/queries/tree-sitter-language-pack/r-tags.scm +21 -0
  97. patch/queries/tree-sitter-language-pack/racket-tags.scm +12 -0
  98. patch/queries/tree-sitter-language-pack/ruby-tags.scm +64 -0
  99. patch/queries/tree-sitter-language-pack/rust-tags.scm +60 -0
  100. patch/queries/tree-sitter-language-pack/solidity-tags.scm +43 -0
  101. patch/queries/tree-sitter-language-pack/swift-tags.scm +51 -0
  102. patch/queries/tree-sitter-language-pack/udev-tags.scm +20 -0
  103. patch/queries/tree-sitter-languages/bash-tags.scm +8 -0
  104. patch/queries/tree-sitter-languages/c-tags.scm +9 -0
  105. patch/queries/tree-sitter-languages/c_sharp-tags.scm +46 -0
  106. patch/queries/tree-sitter-languages/cpp-tags.scm +15 -0
  107. patch/queries/tree-sitter-languages/dart-tags.scm +91 -0
  108. patch/queries/tree-sitter-languages/elisp-tags.scm +8 -0
  109. patch/queries/tree-sitter-languages/elixir-tags.scm +54 -0
  110. patch/queries/tree-sitter-languages/elm-tags.scm +19 -0
  111. patch/queries/tree-sitter-languages/fortran-tags.scm +15 -0
  112. patch/queries/tree-sitter-languages/go-tags.scm +30 -0
  113. patch/queries/tree-sitter-languages/haskell-tags.scm +3 -0
  114. patch/queries/tree-sitter-languages/hcl-tags.scm +77 -0
  115. patch/queries/tree-sitter-languages/java-tags.scm +20 -0
  116. patch/queries/tree-sitter-languages/javascript-tags.scm +88 -0
  117. patch/queries/tree-sitter-languages/julia-tags.scm +60 -0
  118. patch/queries/tree-sitter-languages/kotlin-tags.scm +27 -0
  119. patch/queries/tree-sitter-languages/matlab-tags.scm +10 -0
  120. patch/queries/tree-sitter-languages/ocaml-tags.scm +115 -0
  121. patch/queries/tree-sitter-languages/ocaml_interface-tags.scm +98 -0
  122. patch/queries/tree-sitter-languages/php-tags.scm +26 -0
  123. patch/queries/tree-sitter-languages/python-tags.scm +12 -0
  124. patch/queries/tree-sitter-languages/ql-tags.scm +26 -0
  125. patch/queries/tree-sitter-languages/ruby-tags.scm +64 -0
  126. patch/queries/tree-sitter-languages/rust-tags.scm +60 -0
  127. patch/queries/tree-sitter-languages/scala-tags.scm +65 -0
  128. patch/queries/tree-sitter-languages/typescript-tags.scm +41 -0
  129. patch/queries/tree-sitter-languages/zig-tags.scm +3 -0
  130. patch/reasoning_tags.py +82 -0
  131. patch/repo.py +622 -0
  132. patch/repomap.py +867 -0
  133. patch/report.py +200 -0
  134. patch/resources/__init__.py +3 -0
  135. patch/resources/model-metadata.json +715 -0
  136. patch/resources/model-settings.yml +3128 -0
  137. patch/run_cmd.py +132 -0
  138. patch/scrape.py +284 -0
  139. patch/sendchat.py +61 -0
  140. patch/special.py +203 -0
  141. patch/urls.py +17 -0
  142. patch/utils.py +348 -0
  143. patch/versioncheck.py +130 -0
  144. patch/voice.py +187 -0
  145. patch/waiting.py +221 -0
  146. patch/watch.py +318 -0
  147. patch/watch_prompts.py +12 -0
  148. patch_code-0.1.0.dist-info/METADATA +467 -0
  149. patch_code-0.1.0.dist-info/RECORD +153 -0
  150. patch_code-0.1.0.dist-info/WHEEL +5 -0
  151. patch_code-0.1.0.dist-info/entry_points.txt +2 -0
  152. patch_code-0.1.0.dist-info/licenses/LICENSE.txt +202 -0
  153. patch_code-0.1.0.dist-info/top_level.txt +1 -0
patch/copypaste.py ADDED
@@ -0,0 +1,72 @@
1
+ import threading
2
+ import time
3
+
4
+ import pyperclip
5
+
6
+
7
+ class ClipboardWatcher:
8
+ """Watches clipboard for changes and updates IO placeholder"""
9
+
10
+ def __init__(self, io, verbose=False):
11
+ self.io = io
12
+ self.verbose = verbose
13
+ self.stop_event = None
14
+ self.watcher_thread = None
15
+ self.last_clipboard = None
16
+ self.io.clipboard_watcher = self
17
+
18
+ def start(self):
19
+ """Start watching clipboard for changes"""
20
+ self.stop_event = threading.Event()
21
+ self.last_clipboard = pyperclip.paste()
22
+
23
+ def watch_clipboard():
24
+ while not self.stop_event.is_set():
25
+ try:
26
+ current = pyperclip.paste()
27
+ if current != self.last_clipboard:
28
+ self.last_clipboard = current
29
+ self.io.interrupt_input()
30
+ self.io.placeholder = current
31
+ if len(current.splitlines()) > 1:
32
+ self.io.placeholder = "\n" + self.io.placeholder + "\n"
33
+
34
+ time.sleep(0.5)
35
+ except Exception as e:
36
+ if self.verbose:
37
+ from patch.dump import dump
38
+
39
+ dump(f"Clipboard watcher error: {e}")
40
+ continue
41
+
42
+ self.watcher_thread = threading.Thread(target=watch_clipboard, daemon=True)
43
+ self.watcher_thread.start()
44
+
45
+ def stop(self):
46
+ """Stop watching clipboard for changes"""
47
+ if self.stop_event:
48
+ self.stop_event.set()
49
+ if self.watcher_thread:
50
+ self.watcher_thread.join()
51
+ self.watcher_thread = None
52
+ self.stop_event = None
53
+
54
+
55
+ def main():
56
+ """Example usage of the clipboard watcher"""
57
+ from patch.io import InputOutput
58
+
59
+ io = InputOutput()
60
+ watcher = ClipboardWatcher(io, verbose=True)
61
+
62
+ try:
63
+ watcher.start()
64
+ while True:
65
+ time.sleep(1)
66
+ except KeyboardInterrupt:
67
+ print("\nStopped watching clipboard")
68
+ watcher.stop()
69
+
70
+
71
+ if __name__ == "__main__":
72
+ main()
patch/deprecated.py ADDED
@@ -0,0 +1,126 @@
1
+ def add_deprecated_model_args(parser, group):
2
+ """Add deprecated model shortcut arguments to the argparse parser."""
3
+ opus_model = "claude-3-opus-20240229"
4
+ group.add_argument(
5
+ "--opus",
6
+ action="store_true",
7
+ help=f"Use {opus_model} model for the main chat (deprecated, use --model)",
8
+ default=False,
9
+ )
10
+ sonnet_model = "anthropic/claude-3-7-sonnet-20250219"
11
+ group.add_argument(
12
+ "--sonnet",
13
+ action="store_true",
14
+ help=f"Use {sonnet_model} model for the main chat (deprecated, use --model)",
15
+ default=False,
16
+ )
17
+ haiku_model = "claude-3-5-haiku-20241022"
18
+ group.add_argument(
19
+ "--haiku",
20
+ action="store_true",
21
+ help=f"Use {haiku_model} model for the main chat (deprecated, use --model)",
22
+ default=False,
23
+ )
24
+ gpt_4_model = "gpt-4-0613"
25
+ group.add_argument(
26
+ "--4",
27
+ "-4",
28
+ action="store_true",
29
+ help=f"Use {gpt_4_model} model for the main chat (deprecated, use --model)",
30
+ default=False,
31
+ )
32
+ gpt_4o_model = "gpt-4o"
33
+ group.add_argument(
34
+ "--4o",
35
+ action="store_true",
36
+ help=f"Use {gpt_4o_model} model for the main chat (deprecated, use --model)",
37
+ default=False,
38
+ )
39
+ gpt_4o_mini_model = "gpt-4o-mini"
40
+ group.add_argument(
41
+ "--mini",
42
+ action="store_true",
43
+ help=f"Use {gpt_4o_mini_model} model for the main chat (deprecated, use --model)",
44
+ default=False,
45
+ )
46
+ gpt_4_turbo_model = "gpt-4-1106-preview"
47
+ group.add_argument(
48
+ "--4-turbo",
49
+ action="store_true",
50
+ help=f"Use {gpt_4_turbo_model} model for the main chat (deprecated, use --model)",
51
+ default=False,
52
+ )
53
+ gpt_3_model_name = "gpt-3.5-turbo"
54
+ group.add_argument(
55
+ "--35turbo",
56
+ "--35-turbo",
57
+ "--3",
58
+ "-3",
59
+ action="store_true",
60
+ help=f"Use {gpt_3_model_name} model for the main chat (deprecated, use --model)",
61
+ default=False,
62
+ )
63
+ deepseek_model = "deepseek/deepseek-chat"
64
+ group.add_argument(
65
+ "--deepseek",
66
+ action="store_true",
67
+ help=f"Use {deepseek_model} model for the main chat (deprecated, use --model)",
68
+ default=False,
69
+ )
70
+ o1_mini_model = "o1-mini"
71
+ group.add_argument(
72
+ "--o1-mini",
73
+ action="store_true",
74
+ help=f"Use {o1_mini_model} model for the main chat (deprecated, use --model)",
75
+ default=False,
76
+ )
77
+ o1_preview_model = "o1-preview"
78
+ group.add_argument(
79
+ "--o1-preview",
80
+ action="store_true",
81
+ help=f"Use {o1_preview_model} model for the main chat (deprecated, use --model)",
82
+ default=False,
83
+ )
84
+
85
+
86
+ def handle_deprecated_model_args(args, io):
87
+ """Handle deprecated model shortcut arguments and provide appropriate warnings."""
88
+ # Define model mapping
89
+ model_map = {
90
+ "opus": "claude-3-opus-20240229",
91
+ "sonnet": "anthropic/claude-3-7-sonnet-20250219",
92
+ "haiku": "claude-3-5-haiku-20241022",
93
+ "4": "gpt-4-0613",
94
+ "4o": "gpt-4o",
95
+ "mini": "gpt-4o-mini",
96
+ "4_turbo": "gpt-4-1106-preview",
97
+ "35turbo": "gpt-3.5-turbo",
98
+ "deepseek": "deepseek/deepseek-chat",
99
+ "o1_mini": "o1-mini",
100
+ "o1_preview": "o1-preview",
101
+ }
102
+
103
+ # Check if any deprecated args are used
104
+ for arg_name, model_name in model_map.items():
105
+ arg_name_clean = arg_name.replace("-", "_")
106
+ if hasattr(args, arg_name_clean) and getattr(args, arg_name_clean):
107
+ # Find preferred name to display in warning
108
+ from patch.models import MODEL_ALIASES
109
+
110
+ display_name = model_name
111
+ # Check if there's a shorter alias for this model
112
+ for alias, full_name in MODEL_ALIASES.items():
113
+ if full_name == model_name:
114
+ display_name = alias
115
+ break
116
+
117
+ # Show the warning
118
+ io.tool_warning(
119
+ f"The --{arg_name.replace('_', '-')} flag is deprecated and will be removed in a"
120
+ f" future version. Please use --model {display_name} instead."
121
+ )
122
+
123
+ # Set the model
124
+ if not args.model:
125
+ args.model = model_name
126
+ break
patch/diffs.py ADDED
@@ -0,0 +1,128 @@
1
+ import difflib
2
+ import sys
3
+
4
+ from .dump import dump # noqa: F401
5
+
6
+
7
+ def main():
8
+ if len(sys.argv) != 3:
9
+ print("Usage: python diffs.py file1 file")
10
+ sys.exit(1)
11
+
12
+ file_orig, file_updated = sys.argv[1], sys.argv[2]
13
+
14
+ with open(file_orig, "r", encoding="utf-8") as f:
15
+ lines_orig = f.readlines()
16
+
17
+ with open(file_updated, "r", encoding="utf-8") as f:
18
+ lines_updated = f.readlines()
19
+
20
+ for i in range(len(file_updated)):
21
+ res = diff_partial_update(lines_orig, lines_updated[:i])
22
+ print(res)
23
+ input()
24
+
25
+
26
+ def create_progress_bar(percentage):
27
+ block = "█"
28
+ empty = "░"
29
+ total_blocks = 30
30
+ filled_blocks = int(total_blocks * percentage // 100)
31
+ empty_blocks = total_blocks - filled_blocks
32
+ bar = block * filled_blocks + empty * empty_blocks
33
+ return bar
34
+
35
+
36
+ def assert_newlines(lines):
37
+ if not lines:
38
+ return
39
+ for line in lines[:-1]:
40
+ assert line and line[-1] == "\n", line
41
+
42
+
43
+ def diff_partial_update(lines_orig, lines_updated, final=False, fname=None):
44
+ """
45
+ Given only the first part of an updated file, show the diff while
46
+ ignoring the block of "deleted" lines that are past the end of the
47
+ partially complete update.
48
+ """
49
+
50
+ # dump(lines_orig)
51
+ # dump(lines_updated)
52
+
53
+ assert_newlines(lines_orig)
54
+
55
+ num_orig_lines = len(lines_orig)
56
+
57
+ if final:
58
+ last_non_deleted = num_orig_lines
59
+ else:
60
+ last_non_deleted = find_last_non_deleted(lines_orig, lines_updated)
61
+
62
+ # dump(last_non_deleted)
63
+ if last_non_deleted is None:
64
+ return ""
65
+
66
+ if num_orig_lines:
67
+ pct = last_non_deleted * 100 / num_orig_lines
68
+ else:
69
+ pct = 50
70
+ bar = create_progress_bar(pct)
71
+ bar = f" {last_non_deleted:3d} / {num_orig_lines:3d} lines [{bar}] {pct:3.0f}%\n"
72
+
73
+ lines_orig = lines_orig[:last_non_deleted]
74
+
75
+ if not final:
76
+ lines_updated = lines_updated[:-1] + [bar]
77
+
78
+ diff = difflib.unified_diff(lines_orig, lines_updated, n=5)
79
+
80
+ diff = list(diff)[2:]
81
+
82
+ diff = "".join(diff)
83
+ if not diff.endswith("\n"):
84
+ diff += "\n"
85
+
86
+ for i in range(3, 10):
87
+ backticks = "`" * i
88
+ if backticks not in diff:
89
+ break
90
+
91
+ show = f"{backticks}diff\n"
92
+ if fname:
93
+ show += f"--- {fname} original\n"
94
+ show += f"+++ {fname} updated\n"
95
+
96
+ show += diff
97
+
98
+ show += f"{backticks}\n\n"
99
+
100
+ # print(diff)
101
+
102
+ return show
103
+
104
+
105
+ def find_last_non_deleted(lines_orig, lines_updated):
106
+ diff = list(difflib.ndiff(lines_orig, lines_updated))
107
+
108
+ num_orig = 0
109
+ last_non_deleted_orig = None
110
+
111
+ for line in diff:
112
+ # print(f"{num_orig:2d} {num_updated:2d} {line}", end="")
113
+ code = line[0]
114
+ if code == " ":
115
+ num_orig += 1
116
+ last_non_deleted_orig = num_orig
117
+ elif code == "-":
118
+ # line only in orig
119
+ num_orig += 1
120
+ elif code == "+":
121
+ # line only in updated
122
+ pass
123
+
124
+ return last_non_deleted_orig
125
+
126
+
127
+ if __name__ == "__main__":
128
+ main()
patch/docs/__init__.py ADDED
@@ -0,0 +1 @@
1
+ """Packaged Markdown documentation for Patch's interactive help."""
@@ -0,0 +1,28 @@
1
+ # Analytics
2
+
3
+ Patch ships no analytics destination. No analytics events are sent and no opt-in
4
+ prompt appears unless you configure your own PostHog project. Upstream Aider's
5
+ project keys have been removed. Patch operates no analytics service.
6
+
7
+ ## Your own telemetry
8
+
9
+ The inherited instrumentation can be enabled with both
10
+ `--analytics-posthog-project-api-key KEY` and `--analytics`. The first time,
11
+ Patch asks you to confirm. `--analytics-posthog-host HOST` selects a custom host.
12
+ `--no-analytics` disables collection for the session;
13
+ `python -m patch --analytics-disable` records a permanent opt-out.
14
+
15
+ Events include feature usage, public model names, token counts, error indicators,
16
+ system information, and a random UUID. Unknown model names are redacted.
17
+ Automatic exception capture is disabled. Review [the source](../analytics.py)
18
+ before enabling instrumentation for your own deployment.
19
+
20
+ ## Local logs
21
+
22
+ ```bash
23
+ python -m patch --analytics-log events.jsonl --no-analytics
24
+ ```
25
+
26
+ This writes events locally without uploading them. Review logs before sharing
27
+ them and keep them out of version control. User-level analytics preferences and
28
+ the UUID are stored in `~/.patch/analytics.json`.
patch/docs/config.md ADDED
@@ -0,0 +1,43 @@
1
+ # Configuration
2
+
3
+ Run `python -m patch --help` for the complete, current CLI option reference.
4
+ Most options also accept `.patch.conf.yml` entries or `PATCH_*` environment variables.
5
+ For example, `--dark-mode`, `dark-mode: true` in YAML, and `PATCH_DARK_MODE=true`
6
+ are equivalent. Command-line values override environment and configuration values.
7
+
8
+ Patch searches for `.patch.conf.yml` in your home directory, Git repository root,
9
+ and current directory, with nearer configuration taking precedence. Use
10
+ `--config FILE` for an explicit configuration file.
11
+
12
+ ```yaml
13
+ model: sonnet
14
+ dark-mode: true
15
+ auto-commits: false
16
+ ```
17
+
18
+ ## Environment and credentials
19
+
20
+ Provider credentials retain their own names, such as `ANTHROPIC_API_KEY` and
21
+ `OPENAI_API_KEY`. Store them in your shell environment or an untracked `.env` file.
22
+ Use `--env-file FILE` to select an environment file. YAML `api-key` entries and
23
+ `--api-key provider=KEY` also support providers beyond OpenAI and Anthropic.
24
+ `--set-env NAME=value` sets other provider variables.
25
+
26
+ Review repository-local YAML and `.env` files before running Patch: they can
27
+ configure executable commands and provider endpoints. Never load untrusted
28
+ repository settings with credentials present.
29
+
30
+ ## Linting and tests
31
+
32
+ Patch can automatically lint edited files (`--auto-lint`, enabled by default).
33
+ Configure `--lint-cmd COMMAND` or `--lint-cmd 'python: COMMAND'`. Use
34
+ `--test-cmd COMMAND` with `--auto-test` for automatic tests, or `/test COMMAND`
35
+ inside chat. Only configure trusted commands.
36
+
37
+ ## State and privacy
38
+
39
+ Patch uses `.patch*` state files and `~/.patch/` for user-level data and caches.
40
+ `--input-history-file` and `--chat-history-file` change history destinations.
41
+ History, logs, and verbose settings can contain sensitive data; do not publish them
42
+ without review. Patch does not migrate `.aider*` or `AIDER_*` settings automatically.
43
+ See [analytics](analytics.md) for the disabled-by-default telemetry instrumentation.
patch/docs/git.md ADDED
@@ -0,0 +1,22 @@
1
+ # Git integration
2
+
3
+ Patch works best in a Git repository. By default it commits its edits with a
4
+ generated message and can commit pre-existing dirty changes before editing those
5
+ files. Review changes with `/diff` and normal Git commands.
6
+
7
+ `--no-auto-commits` disables automatic commits of model edits.
8
+ `--no-dirty-commits` disables the pre-edit commit of existing changes.
9
+ `--no-git` disables Git integration. `/commit` asks Patch to commit changes;
10
+ `/git <arguments>` runs Git directly.
11
+
12
+ ## Undo
13
+
14
+ `/undo` reverts the last eligible Patch commit. It is not a general backup system;
15
+ check `git status` and `git diff` before destructive Git operations. Keep your own
16
+ commits and backups, especially when automatic commits are disabled.
17
+
18
+ ## Attribution
19
+
20
+ Use `--attribute-author`, `--attribute-committer`, and the commit-message
21
+ attribution options shown by `python -m patch --help` to control Patch attribution.
22
+ Configure your own Git user name and email before working in a repository.
patch/docs/install.md ADDED
@@ -0,0 +1,54 @@
1
+ # Installing Patch
2
+
3
+ Patch supports Python 3.10–3.14. Use an isolated virtual environment:
4
+
5
+ ```bash
6
+ python -m venv .venv
7
+ # macOS / Linux:
8
+ source .venv/bin/activate
9
+ # Windows PowerShell: .venv\Scripts\Activate.ps1
10
+ python -m pip install patch-code
11
+ python -m patch --help
12
+ ```
13
+
14
+ Run `python -m pip install --upgrade patch-code` to upgrade. Update notices do not
15
+ install anything automatically. Use `python -m patch` to avoid the Unix `patch`
16
+ utility. For source development see [CONTRIBUTING.md](../../CONTRIBUTING.md).
17
+
18
+ ## Interactive help
19
+
20
+ ```bash
21
+ python -m pip install 'patch-code[help]' --extra-index-url https://download.pytorch.org/whl/cpu
22
+ ```
23
+
24
+ `/help <question>` can offer to install this extra. The first use downloads a
25
+ Hugging Face embedding model and indexes the packaged Markdown docs; subsequent
26
+ uses cache the index under `~/.patch/caches/`. Retrieval runs locally, but the
27
+ question and relevant docs are sent to your configured chat model for an answer.
28
+ Bare `/help` and `python -m patch --help` do not require this extra.
29
+
30
+ ## Browser UI
31
+
32
+ ```bash
33
+ python -m pip install 'patch-code[browser]'
34
+ python -m patch --browser
35
+ ```
36
+
37
+ The experimental UI is intended for a trusted single user. Do not expose it to
38
+ untrusted networks or share it with other users: it can edit files and run commands.
39
+
40
+ ## Enable Playwright
41
+
42
+ For pages that need browser rendering:
43
+
44
+ ```bash
45
+ python -m pip install 'patch-code[playwright]'
46
+ python -m playwright install --with-deps chromium
47
+ ```
48
+
49
+ ## Installation problems
50
+
51
+ Check that `python --version` is supported and `python -m pip --version` points at
52
+ the active environment. Use the same Python for installation and launch. Avoid
53
+ naming local files `patch.py` or `patch`, which can shadow the installed package.
54
+ Recreate the virtual environment if it contains incompatible dependencies.
patch/docs/models.md ADDED
@@ -0,0 +1,59 @@
1
+ # Models
2
+
3
+ Select a model with `python -m patch --model MODEL` or `/model MODEL` in chat.
4
+ `python -m patch --list-models QUERY` lists matching known names. Aliases such as
5
+ `sonnet` are defined in [the model module](../models.py); they can change over time.
6
+
7
+ ## API keys
8
+
9
+ Use provider environment variables such as `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`,
10
+ `GEMINI_API_KEY`, or `OPENROUTER_API_KEY`. Alternatively use
11
+ `--api-key anthropic=YOUR_KEY` (substitute your provider). Shell history and process
12
+ listings can expose command-line keys, so prefer a private environment or `.env`.
13
+ Never commit credentials or paste them into issue reports.
14
+
15
+ Examples of model selection:
16
+
17
+ ```bash
18
+ python -m patch --model sonnet
19
+ python -m patch --model openrouter/anthropic/claude-3.5-sonnet
20
+ python -m patch --model ollama_chat/YOUR_LOCAL_MODEL
21
+ ```
22
+
23
+ For Ollama, start its server and pull the model first; set `OLLAMA_API_BASE` if
24
+ needed. For an OpenAI-compatible server use an `openai/` model name and configure
25
+ `OPENAI_API_BASE` and `OPENAI_API_KEY` as required by that server. Availability,
26
+ prices, permissions, and context limits are controlled by the provider.
27
+
28
+ ## Model warnings
29
+
30
+ Unknown context limits or token costs mean Patch lacks model metadata, not
31
+ necessarily that the model cannot work. Check the provider's model name and limits.
32
+ Add metadata with `.patch.model.metadata.json` or `--model-metadata-file`.
33
+ The JSON maps model names to LiteLLM metadata such as `max_input_tokens`,
34
+ `max_output_tokens`, `input_cost_per_token`, `output_cost_per_token`,
35
+ `litellm_provider`, and `mode`.
36
+
37
+ ## Model settings
38
+
39
+ Use `.patch.model.settings.yml` or `--model-settings-file` for a YAML list of
40
+ settings. For example:
41
+
42
+ ```yaml
43
+ - name: openai/your-model
44
+ edit_format: whole
45
+ weak_model_name: null
46
+ use_repo_map: true
47
+ ```
48
+
49
+ See [the packaged settings](../resources/model-settings.yml) for supported examples.
50
+ These are distinct from model metadata. Use `--alias short:provider/model` to
51
+ define a short name. See [configuration](config.md) for storing command options.
52
+
53
+ ## Edit formats
54
+
55
+ Patch chooses an edit format from its model settings. `diff` uses SEARCH/REPLACE
56
+ blocks; `whole` replaces full files; `udiff` uses unified diffs; `patch` uses
57
+ explicit patch operations. `--edit-format FORMAT` overrides the default.
58
+ Choose a format your model follows reliably. Use `/ask` for discussion without
59
+ edits and `/architect` for a plan followed by a separate editor model.
@@ -0,0 +1,23 @@
1
+ # Troubleshooting
2
+
3
+ Start with `python -m patch --help` and `/help`. For installation/import problems
4
+ see [installation](install.md#installation-problems); for credentials and provider
5
+ errors see [models](models.md#api-keys). Report reproducible problems in
6
+ [Patch issues](https://github.com/PierrunoYT/patch/issues), omitting credentials,
7
+ private code, and unredacted logs.
8
+
9
+ ## Edit errors
10
+
11
+ An edit error means Patch could not apply the model's requested format or match
12
+ its source text. Patch normally sends feedback to the model so it can retry.
13
+ If failures repeat, reduce the request, add the correct files, and use a model
14
+ with reliable editing support. Check [edit formats](models.md#edit-formats).
15
+ Review the diff: a failed response may still have applied some edits.
16
+
17
+ ## Token limits
18
+
19
+ Use `/tokens` to inspect context usage. `/drop` unnecessary files and `/clear`
20
+ old chat history; ask for smaller changes. Large files, pasted output, and long
21
+ conversations consume input context. Output limits can truncate edits, so review
22
+ files and tests rather than assuming a finished response made complete changes.
23
+ Check [model metadata](models.md#model-warnings) if the reported limits look wrong.
patch/docs/usage.md ADDED
@@ -0,0 +1,47 @@
1
+ # Using Patch
2
+
3
+ Patch is an AI pair-programming tool for your terminal, forked from Aider.
4
+ Start in your project directory with `python -m patch file1.py file2.py`, then
5
+ describe the change you want. Review the edits and run your tests.
6
+ See [installation](install.md), [models](models.md), [configuration](config.md),
7
+ [Git integration](git.md), and [troubleshooting](troubleshooting.md).
8
+
9
+ ## Adding files
10
+
11
+ Use `/add path/to/file` to share editable files, `/read path/to/file` for read-only
12
+ context, `/ls` to list files, and `/drop path/to/file` to remove files from chat.
13
+ Only add files needed for the task: adding everything costs tokens and can confuse
14
+ the model. The repository map supplies related context without adding every file.
15
+ Use `/tokens` to inspect context usage.
16
+
17
+ ## Large repositories
18
+
19
+ Start Patch in the repository and add only the files you expect to edit.
20
+ Use `.patchignore` with Git-ignore patterns to exclude irrelevant files from the
21
+ repository map and file discovery. Adjust `--map-tokens` to control map size;
22
+ `--map-tokens 0` disables the map. `/map` shows it and `/map-refresh` refreshes it.
23
+
24
+ ## Commands and modes
25
+
26
+ - `/help` lists commands without installing extras. `/help <question>` retrieves
27
+ these packaged docs and asks your configured model for an answer; it requires
28
+ the [help extra](install.md#interactive-help) and may incur model API charges.
29
+ - `/ask <question>` discusses code without editing; `/code <request>` requests edits.
30
+ - `/architect <request>` uses a planning model followed by an editor model.
31
+ `/chat-mode` changes the mode for subsequent messages.
32
+ - `/model <name>` changes the main model; `/models <query>` searches model names.
33
+ - `/diff` reviews the last changes; `/undo` undoes the last eligible Patch commit.
34
+ - `/run <command>` runs a shell command and offers to add its output to chat.
35
+ - `/test <command>` runs tests and offers to fix failures; `/lint` runs configured linters.
36
+ - `/clear` clears chat history; `/reset` also drops files; `/exit` ends the session.
37
+
38
+ ## More context
39
+
40
+ Use `/web <URL>` to read a page, `/add` for a supported image, and `/voice` for
41
+ microphone transcription. Voice requires an audio device and transcription provider
42
+ credentials. Use `/paste` for clipboard content and `/editor` to write a prompt
43
+ in your editor. `/multiline-mode` toggles multiline input.
44
+
45
+ `--watch-files` reacts to AI comment markers in source files. Only enable it in
46
+ trusted projects: other local processes that write files can trigger model turns.
47
+ The experimental `--browser` UI requires the [browser extra](install.md#browser-ui).
patch/dump.py ADDED
@@ -0,0 +1,29 @@
1
+ import json
2
+ import traceback
3
+
4
+
5
+ def cvt(s):
6
+ if isinstance(s, str):
7
+ return s
8
+ try:
9
+ return json.dumps(s, indent=4)
10
+ except TypeError:
11
+ return str(s)
12
+
13
+
14
+ def dump(*vals):
15
+ # http://docs.python.org/library/traceback.html
16
+ stack = traceback.extract_stack()
17
+ vars = stack[-2][3]
18
+
19
+ # strip away the call to dump()
20
+ vars = "(".join(vars.split("(")[1:])
21
+ vars = ")".join(vars.split(")")[:-1])
22
+
23
+ vals = [cvt(v) for v in vals]
24
+ has_newline = sum(1 for v in vals if "\n" in v)
25
+ if has_newline:
26
+ print("%s:" % vars)
27
+ print(", ".join(vals))
28
+ else:
29
+ print("%s:" % vars, ", ".join(vals))