llm-ide-rules 0.7.0__py3-none-any.whl → 0.8.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.
llm_ide_rules/utils.py ADDED
@@ -0,0 +1,118 @@
1
+ """Utility functions for LLM IDE rules."""
2
+
3
+ import re
4
+ from pathlib import Path
5
+ from typing import Any
6
+
7
+
8
+ def modify_json_file(file_path: Path, updates: dict[str, Any]) -> bool:
9
+ """Modify a JSON/JSONC file by adding MISSING keys using string manipulation to preserve comments.
10
+
11
+ Returns:
12
+ bool: True if changes were written to the file, False otherwise.
13
+ """
14
+ if not file_path.exists():
15
+ # Create new file with standard JSON if it doesn't exist
16
+ import json
17
+
18
+ file_path.parent.mkdir(parents=True, exist_ok=True)
19
+ file_path.write_text(json.dumps(updates, indent=2))
20
+ return True
21
+
22
+ original_content = file_path.read_text()
23
+ content = original_content
24
+
25
+ for key, value in updates.items():
26
+ # Prepare the value representation (basic JSON serialization)
27
+ if isinstance(value, bool):
28
+ val_str = "true" if value else "false"
29
+ elif isinstance(value, (int, float)):
30
+ val_str = str(value)
31
+ elif isinstance(value, str):
32
+ val_str = f'"{value}"'
33
+ else:
34
+ import json
35
+
36
+ val_str = json.dumps(value)
37
+
38
+ # Updated pattern:
39
+ # 1. Match key part: (["']?key["']?\s* : \s*)
40
+ # 2. Match value part: ([^,\n\r}]+?)
41
+ # 3. Lookahead to stop before a comma, newline, closing brace, or start of a comment
42
+ escaped_key = re.escape(key)
43
+ pattern_str = (
44
+ rf'(["\\]?{escaped_key}["\\]?\s*:\s*)([^,\n\r}}]+?)'
45
+ r"(?=\s*(?:,|\n|\r|\}|\/\/|\/\*))"
46
+ )
47
+ pattern = re.compile(pattern_str, re.MULTILINE)
48
+
49
+ match = pattern.search(content)
50
+ if match:
51
+ # Key exists, replace the value part
52
+ # full_match = match.group(0)
53
+ key_part = match.group(1)
54
+ # Replace the value part (group 2) with new value
55
+ new_entry = f"{key_part}{val_str}"
56
+ content = content[: match.start()] + new_entry + content[match.end() :]
57
+ else:
58
+ # Insert new key
59
+ last_brace_idx = content.rfind("}")
60
+ if last_brace_idx != -1:
61
+ insertion_point = last_brace_idx
62
+
63
+ # Look backwards for the first non-whitespace character before the brace
64
+ prev_char_idx = insertion_point - 1
65
+ while prev_char_idx >= 0 and content[prev_char_idx].isspace():
66
+ prev_char_idx -= 1
67
+
68
+ # Detect indentation from the previous line if possible
69
+ line_start = content.rfind("\n", 0, insertion_point)
70
+ if line_start != -1:
71
+ indent_match = re.match(r"^(\s*)", content[line_start + 1 :])
72
+ indent = indent_match.group(1) if indent_match else " "
73
+ else:
74
+ indent = " "
75
+
76
+ if prev_char_idx >= 0:
77
+ prev_char = content[prev_char_idx]
78
+ # If the last thing wasn't a comma or opening brace, we need a comma
79
+ if prev_char not in ["{", ","]:
80
+ new_entry = f',\n{indent}"{key}": {val_str}'
81
+ else:
82
+ new_entry = f'\n{indent}"{key}": {val_str}'
83
+
84
+ content = (
85
+ content[:insertion_point]
86
+ + new_entry
87
+ + content[insertion_point:]
88
+ )
89
+
90
+ if content != original_content:
91
+ file_path.write_text(content)
92
+ return True
93
+
94
+ return False
95
+
96
+
97
+ def find_project_root(start_path: Path | None = None) -> Path:
98
+ """Find the project root by looking for common markers."""
99
+ if start_path is None:
100
+ start_path = Path.cwd()
101
+
102
+ path = start_path.resolve()
103
+ # Check current directory and parents
104
+ for parent in [path] + list(path.parents):
105
+ if (parent / ".git").exists():
106
+ return parent
107
+ if (parent / "pyproject.toml").exists():
108
+ return parent
109
+ if (parent / ".cursor").exists():
110
+ return parent
111
+ if (parent / ".claude").exists():
112
+ return parent
113
+ if (parent / ".gemini").exists():
114
+ return parent
115
+ if (parent / ".github").exists():
116
+ return parent
117
+
118
+ return start_path # Fallback to current directory
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: llm-ide-rules
3
- Version: 0.7.0
3
+ Version: 0.8.0
4
4
  Summary: CLI tool for managing LLM IDE prompts and rules
5
5
  Keywords: llm,ide,prompts,cursor,copilot
6
6
  Author: Michael Bianco
@@ -18,7 +18,7 @@ Description-Content-Type: text/markdown
18
18
 
19
19
  # Copilot, Cursor, Claude, Gemini, etc LLM Instructions
20
20
 
21
- This project makes it easy to download prompts and implode/explode them so they can be used by various providers.
21
+ This project makes it easy to download prompts and implode/explode them so they can be used by various providers. It's completely vibe coded, but it works.
22
22
 
23
23
  I don't want to be tied to a specific IDE and it's a pain to have to edit instructions for various languages across a ton of different files.
24
24
 
@@ -40,7 +40,7 @@ Different AI coding assistants use different formats for instructions and comman
40
40
  | **GitHub Copilot** | instructions | `.github/copilot-instructions.md` | Single markdown file |
41
41
  | **GitHub Copilot** | instructions | `.github/instructions/*.instructions.md` | Multiple instruction files |
42
42
  | **GitHub Copilot** | prompts | `.github/prompts/*.prompt.md` | YAML frontmatter with `mode: 'agent'` |
43
- | **Gemini CLI** | instructions | `GEMINI.md` | Single markdown file at root |
43
+ | **Gemini CLI** | instructions | `AGENTS.md` | Single markdown file at root |
44
44
  | **Gemini CLI** | commands | `.gemini/commands/*.toml` | TOML format, supports `{{args}}` and shell commands |
45
45
  | **OpenCode** | commands | `.opencode/commands/*.md` | Plain markdown, no frontmatter |
46
46
 
@@ -0,0 +1,27 @@
1
+ llm_ide_rules/__init__.py,sha256=azpwor_AmypcI7JkDSgoOf-gyUJ66q2rPQ_WEzdJvVo,2746
2
+ llm_ide_rules/__main__.py,sha256=8maIDGnEcSUBs9lXg7YEevCXPC0fisYPC2gAEXHfHGM,145
3
+ llm_ide_rules/agents/__init__.py,sha256=pJ9sifirxbFGbajyFM6ZAnuE0kQAWiNw_bWanA4ujOY,1063
4
+ llm_ide_rules/agents/agents.py,sha256=QxXwlneARcPyKrsoQIlDhBMwmEKAXZDulkxZGJo6xNw,4296
5
+ llm_ide_rules/agents/base.py,sha256=WdzFBp_IUcOmh34joAu4FIyysZIFHbamT_4NH4IzIso,10843
6
+ llm_ide_rules/agents/claude.py,sha256=21D8s0FEMuD3_hAV8m_vK_zlA5BD15sPd1V_RhXRzPs,3647
7
+ llm_ide_rules/agents/cursor.py,sha256=QOrroQK3vHmJhpg1QsdIwfcvxjMkCNwcwwiGtxa2TNA,6890
8
+ llm_ide_rules/agents/gemini.py,sha256=bkigB1eUOpB6qz3N61IEF7kVH5TNZpSs0a2pqABkssE,6427
9
+ llm_ide_rules/agents/github.py,sha256=NZse_v5bogIyiUq0eBozZUrP0tzyYCcgiUfRpURmfNE,8196
10
+ llm_ide_rules/agents/opencode.py,sha256=GRtuJf8LU75KY9By4g0-Cr5e212rFeO4VnA64gnhdEk,4241
11
+ llm_ide_rules/agents/vscode.py,sha256=Xlte0I1TXTMV_F57hOY-6hROnh8L7arAOYXYRveAP6I,2764
12
+ llm_ide_rules/commands/config.py,sha256=_aVbQ4L39rYi5sQAQvK7Nd_AaMFHxn3ardNf_283mW0,1377
13
+ llm_ide_rules/commands/delete.py,sha256=8x0x6Hl0x-tKGy6X9yDggwREEKPUfNJ6NIanoxF05lM,9819
14
+ llm_ide_rules/commands/download.py,sha256=H0NX116aK1PahGTON8Ei5zysViAEIjDy_QF72OPXp4k,15189
15
+ llm_ide_rules/commands/explode.py,sha256=m8QUKzfX3-yRjMO4Rxwv_DPpZwBhumcaggarem99IH0,10989
16
+ llm_ide_rules/commands/implode.py,sha256=CEFcQkUCD8F1X3gpUscKr769qwCU8Lirg4Pp1-bPM7w,7126
17
+ llm_ide_rules/commands/mcp.py,sha256=KDG5RBVay6zK81RV9Msk4JJmQOpBKRsxA1JuKydzrRQ,3688
18
+ llm_ide_rules/constants.py,sha256=i1fWk39ZmtMgsf71xwWNCn-2U_2zOfJyVxCZ4JXJ_Ow,437
19
+ llm_ide_rules/log.py,sha256=hfkCLaTf2juQ7n67BYNREUrFxXDh6hqNcN2Pt9YTOo8,322
20
+ llm_ide_rules/markdown_parser.py,sha256=-S3sxrfFe1DRkNdu0dgUId1SMhUnfCZFMm9P7CZagUs,3418
21
+ llm_ide_rules/mcp/__init__.py,sha256=g73PAMhN7jDqmTBGskWJg2atpPj_-tiVY9ww7YqO2Yw,118
22
+ llm_ide_rules/mcp/models.py,sha256=gYzhgdWQwhH3pmj6OWVFWNNKRgxcblXeE3car2Tv8O4,440
23
+ llm_ide_rules/utils.py,sha256=n4gS-97pE1BE1ImypEvLUNbdAhxxHvtbZDvaIdciCgY,4288
24
+ llm_ide_rules-0.8.0.dist-info/WHEEL,sha256=XV0cjMrO7zXhVAIyyc8aFf1VjZ33Fen4IiJk5zFlC3g,80
25
+ llm_ide_rules-0.8.0.dist-info/entry_points.txt,sha256=xsALXWBwSEifz-2Mike7s2SwqNu1taLs_-EcmGrONeM,54
26
+ llm_ide_rules-0.8.0.dist-info/METADATA,sha256=bse_eIJTkQ0-YoNSY7V2NSS-ARvMurpMEXcSkPKs7_k,5397
27
+ llm_ide_rules-0.8.0.dist-info/RECORD,,
@@ -1,23 +0,0 @@
1
- llm_ide_rules/__init__.py,sha256=jr4i_EenGGu4xPpuAdZYEA3oOQZCBau5v65uFJr8YsM,2201
2
- llm_ide_rules/__main__.py,sha256=8maIDGnEcSUBs9lXg7YEevCXPC0fisYPC2gAEXHfHGM,145
3
- llm_ide_rules/agents/__init__.py,sha256=-KfKLr_qG26t2OXi1dA-gCesPDqS1ARGa6hELdoyCo0,905
4
- llm_ide_rules/agents/base.py,sha256=BZCW-Ikmj-YsZzqzE5GOsWg68uOlSeCztENmqOZOYLo,10434
5
- llm_ide_rules/agents/claude.py,sha256=07qKYmrX1ScWhLATK3sRClhddbb8iaJd9ZiaUdhb8aA,3176
6
- llm_ide_rules/agents/cursor.py,sha256=3nfbagRtAMXhyPVY6rpOe-XnEJVHOZiVIW9hKeTmSPg,5939
7
- llm_ide_rules/agents/gemini.py,sha256=sALl6NuX9wNL0cQ5UYclDQOBt-MlF1TUpPnW5Bk9i4g,5518
8
- llm_ide_rules/agents/github.py,sha256=aEilEXCiRmRLtCpArhzRO12ZyqL6-sGKczvmQbGzlLE,6950
9
- llm_ide_rules/agents/opencode.py,sha256=6aOwfns2DvynvWNSpidjyK3erxEahfa7bUJeml_APhg,3993
10
- llm_ide_rules/commands/delete.py,sha256=m8hSDD5jruj6QN0w8zuRmrmX-SfscXjuEWwrGy3v0fs,5490
11
- llm_ide_rules/commands/download.py,sha256=X6RAPXXXX5aseTWZHFTzHTrbzGP6GMofsZAC4iyO-oQ,14384
12
- llm_ide_rules/commands/explode.py,sha256=auCx-LqRee93zHv7CqISDp_uiCK_xrEJWlrMBuKD4Dg,9384
13
- llm_ide_rules/commands/implode.py,sha256=KHaOkkpz4vqAXhQh-iE5ftvrtDtFuSz0itXNQpKigls,6971
14
- llm_ide_rules/commands/mcp.py,sha256=61juJyWe7BQrOisWH67-ynTBe3xjBPGq-s-HAzPWVrU,3680
15
- llm_ide_rules/constants.py,sha256=WDz1_LFKzQe3m2pM8nCrDS47a16OMKFMZo2VK3rkX7E,427
16
- llm_ide_rules/log.py,sha256=hfkCLaTf2juQ7n67BYNREUrFxXDh6hqNcN2Pt9YTOo8,322
17
- llm_ide_rules/markdown_parser.py,sha256=-S3sxrfFe1DRkNdu0dgUId1SMhUnfCZFMm9P7CZagUs,3418
18
- llm_ide_rules/mcp/__init__.py,sha256=g73PAMhN7jDqmTBGskWJg2atpPj_-tiVY9ww7YqO2Yw,118
19
- llm_ide_rules/mcp/models.py,sha256=gYzhgdWQwhH3pmj6OWVFWNNKRgxcblXeE3car2Tv8O4,440
20
- llm_ide_rules-0.7.0.dist-info/WHEEL,sha256=XV0cjMrO7zXhVAIyyc8aFf1VjZ33Fen4IiJk5zFlC3g,80
21
- llm_ide_rules-0.7.0.dist-info/entry_points.txt,sha256=xsALXWBwSEifz-2Mike7s2SwqNu1taLs_-EcmGrONeM,54
22
- llm_ide_rules-0.7.0.dist-info/METADATA,sha256=uuHchmwl2QlV-V_CXT76NgVD7vqvBeo3MDKWjDt7qX4,5355
23
- llm_ide_rules-0.7.0.dist-info/RECORD,,