llm-ide-rules 0.5.0__py3-none-any.whl → 0.7.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/__init__.py +53 -9
- llm_ide_rules/__main__.py +1 -1
- llm_ide_rules/agents/__init__.py +28 -0
- llm_ide_rules/agents/base.py +329 -0
- llm_ide_rules/agents/claude.py +108 -0
- llm_ide_rules/agents/cursor.py +199 -0
- llm_ide_rules/agents/gemini.py +177 -0
- llm_ide_rules/agents/github.py +212 -0
- llm_ide_rules/agents/opencode.py +130 -0
- llm_ide_rules/commands/delete.py +24 -34
- llm_ide_rules/commands/download.py +146 -60
- llm_ide_rules/commands/explode.py +222 -382
- llm_ide_rules/commands/implode.py +174 -360
- llm_ide_rules/commands/mcp.py +119 -0
- llm_ide_rules/constants.py +6 -29
- llm_ide_rules/log.py +9 -0
- llm_ide_rules/markdown_parser.py +108 -0
- llm_ide_rules/mcp/__init__.py +7 -0
- llm_ide_rules/mcp/models.py +21 -0
- {llm_ide_rules-0.5.0.dist-info → llm_ide_rules-0.7.0.dist-info}/METADATA +36 -59
- llm_ide_rules-0.7.0.dist-info/RECORD +23 -0
- {llm_ide_rules-0.5.0.dist-info → llm_ide_rules-0.7.0.dist-info}/WHEEL +2 -2
- llm_ide_rules/sections.json +0 -27
- llm_ide_rules-0.5.0.dist-info/RECORD +0 -12
- {llm_ide_rules-0.5.0.dist-info → llm_ide_rules-0.7.0.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"""
|
|
2
|
+
MCP configuration management commands.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import json5
|
|
6
|
+
import typer
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
from llm_ide_rules.agents import get_agent, get_all_agents
|
|
10
|
+
from llm_ide_rules.mcp import McpConfig
|
|
11
|
+
from llm_ide_rules.log import log
|
|
12
|
+
|
|
13
|
+
mcp_app = typer.Typer(help="MCP configuration management")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@mcp_app.command()
|
|
17
|
+
def explode(
|
|
18
|
+
input_file: str = typer.Argument("mcp.json", help="Input unified MCP config file"),
|
|
19
|
+
scope: str = typer.Option(
|
|
20
|
+
"project", "--scope", "-s", help="Scope: project, global, or both"
|
|
21
|
+
),
|
|
22
|
+
agent: str = typer.Option(
|
|
23
|
+
"all",
|
|
24
|
+
"--agent",
|
|
25
|
+
"-a",
|
|
26
|
+
help="Agent: claude, cursor, gemini, opencode, copilot, or all",
|
|
27
|
+
),
|
|
28
|
+
) -> None:
|
|
29
|
+
"""Convert unified mcp.json to platform-specific configs."""
|
|
30
|
+
input_path = Path(input_file)
|
|
31
|
+
if not input_path.exists():
|
|
32
|
+
log.error("input file not found", file=input_file)
|
|
33
|
+
raise typer.Exit(1)
|
|
34
|
+
|
|
35
|
+
config = McpConfig.model_validate(json5.loads(input_path.read_text()))
|
|
36
|
+
|
|
37
|
+
if agent == "all":
|
|
38
|
+
agents = get_all_agents()
|
|
39
|
+
else:
|
|
40
|
+
agents = [get_agent(agent)]
|
|
41
|
+
|
|
42
|
+
for ag in agents:
|
|
43
|
+
if not ag.mcp_project_path:
|
|
44
|
+
continue
|
|
45
|
+
|
|
46
|
+
mcp_project_path = ag.mcp_project_path
|
|
47
|
+
|
|
48
|
+
servers = {
|
|
49
|
+
name: ag.transform_mcp_server(s) for name, s in config.servers.items()
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if scope in ("project", "both"):
|
|
53
|
+
project_path = Path.cwd() / mcp_project_path
|
|
54
|
+
ag.write_mcp_config(servers, project_path)
|
|
55
|
+
log.info("wrote project config", agent=ag.name, path=str(project_path))
|
|
56
|
+
|
|
57
|
+
if scope in ("global", "both") and ag.mcp_global_path:
|
|
58
|
+
global_path = Path.home() / ag.mcp_global_path
|
|
59
|
+
ag.write_mcp_config(servers, global_path)
|
|
60
|
+
log.info("wrote global config", agent=ag.name, path=str(global_path))
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@mcp_app.command()
|
|
64
|
+
def implode(
|
|
65
|
+
output_file: str = typer.Argument(
|
|
66
|
+
"mcp.json", help="Output unified MCP config file"
|
|
67
|
+
),
|
|
68
|
+
source: str = typer.Option(
|
|
69
|
+
None, "--source", help="Source agent to read from (e.g., claude, cursor)"
|
|
70
|
+
),
|
|
71
|
+
scope: str = typer.Option(
|
|
72
|
+
"project", "--scope", "-s", help="Scope: project or global"
|
|
73
|
+
),
|
|
74
|
+
) -> None:
|
|
75
|
+
"""Merge platform-specific MCP configs into unified mcp.json."""
|
|
76
|
+
if not source:
|
|
77
|
+
log.error("source agent must be specified")
|
|
78
|
+
raise typer.Exit(1)
|
|
79
|
+
|
|
80
|
+
ag = get_agent(source)
|
|
81
|
+
|
|
82
|
+
if scope == "project":
|
|
83
|
+
mcp_project_path = ag.mcp_project_path
|
|
84
|
+
if not mcp_project_path:
|
|
85
|
+
log.error("project config path not defined for agent", agent=source)
|
|
86
|
+
raise typer.Exit(1)
|
|
87
|
+
source_path = Path.cwd() / mcp_project_path
|
|
88
|
+
else:
|
|
89
|
+
mcp_global_path = ag.mcp_global_path
|
|
90
|
+
if not mcp_global_path:
|
|
91
|
+
log.error("global config path not defined for agent", agent=source)
|
|
92
|
+
raise typer.Exit(1)
|
|
93
|
+
source_path = Path.home() / mcp_global_path
|
|
94
|
+
|
|
95
|
+
if not source_path.exists():
|
|
96
|
+
log.error("source config not found", path=str(source_path))
|
|
97
|
+
raise typer.Exit(1)
|
|
98
|
+
|
|
99
|
+
server_configs = ag.read_mcp_config(source_path)
|
|
100
|
+
if not server_configs:
|
|
101
|
+
log.error("no MCP servers found in config", path=str(source_path))
|
|
102
|
+
raise typer.Exit(1)
|
|
103
|
+
|
|
104
|
+
servers = {
|
|
105
|
+
name: ag.reverse_transform_mcp_server(name, config)
|
|
106
|
+
for name, config in server_configs.items()
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
config = McpConfig(servers=servers)
|
|
110
|
+
output_path = Path(output_file)
|
|
111
|
+
|
|
112
|
+
import json
|
|
113
|
+
|
|
114
|
+
output_path.write_text(
|
|
115
|
+
json.dumps(
|
|
116
|
+
config.model_dump(exclude_none=True, exclude_defaults=True), indent=2
|
|
117
|
+
)
|
|
118
|
+
)
|
|
119
|
+
log.info("wrote unified config", path=str(output_path))
|
llm_ide_rules/constants.py
CHANGED
|
@@ -1,36 +1,13 @@
|
|
|
1
1
|
"""Shared constants for explode and implode functionality."""
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
import os
|
|
5
|
-
from pathlib import Path
|
|
3
|
+
VALID_AGENTS = ["cursor", "github", "claude", "gemini", "opencode", "all"]
|
|
6
4
|
|
|
7
|
-
def load_section_globs(custom_config_path: str = None) -> dict:
|
|
8
|
-
"""Load section globs from JSON config file.
|
|
9
|
-
|
|
10
|
-
Args:
|
|
11
|
-
custom_config_path: Path to custom configuration file to override defaults
|
|
12
|
-
|
|
13
|
-
Returns:
|
|
14
|
-
Dictionary mapping section headers to their file globs or None for prompts
|
|
15
|
-
"""
|
|
16
|
-
if custom_config_path and os.path.exists(custom_config_path):
|
|
17
|
-
config_path = Path(custom_config_path)
|
|
18
|
-
else:
|
|
19
|
-
# Load default bundled config
|
|
20
|
-
config_path = Path(__file__).parent / "sections.json"
|
|
21
|
-
|
|
22
|
-
with open(config_path, 'r') as f:
|
|
23
|
-
config = json.load(f)
|
|
24
|
-
|
|
25
|
-
return config["section_globs"]
|
|
26
5
|
|
|
27
|
-
|
|
28
|
-
SECTION_GLOBS = load_section_globs()
|
|
29
|
-
|
|
30
|
-
def header_to_filename(header):
|
|
6
|
+
def header_to_filename(header: str) -> str:
|
|
31
7
|
"""Convert a section header to a filename."""
|
|
32
|
-
return header.lower().replace(
|
|
8
|
+
return header.lower().replace(" ", "-")
|
|
9
|
+
|
|
33
10
|
|
|
34
|
-
def filename_to_header(filename):
|
|
11
|
+
def filename_to_header(filename: str) -> str:
|
|
35
12
|
"""Convert a filename back to a section header."""
|
|
36
|
-
return filename.replace(
|
|
13
|
+
return filename.replace("-", " ").title()
|
llm_ide_rules/log.py
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"""Centralized logging configuration using structlog-config.
|
|
2
|
+
|
|
3
|
+
This module configures structlog with opinionated defaults and exports a global logger.
|
|
4
|
+
Import the `log` object from this module to use structured logging throughout the application.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from structlog_config import configure_logger
|
|
8
|
+
|
|
9
|
+
log = configure_logger()
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"""Markdown parsing utilities using markdown-it-py."""
|
|
2
|
+
|
|
3
|
+
from typing import NamedTuple
|
|
4
|
+
|
|
5
|
+
from markdown_it import MarkdownIt
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SectionData(NamedTuple):
|
|
9
|
+
"""Data for a parsed section."""
|
|
10
|
+
|
|
11
|
+
content: list[str]
|
|
12
|
+
glob_pattern: str | None
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def extract_glob_directive(
|
|
16
|
+
content_lines: list[str],
|
|
17
|
+
) -> tuple[list[str], str | None]:
|
|
18
|
+
"""Extract glob directive from section content if present.
|
|
19
|
+
|
|
20
|
+
Checks the first non-empty line after the header for 'globs: PATTERN'.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
content_lines: Lines including the header
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
Tuple of (content_without_directive, glob_pattern)
|
|
27
|
+
- glob_pattern is None if no directive found (means alwaysApply)
|
|
28
|
+
- glob_pattern is "manual" for manual-only sections
|
|
29
|
+
"""
|
|
30
|
+
if not content_lines:
|
|
31
|
+
return content_lines, None
|
|
32
|
+
|
|
33
|
+
header_idx = None
|
|
34
|
+
for i, line in enumerate(content_lines):
|
|
35
|
+
if line.startswith("## "):
|
|
36
|
+
header_idx = i
|
|
37
|
+
break
|
|
38
|
+
|
|
39
|
+
if header_idx is None:
|
|
40
|
+
return content_lines, None
|
|
41
|
+
|
|
42
|
+
for i in range(header_idx + 1, len(content_lines)):
|
|
43
|
+
line = content_lines[i].strip()
|
|
44
|
+
if not line:
|
|
45
|
+
continue
|
|
46
|
+
|
|
47
|
+
if line.lower().startswith("globs: "):
|
|
48
|
+
glob_value = line[7:].strip()
|
|
49
|
+
filtered_content = content_lines[:i] + content_lines[i + 1 :]
|
|
50
|
+
return filtered_content, glob_value
|
|
51
|
+
|
|
52
|
+
break
|
|
53
|
+
|
|
54
|
+
return content_lines, None
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def parse_sections(text: str) -> tuple[list[str], dict[str, SectionData]]:
|
|
58
|
+
"""Parse markdown text into general section and named sections.
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
Tuple of (general_lines, sections_dict) where:
|
|
62
|
+
- general_lines: Lines before the first H2 header
|
|
63
|
+
- sections_dict: Dict mapping section names to SectionData (content + glob_pattern)
|
|
64
|
+
"""
|
|
65
|
+
md = MarkdownIt()
|
|
66
|
+
tokens = md.parse(text)
|
|
67
|
+
lines = text.splitlines(keepends=True)
|
|
68
|
+
|
|
69
|
+
# Find all H2 headers
|
|
70
|
+
section_starts = []
|
|
71
|
+
for i, token in enumerate(tokens):
|
|
72
|
+
if token.type == "heading_open" and token.tag == "h2":
|
|
73
|
+
# Get the content of the header
|
|
74
|
+
# The next token is usually inline, which contains the text
|
|
75
|
+
if i + 1 < len(tokens) and tokens[i + 1].type == "inline":
|
|
76
|
+
header_content = tokens[i + 1].content.strip()
|
|
77
|
+
# token.map contains [start_line, end_line] (0-based)
|
|
78
|
+
if token.map:
|
|
79
|
+
start_line = token.map[0]
|
|
80
|
+
section_starts.append((start_line, header_content))
|
|
81
|
+
|
|
82
|
+
if not section_starts:
|
|
83
|
+
return lines, {}
|
|
84
|
+
|
|
85
|
+
# Extract general content (everything before first H2)
|
|
86
|
+
first_section_start = section_starts[0][0]
|
|
87
|
+
general_lines = lines[:first_section_start]
|
|
88
|
+
|
|
89
|
+
# Extract named sections
|
|
90
|
+
sections = {}
|
|
91
|
+
for i, (start_line, header_name) in enumerate(section_starts):
|
|
92
|
+
# End line is the start of the next section, or end of file
|
|
93
|
+
if i + 1 < len(section_starts):
|
|
94
|
+
end_line = section_starts[i + 1][0]
|
|
95
|
+
else:
|
|
96
|
+
end_line = len(lines)
|
|
97
|
+
|
|
98
|
+
# Extract all lines for this section
|
|
99
|
+
section_content = lines[start_line:end_line]
|
|
100
|
+
|
|
101
|
+
# Extract glob directive if present
|
|
102
|
+
filtered_content, glob_pattern = extract_glob_directive(section_content)
|
|
103
|
+
|
|
104
|
+
sections[header_name] = SectionData(
|
|
105
|
+
content=filtered_content, glob_pattern=glob_pattern
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
return general_lines, sections
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Pydantic models for unified MCP configuration.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, Field
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class McpServer(BaseModel):
|
|
9
|
+
"""Unified MCP server definition."""
|
|
10
|
+
|
|
11
|
+
command: str | None = None
|
|
12
|
+
args: list[str] = Field(default_factory=list)
|
|
13
|
+
url: str | None = None
|
|
14
|
+
type: str | None = None
|
|
15
|
+
env: dict[str, str] | None = None
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class McpConfig(BaseModel):
|
|
19
|
+
"""Unified mcp.json format."""
|
|
20
|
+
|
|
21
|
+
servers: dict[str, McpServer]
|
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: llm-ide-rules
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.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
|
|
7
7
|
Author-email: Michael Bianco <mike@mikebian.co>
|
|
8
8
|
Requires-Dist: typer>=0.9.0
|
|
9
|
-
Requires-Dist: structlog>=
|
|
9
|
+
Requires-Dist: structlog-config>=0.6.0
|
|
10
10
|
Requires-Dist: requests>=2.25.0
|
|
11
|
-
Requires-
|
|
11
|
+
Requires-Dist: pydantic>=2.0.0
|
|
12
|
+
Requires-Dist: json5>=0.9.0
|
|
13
|
+
Requires-Dist: tomli-w>=1.0.0
|
|
14
|
+
Requires-Dist: markdown-it-py>=4.0.0
|
|
15
|
+
Requires-Python: >=3.11
|
|
12
16
|
Project-URL: Repository, https://github.com/iloveitaly/llm-ide-rules
|
|
13
17
|
Description-Content-Type: text/markdown
|
|
14
18
|
|
|
15
19
|
# Copilot, Cursor, Claude, Gemini, etc LLM Instructions
|
|
16
20
|
|
|
17
|
-
|
|
21
|
+
This project makes it easy to download prompts and implode/explode them so they can be used by various providers.
|
|
18
22
|
|
|
19
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.
|
|
20
24
|
|
|
@@ -22,25 +26,28 @@ Additionally, it becomes challenging to copy these prompts into various projects
|
|
|
22
26
|
|
|
23
27
|
Some of the glob assumptions in this repo are specific to how I've chosen to organize python and typescript [in the python starter template](https://github.com/iloveitaly/python-starter-template) and what tooling (fastapi, etc) that I've chosen to use.
|
|
24
28
|
|
|
25
|
-
##
|
|
26
|
-
|
|
27
|
-
You can run the `llm-ide-rules` CLI tool using uvx:
|
|
29
|
+
## IDE Format Comparison
|
|
28
30
|
|
|
29
|
-
|
|
30
|
-
uvx llm-ide-rules
|
|
31
|
-
```
|
|
31
|
+
Different AI coding assistants use different formats for instructions and commands:
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
| IDE | type | folder | Notes |
|
|
34
|
+
|-----|------|--------|-------|
|
|
35
|
+
| **Cursor** | instructions | `.cursor/rules/*.mdc` | Multiple plain markdown files |
|
|
36
|
+
| **Cursor** | commands | `.cursor/commands/*.md` | Plain markdown, no frontmatter |
|
|
37
|
+
| **Claude Code** | instructions | `CLAUDE.md` | Single markdown file at root |
|
|
38
|
+
| **Claude Code** | instructions | `AGENT.md` | Single markdown file at root (agent-specific) |
|
|
39
|
+
| **Claude Code** | commands | `.claude/commands/*.md` | Plain markdown, no frontmatter |
|
|
40
|
+
| **GitHub Copilot** | instructions | `.github/copilot-instructions.md` | Single markdown file |
|
|
41
|
+
| **GitHub Copilot** | instructions | `.github/instructions/*.instructions.md` | Multiple instruction files |
|
|
42
|
+
| **GitHub Copilot** | prompts | `.github/prompts/*.prompt.md` | YAML frontmatter with `mode: 'agent'` |
|
|
43
|
+
| **Gemini CLI** | instructions | `GEMINI.md` | Single markdown file at root |
|
|
44
|
+
| **Gemini CLI** | commands | `.gemini/commands/*.toml` | TOML format, supports `{{args}}` and shell commands |
|
|
45
|
+
| **OpenCode** | commands | `.opencode/commands/*.md` | Plain markdown, no frontmatter |
|
|
34
46
|
|
|
35
|
-
|
|
36
|
-
uv tool install git+https://github.com/iloveitaly/llm-ide-rules.git
|
|
37
|
-
```
|
|
47
|
+
## Installation
|
|
38
48
|
|
|
39
49
|
```sh
|
|
40
|
-
|
|
41
|
-
cd llm-ide-rules
|
|
42
|
-
uv sync
|
|
43
|
-
source .venv/bin/activate
|
|
50
|
+
uvx llm-ide-rules@latest --help
|
|
44
51
|
```
|
|
45
52
|
|
|
46
53
|
## Usage
|
|
@@ -55,7 +62,10 @@ uvx llm-ide-rules explode [input_file]
|
|
|
55
62
|
|
|
56
63
|
# Bundle rule files back into a single instruction file
|
|
57
64
|
uvx llm-ide-rules implode cursor [output_file] # Bundle Cursor rules
|
|
58
|
-
uvx llm-ide-rules implode github [output_file]
|
|
65
|
+
uvx llm-ide-rules implode github [output_file] # Bundle GitHub/Copilot instructions
|
|
66
|
+
uvx llm-ide-rules implode claude [output_file] # Bundle Claude Code commands
|
|
67
|
+
uvx llm-ide-rules implode gemini [output_file] # Bundle Gemini CLI commands
|
|
68
|
+
uvx llm-ide-rules implode opencode [output_file] # Bundle OpenCode commands
|
|
59
69
|
|
|
60
70
|
# Download instruction files from repositories
|
|
61
71
|
uvx llm-ide-rules download [instruction_types] # Download everything by default
|
|
@@ -66,21 +76,26 @@ uvx llm-ide-rules download --repo other/repo # Download from different repo
|
|
|
66
76
|
uvx llm-ide-rules delete [instruction_types] # Delete everything by default
|
|
67
77
|
uvx llm-ide-rules delete cursor gemini # Delete specific types
|
|
68
78
|
uvx llm-ide-rules delete --yes # Skip confirmation prompt
|
|
69
|
-
|
|
70
79
|
```
|
|
71
80
|
|
|
72
81
|
### Examples
|
|
73
82
|
|
|
74
83
|
```sh
|
|
75
|
-
# Explode instructions.md into
|
|
84
|
+
# Explode instructions.md into all supported formats (cursor, github, claude, gemini, opencode)
|
|
76
85
|
uvx llm-ide-rules explode instructions.md
|
|
77
86
|
|
|
87
|
+
# Explode for a specific agent only
|
|
88
|
+
uvx llm-ide-rules explode instructions.md --agent opencode
|
|
89
|
+
|
|
78
90
|
# Bundle Cursor rules back into a single file
|
|
79
91
|
uvx llm-ide-rules implode cursor bundled-instructions.md
|
|
80
92
|
|
|
81
93
|
# Bundle GitHub instructions with verbose logging
|
|
82
94
|
uvx llm-ide-rules implode github --verbose instructions.md
|
|
83
95
|
|
|
96
|
+
# Bundle OpenCode commands into commands.md
|
|
97
|
+
uvx llm-ide-rules implode opencode
|
|
98
|
+
|
|
84
99
|
# Download everything from default repository
|
|
85
100
|
uvx llm-ide-rules download
|
|
86
101
|
|
|
@@ -100,44 +115,6 @@ uvx llm-ide-rules delete cursor gemini --target ./my-project
|
|
|
100
115
|
uvx llm-ide-rules delete --yes
|
|
101
116
|
```
|
|
102
117
|
|
|
103
|
-
### IDE Command Format Comparison
|
|
104
|
-
|
|
105
|
-
Different AI coding assistants use different formats for commands:
|
|
106
|
-
|
|
107
|
-
| IDE | Directory | Format | Notes |
|
|
108
|
-
|-----|-----------|--------|-------|
|
|
109
|
-
| **Cursor** | `.cursor/commands/` | `.md` (plain markdown) | Simple, no frontmatter |
|
|
110
|
-
| **Claude Code** | `.claude/commands/` | `.md` (plain markdown) | Simple, no frontmatter |
|
|
111
|
-
| **GitHub Copilot** | `.github/prompts/` | `.prompt.md` (YAML + markdown) | Requires frontmatter with `mode: 'agent'` |
|
|
112
|
-
| **Gemini CLI** | `.gemini/commands/` | `.toml` | Uses TOML format, supports `{{args}}` and shell commands |
|
|
113
|
-
|
|
114
|
-
## Development
|
|
115
|
-
|
|
116
|
-
### Using the CLI for Development
|
|
117
|
-
|
|
118
|
-
The CLI replaces the old standalone scripts. Use the CLI commands in your development workflow:
|
|
119
|
-
|
|
120
|
-
```shell
|
|
121
|
-
# Setup the environment
|
|
122
|
-
uv sync
|
|
123
|
-
|
|
124
|
-
# Explode instructions into separate rule files
|
|
125
|
-
uvx llm-ide-rules explode
|
|
126
|
-
|
|
127
|
-
# Bundle rules back into instructions
|
|
128
|
-
uvx llm-ide-rules implode cursor instructions.md
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
### Building and Testing
|
|
132
|
-
|
|
133
|
-
```shell
|
|
134
|
-
# Build the package
|
|
135
|
-
uv build
|
|
136
|
-
|
|
137
|
-
# Run tests
|
|
138
|
-
pytest
|
|
139
|
-
```
|
|
140
|
-
|
|
141
118
|
## Extracting Changes
|
|
142
119
|
|
|
143
120
|
The idea of this repo is you'll copy prompts into your various projects. Then, if you improve a prompt in a project, you can pull that change into this upstream repo.
|
|
@@ -0,0 +1,23 @@
|
|
|
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,,
|
llm_ide_rules/sections.json
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"section_globs": {
|
|
3
|
-
"Python": "**/*.py",
|
|
4
|
-
"Python App": "**/*.py",
|
|
5
|
-
"Pytest Integration Tests": "tests/integration/**/*.py",
|
|
6
|
-
"Pytest Tests": "tests/**/*.py",
|
|
7
|
-
"Python Route Tests": "tests/routes/**/*.py",
|
|
8
|
-
"Alembic Migrations": "migrations/versions/*.py",
|
|
9
|
-
"FastAPI": "app/routes/**/*.py",
|
|
10
|
-
"React": "**/*.tsx",
|
|
11
|
-
"React Router": "web/app/routes/**/*.tsx",
|
|
12
|
-
"React Router Client Loader": null,
|
|
13
|
-
"Shell": "**/*.sh",
|
|
14
|
-
"TypeScript": "**/*.ts,**/*.tsx",
|
|
15
|
-
"TypeScript DocString": null,
|
|
16
|
-
"Secrets": null,
|
|
17
|
-
"Dev In Browser": null,
|
|
18
|
-
"Fastapi Stripe": null,
|
|
19
|
-
"Fix Tests": null,
|
|
20
|
-
"Implement Fastapi Routes": null,
|
|
21
|
-
"Plan Only": null,
|
|
22
|
-
"Python Command": null,
|
|
23
|
-
"Refactor On Instructions": null,
|
|
24
|
-
"Standalone Python Scripts": null,
|
|
25
|
-
"Stripe Backend": null
|
|
26
|
-
}
|
|
27
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
llm_ide_rules/__init__.py,sha256=494c58df084291e4e427a1a36f78306224ea83305531dcff5c566c2fb53e16ce,1472
|
|
2
|
-
llm_ide_rules/__main__.py,sha256=881447dbad0fe837590fa8224f1d0dd70416fd5344779978d07744ff8e0cf868,144
|
|
3
|
-
llm_ide_rules/commands/delete.py,sha256=6ed0a44b1be1d950180831681d79e3a0be91cd37296e30e7a0d821d49292ebf4,5812
|
|
4
|
-
llm_ide_rules/commands/download.py,sha256=06c2a841db5fe0b0f7f3e8c99ad198c8e07e53d8801fb4d95e802ecee60cda31,11022
|
|
5
|
-
llm_ide_rules/commands/explode.py,sha256=59df4bb542397c9204332ba563a95c49d236a82ebc6af81378b2798f8adc2e77,14779
|
|
6
|
-
llm_ide_rules/commands/implode.py,sha256=f3e9ff754530c06d7eacb20fc37ae8d958218f02df2a0f48eac1d5c6a9a749be,16743
|
|
7
|
-
llm_ide_rules/constants.py,sha256=1182b9757ca58d038a4878d1b55570aac4f0287f1a5ab5af8d68331b799b0686,1118
|
|
8
|
-
llm_ide_rules/sections.json,sha256=e82bf37f8a7bd919c881d7cc084cdfd82e1f9e6ff5385c74b18c14996bcac3c1,822
|
|
9
|
-
llm_ide_rules-0.5.0.dist-info/WHEEL,sha256=0f7d664a881437bddec71c703c3c2f01fd13581519f95130abcc96e296ef0426,79
|
|
10
|
-
llm_ide_rules-0.5.0.dist-info/entry_points.txt,sha256=c6c00b5d607048489fcfed8c8a47bbb364b0a8dbb5b5a2ecffe11c986ace35e3,54
|
|
11
|
-
llm_ide_rules-0.5.0.dist-info/METADATA,sha256=af671c42110d55d0670a3aef9007b890dcb5d6335add807d36d8baadf3e802a3,4898
|
|
12
|
-
llm_ide_rules-0.5.0.dist-info/RECORD,,
|
|
File without changes
|