msl 0.1.0__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.
- msl-0.1.0/LICENSE +21 -0
- msl-0.1.0/MANIFEST.in +3 -0
- msl-0.1.0/PKG-INFO +130 -0
- msl-0.1.0/README.md +99 -0
- msl-0.1.0/pyproject.toml +55 -0
- msl-0.1.0/setup.cfg +4 -0
- msl-0.1.0/src/msl/__init__.py +3 -0
- msl-0.1.0/src/msl/cli.py +51 -0
- msl-0.1.0/src/msl/detection.py +97 -0
- msl-0.1.0/src/msl/models.py +80 -0
- msl-0.1.0/src/msl/path_rules.py +28 -0
- msl-0.1.0/src/msl/scanner.py +376 -0
- msl-0.1.0/src/msl/skills/flutter/industry_standard.md +87 -0
- msl-0.1.0/src/msl/skills/flutter/intermediate.md +46 -0
- msl-0.1.0/src/msl/skills/flutter/simple.md +20 -0
- msl-0.1.0/src/msl/skills/go-server/industry_standard.md +89 -0
- msl-0.1.0/src/msl/skills/go-server/intermediate.md +53 -0
- msl-0.1.0/src/msl/skills/go-server/simple.md +19 -0
- msl-0.1.0/src/msl/skills/nextjs/industry_standard.md +88 -0
- msl-0.1.0/src/msl/skills/nextjs/intermediate.md +46 -0
- msl-0.1.0/src/msl/skills/nextjs/simple.md +21 -0
- msl-0.1.0/src/msl/skills/nodejs-server/industry_standard.md +91 -0
- msl-0.1.0/src/msl/skills/nodejs-server/intermediate.md +49 -0
- msl-0.1.0/src/msl/skills/nodejs-server/simple.md +20 -0
- msl-0.1.0/src/msl/skills/python/industry_standard.md +86 -0
- msl-0.1.0/src/msl/skills/python/intermediate.md +48 -0
- msl-0.1.0/src/msl/skills/python/simple.md +20 -0
- msl-0.1.0/src/msl/skills/react-vite/industry_standard.md +80 -0
- msl-0.1.0/src/msl/skills/react-vite/intermediate.md +44 -0
- msl-0.1.0/src/msl/skills/react-vite/simple.md +19 -0
- msl-0.1.0/src/msl/skills/rust-server/industry_standard.md +87 -0
- msl-0.1.0/src/msl/skills/rust-server/intermediate.md +45 -0
- msl-0.1.0/src/msl/skills/rust-server/simple.md +19 -0
- msl-0.1.0/src/msl/templates.py +40 -0
- msl-0.1.0/src/msl/ui.py +314 -0
- msl-0.1.0/src/msl/writer.py +63 -0
- msl-0.1.0/src/msl.egg-info/PKG-INFO +130 -0
- msl-0.1.0/src/msl.egg-info/SOURCES.txt +45 -0
- msl-0.1.0/src/msl.egg-info/dependency_links.txt +1 -0
- msl-0.1.0/src/msl.egg-info/entry_points.txt +2 -0
- msl-0.1.0/src/msl.egg-info/requires.txt +2 -0
- msl-0.1.0/src/msl.egg-info/top_level.txt +1 -0
- msl-0.1.0/tests/test_detection.py +101 -0
- msl-0.1.0/tests/test_path_rules.py +32 -0
- msl-0.1.0/tests/test_scanner.py +156 -0
- msl-0.1.0/tests/test_templates.py +51 -0
- msl-0.1.0/tests/test_writer.py +73 -0
msl-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Murad
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
msl-0.1.0/MANIFEST.in
ADDED
msl-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: msl
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: MSL — Muradian Skill Languages: Generate platform-specific skill files for AI coding assistants
|
|
5
|
+
Author: Murad
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/mozaddedalfeshani/msl
|
|
8
|
+
Project-URL: Repository, https://github.com/mozaddedalfeshani/msl
|
|
9
|
+
Project-URL: Issues, https://github.com/mozaddedalfeshani/msl/issues
|
|
10
|
+
Keywords: ai,coding-assistant,cursor,vscode,claude,codex,skill,rules,developer-tools,cli
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Software Development
|
|
23
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
24
|
+
Classifier: Typing :: Typed
|
|
25
|
+
Requires-Python: >=3.9
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Requires-Dist: rich>=13.0
|
|
29
|
+
Requires-Dist: questionary>=2.0
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
|
|
32
|
+
# MSL — Muradian Skill Languages
|
|
33
|
+
|
|
34
|
+
Generate platform-specific skill/rule files for AI coding assistants with one command. No need to remember which file goes where — `msl` handles the structure for you.
|
|
35
|
+
|
|
36
|
+
## Install
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pip install msl
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Usage
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
msl
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The wizard will:
|
|
49
|
+
|
|
50
|
+
1. **Detect** your environment (Node.js, Cursor, VS Code, Claude Code, Codex)
|
|
51
|
+
2. **Scan** your project to auto-detect frameworks, languages, package manager
|
|
52
|
+
3. **Ask** which platform to target
|
|
53
|
+
4. **Ask** your project path (current directory or custom)
|
|
54
|
+
5. **Ask** your project type (auto-suggested from scan)
|
|
55
|
+
6. **Ask** your preference level (Simple → Industry Standard)
|
|
56
|
+
7. **Generate** the correct file in the right location with project-aware content
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
╭──────────────────────────────────────╮
|
|
60
|
+
│ MSL — Muradian Skill Languages │
|
|
61
|
+
╰──────────────────────────────────────╯
|
|
62
|
+
|
|
63
|
+
Environment Check
|
|
64
|
+
✓ Node.js v20.11.0
|
|
65
|
+
✓ Cursor 0.45.0
|
|
66
|
+
✓ VS Code 1.89.1
|
|
67
|
+
✓ Claude 2.1.0
|
|
68
|
+
✓ Codex 0.72.0
|
|
69
|
+
|
|
70
|
+
Project Scan
|
|
71
|
+
Name: my-saas-app
|
|
72
|
+
Languages: TypeScript
|
|
73
|
+
Detected: Next.js, App Router, tailwindcss, prisma
|
|
74
|
+
Type: Web (Next.js) (95% confidence)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Supported Platforms
|
|
78
|
+
|
|
79
|
+
| Platform | Output Path |
|
|
80
|
+
| ----------- | --------------------------------- |
|
|
81
|
+
| Cursor | `.cursor/rules.md` |
|
|
82
|
+
| VS Code | `.github/copilot-instructions.md` |
|
|
83
|
+
| Claude Code | `CLAUDE.md` |
|
|
84
|
+
| Codex | `AGENTS.md` |
|
|
85
|
+
|
|
86
|
+
## Supported Project Types
|
|
87
|
+
|
|
88
|
+
- **Flutter** — Dart, widgets, state management, routing
|
|
89
|
+
- **Web (Next.js)** — App Router, Server Components, data fetching
|
|
90
|
+
- **Web (React/Vite)** — SPA, hooks, React Router, Zustand
|
|
91
|
+
- **Rust (Server)** — Axum/Actix, async, sqlx, error handling
|
|
92
|
+
- **Node.js (Server)** — Express/Fastify, TypeScript, Prisma
|
|
93
|
+
- **Python** — FastAPI/Flask, typed Python, pytest
|
|
94
|
+
- **Go (Server)** — Chi/Gin, structured logging, sqlx
|
|
95
|
+
|
|
96
|
+
## Preference Levels
|
|
97
|
+
|
|
98
|
+
| Level | What it includes |
|
|
99
|
+
| ----------------- | ------------------------------------------------- |
|
|
100
|
+
| Simple | Clean code basics, modular structure |
|
|
101
|
+
| Intermediate | Patterns, testing, conventions, data layer |
|
|
102
|
+
| Industry Standard | Full architecture, CI/CD, security, observability |
|
|
103
|
+
|
|
104
|
+
## Smart Features
|
|
105
|
+
|
|
106
|
+
- **Auto-detection**: Scans `package.json`, `Cargo.toml`, `pubspec.yaml`, `pyproject.toml`, `go.mod` to identify your stack
|
|
107
|
+
- **Context injection**: Appends detected project name, frameworks, and package manager to the generated file
|
|
108
|
+
- **Correct conventions**: Uses each platform's real config file path — not a generic filename
|
|
109
|
+
- **Safe writes**: Always asks before overwriting existing files
|
|
110
|
+
|
|
111
|
+
## CLI Options
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
msl # Run the interactive wizard
|
|
115
|
+
msl --version # Show version
|
|
116
|
+
msl --help # Show help
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Development
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
git clone https://github.com/murad/msl.git
|
|
123
|
+
cd msl
|
|
124
|
+
pip install -e .
|
|
125
|
+
msl
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## License
|
|
129
|
+
|
|
130
|
+
MIT
|
msl-0.1.0/README.md
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# MSL — Muradian Skill Languages
|
|
2
|
+
|
|
3
|
+
Generate platform-specific skill/rule files for AI coding assistants with one command. No need to remember which file goes where — `msl` handles the structure for you.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install msl
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
msl
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The wizard will:
|
|
18
|
+
|
|
19
|
+
1. **Detect** your environment (Node.js, Cursor, VS Code, Claude Code, Codex)
|
|
20
|
+
2. **Scan** your project to auto-detect frameworks, languages, package manager
|
|
21
|
+
3. **Ask** which platform to target
|
|
22
|
+
4. **Ask** your project path (current directory or custom)
|
|
23
|
+
5. **Ask** your project type (auto-suggested from scan)
|
|
24
|
+
6. **Ask** your preference level (Simple → Industry Standard)
|
|
25
|
+
7. **Generate** the correct file in the right location with project-aware content
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
╭──────────────────────────────────────╮
|
|
29
|
+
│ MSL — Muradian Skill Languages │
|
|
30
|
+
╰──────────────────────────────────────╯
|
|
31
|
+
|
|
32
|
+
Environment Check
|
|
33
|
+
✓ Node.js v20.11.0
|
|
34
|
+
✓ Cursor 0.45.0
|
|
35
|
+
✓ VS Code 1.89.1
|
|
36
|
+
✓ Claude 2.1.0
|
|
37
|
+
✓ Codex 0.72.0
|
|
38
|
+
|
|
39
|
+
Project Scan
|
|
40
|
+
Name: my-saas-app
|
|
41
|
+
Languages: TypeScript
|
|
42
|
+
Detected: Next.js, App Router, tailwindcss, prisma
|
|
43
|
+
Type: Web (Next.js) (95% confidence)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Supported Platforms
|
|
47
|
+
|
|
48
|
+
| Platform | Output Path |
|
|
49
|
+
| ----------- | --------------------------------- |
|
|
50
|
+
| Cursor | `.cursor/rules.md` |
|
|
51
|
+
| VS Code | `.github/copilot-instructions.md` |
|
|
52
|
+
| Claude Code | `CLAUDE.md` |
|
|
53
|
+
| Codex | `AGENTS.md` |
|
|
54
|
+
|
|
55
|
+
## Supported Project Types
|
|
56
|
+
|
|
57
|
+
- **Flutter** — Dart, widgets, state management, routing
|
|
58
|
+
- **Web (Next.js)** — App Router, Server Components, data fetching
|
|
59
|
+
- **Web (React/Vite)** — SPA, hooks, React Router, Zustand
|
|
60
|
+
- **Rust (Server)** — Axum/Actix, async, sqlx, error handling
|
|
61
|
+
- **Node.js (Server)** — Express/Fastify, TypeScript, Prisma
|
|
62
|
+
- **Python** — FastAPI/Flask, typed Python, pytest
|
|
63
|
+
- **Go (Server)** — Chi/Gin, structured logging, sqlx
|
|
64
|
+
|
|
65
|
+
## Preference Levels
|
|
66
|
+
|
|
67
|
+
| Level | What it includes |
|
|
68
|
+
| ----------------- | ------------------------------------------------- |
|
|
69
|
+
| Simple | Clean code basics, modular structure |
|
|
70
|
+
| Intermediate | Patterns, testing, conventions, data layer |
|
|
71
|
+
| Industry Standard | Full architecture, CI/CD, security, observability |
|
|
72
|
+
|
|
73
|
+
## Smart Features
|
|
74
|
+
|
|
75
|
+
- **Auto-detection**: Scans `package.json`, `Cargo.toml`, `pubspec.yaml`, `pyproject.toml`, `go.mod` to identify your stack
|
|
76
|
+
- **Context injection**: Appends detected project name, frameworks, and package manager to the generated file
|
|
77
|
+
- **Correct conventions**: Uses each platform's real config file path — not a generic filename
|
|
78
|
+
- **Safe writes**: Always asks before overwriting existing files
|
|
79
|
+
|
|
80
|
+
## CLI Options
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
msl # Run the interactive wizard
|
|
84
|
+
msl --version # Show version
|
|
85
|
+
msl --help # Show help
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Development
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
git clone https://github.com/murad/msl.git
|
|
92
|
+
cd msl
|
|
93
|
+
pip install -e .
|
|
94
|
+
msl
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## License
|
|
98
|
+
|
|
99
|
+
MIT
|
msl-0.1.0/pyproject.toml
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "msl"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "MSL — Muradian Skill Languages: Generate platform-specific skill files for AI coding assistants"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = {text = "MIT"}
|
|
11
|
+
requires-python = ">=3.9"
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "Murad"},
|
|
14
|
+
]
|
|
15
|
+
keywords = [
|
|
16
|
+
"ai", "coding-assistant", "cursor", "vscode", "claude", "codex",
|
|
17
|
+
"skill", "rules", "developer-tools", "cli",
|
|
18
|
+
]
|
|
19
|
+
classifiers = [
|
|
20
|
+
"Development Status :: 4 - Beta",
|
|
21
|
+
"Environment :: Console",
|
|
22
|
+
"Intended Audience :: Developers",
|
|
23
|
+
"License :: OSI Approved :: MIT License",
|
|
24
|
+
"Operating System :: OS Independent",
|
|
25
|
+
"Programming Language :: Python :: 3",
|
|
26
|
+
"Programming Language :: Python :: 3.9",
|
|
27
|
+
"Programming Language :: Python :: 3.10",
|
|
28
|
+
"Programming Language :: Python :: 3.11",
|
|
29
|
+
"Programming Language :: Python :: 3.12",
|
|
30
|
+
"Programming Language :: Python :: 3.13",
|
|
31
|
+
"Topic :: Software Development",
|
|
32
|
+
"Topic :: Software Development :: Code Generators",
|
|
33
|
+
"Typing :: Typed",
|
|
34
|
+
]
|
|
35
|
+
dependencies = [
|
|
36
|
+
"rich>=13.0",
|
|
37
|
+
"questionary>=2.0",
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
[project.scripts]
|
|
41
|
+
msl = "msl.cli:main"
|
|
42
|
+
|
|
43
|
+
[project.urls]
|
|
44
|
+
Homepage = "https://github.com/mozaddedalfeshani/msl"
|
|
45
|
+
Repository = "https://github.com/mozaddedalfeshani/msl"
|
|
46
|
+
Issues = "https://github.com/mozaddedalfeshani/msl/issues"
|
|
47
|
+
|
|
48
|
+
[tool.setuptools.packages.find]
|
|
49
|
+
where = ["src"]
|
|
50
|
+
|
|
51
|
+
[tool.setuptools.package-data]
|
|
52
|
+
msl = ["skills/**/*.md"]
|
|
53
|
+
|
|
54
|
+
[tool.pytest.ini_options]
|
|
55
|
+
testpaths = ["tests"]
|
msl-0.1.0/setup.cfg
ADDED
msl-0.1.0/src/msl/cli.py
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def main() -> None:
|
|
7
|
+
# Handle --version / --help before importing heavy dependencies
|
|
8
|
+
if len(sys.argv) > 1:
|
|
9
|
+
arg = sys.argv[1]
|
|
10
|
+
if arg in ("--version", "-V"):
|
|
11
|
+
from . import __version__
|
|
12
|
+
print(f"msl {__version__}")
|
|
13
|
+
return
|
|
14
|
+
if arg in ("--help", "-h"):
|
|
15
|
+
print(
|
|
16
|
+
"Usage: msl [options]\n"
|
|
17
|
+
"\n"
|
|
18
|
+
" Interactive wizard that generates platform-specific skill\n"
|
|
19
|
+
" files for AI coding assistants (Cursor, VS Code, Claude Code, Codex).\n"
|
|
20
|
+
"\n"
|
|
21
|
+
"Options:\n"
|
|
22
|
+
" -h, --help Show this help message\n"
|
|
23
|
+
" -V, --version Show version number\n"
|
|
24
|
+
)
|
|
25
|
+
return
|
|
26
|
+
|
|
27
|
+
from .ui import console, run_wizard, show_cancelled, show_success
|
|
28
|
+
from .writer import generate_skill_file
|
|
29
|
+
|
|
30
|
+
try:
|
|
31
|
+
result = run_wizard()
|
|
32
|
+
if result is None:
|
|
33
|
+
sys.exit(0)
|
|
34
|
+
|
|
35
|
+
ctx, scan = result
|
|
36
|
+
output_path = generate_skill_file(ctx, scan)
|
|
37
|
+
show_success(output_path)
|
|
38
|
+
|
|
39
|
+
except KeyboardInterrupt:
|
|
40
|
+
show_cancelled()
|
|
41
|
+
sys.exit(0)
|
|
42
|
+
except FileExistsError as exc:
|
|
43
|
+
console.print(f"\n[yellow]{exc}[/yellow]")
|
|
44
|
+
sys.exit(0)
|
|
45
|
+
except Exception as exc:
|
|
46
|
+
console.print(f"\n[red]Error: {exc}[/red]")
|
|
47
|
+
sys.exit(1)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
if __name__ == "__main__":
|
|
51
|
+
main()
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import platform as platform_mod
|
|
4
|
+
import shutil
|
|
5
|
+
import subprocess
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from .models import DetectedTool
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _run_version_cmd(cmd: str) -> str | None:
|
|
12
|
+
try:
|
|
13
|
+
result = subprocess.run(
|
|
14
|
+
[cmd, "--version"],
|
|
15
|
+
capture_output=True,
|
|
16
|
+
text=True,
|
|
17
|
+
timeout=5,
|
|
18
|
+
)
|
|
19
|
+
if result.returncode == 0:
|
|
20
|
+
return (result.stdout.strip() or result.stderr.strip()) or None
|
|
21
|
+
except (FileNotFoundError, subprocess.TimeoutExpired, OSError):
|
|
22
|
+
pass
|
|
23
|
+
return None
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _check_macos_app(app_name: str) -> bool:
|
|
27
|
+
return Path(f"/Applications/{app_name}.app").exists()
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def detect_nodejs() -> DetectedTool:
|
|
31
|
+
version = _run_version_cmd("node")
|
|
32
|
+
return DetectedTool(
|
|
33
|
+
name="Node.js",
|
|
34
|
+
installed=version is not None,
|
|
35
|
+
version=version,
|
|
36
|
+
path=shutil.which("node"),
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def detect_cursor() -> DetectedTool:
|
|
41
|
+
cursor_path = shutil.which("cursor")
|
|
42
|
+
if cursor_path:
|
|
43
|
+
version = _run_version_cmd("cursor")
|
|
44
|
+
return DetectedTool(
|
|
45
|
+
name="Cursor", installed=True, version=version, path=cursor_path
|
|
46
|
+
)
|
|
47
|
+
if platform_mod.system() == "Darwin" and _check_macos_app("Cursor"):
|
|
48
|
+
return DetectedTool(
|
|
49
|
+
name="Cursor", installed=True, path="/Applications/Cursor.app"
|
|
50
|
+
)
|
|
51
|
+
return DetectedTool(name="Cursor", installed=False)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def detect_vscode() -> DetectedTool:
|
|
55
|
+
code_path = shutil.which("code")
|
|
56
|
+
if code_path:
|
|
57
|
+
version = _run_version_cmd("code")
|
|
58
|
+
return DetectedTool(
|
|
59
|
+
name="VS Code", installed=True, version=version, path=code_path
|
|
60
|
+
)
|
|
61
|
+
if platform_mod.system() == "Darwin" and _check_macos_app("Visual Studio Code"):
|
|
62
|
+
return DetectedTool(
|
|
63
|
+
name="VS Code",
|
|
64
|
+
installed=True,
|
|
65
|
+
path="/Applications/Visual Studio Code.app",
|
|
66
|
+
)
|
|
67
|
+
return DetectedTool(name="VS Code", installed=False)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def detect_claude_code() -> DetectedTool:
|
|
71
|
+
claude_path = shutil.which("claude")
|
|
72
|
+
if claude_path:
|
|
73
|
+
version = _run_version_cmd("claude")
|
|
74
|
+
return DetectedTool(
|
|
75
|
+
name="Claude Code", installed=True, version=version, path=claude_path
|
|
76
|
+
)
|
|
77
|
+
return DetectedTool(name="Claude Code", installed=False)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def detect_codex() -> DetectedTool:
|
|
81
|
+
codex_path = shutil.which("codex")
|
|
82
|
+
if codex_path:
|
|
83
|
+
version = _run_version_cmd("codex")
|
|
84
|
+
return DetectedTool(
|
|
85
|
+
name="Codex", installed=True, version=version, path=codex_path
|
|
86
|
+
)
|
|
87
|
+
return DetectedTool(name="Codex", installed=False)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def detect_all() -> dict[str, DetectedTool]:
|
|
91
|
+
return {
|
|
92
|
+
"nodejs": detect_nodejs(),
|
|
93
|
+
"cursor": detect_cursor(),
|
|
94
|
+
"vscode": detect_vscode(),
|
|
95
|
+
"claude-code": detect_claude_code(),
|
|
96
|
+
"codex": detect_codex(),
|
|
97
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from enum import Enum
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Platform(Enum):
|
|
9
|
+
CURSOR = "cursor"
|
|
10
|
+
VSCODE = "vscode"
|
|
11
|
+
CLAUDE_CODE = "claude-code"
|
|
12
|
+
CODEX = "codex"
|
|
13
|
+
|
|
14
|
+
@property
|
|
15
|
+
def display_name(self) -> str:
|
|
16
|
+
return {
|
|
17
|
+
Platform.CURSOR: "Cursor",
|
|
18
|
+
Platform.VSCODE: "VS Code",
|
|
19
|
+
Platform.CLAUDE_CODE: "Claude Code",
|
|
20
|
+
Platform.CODEX: "Codex",
|
|
21
|
+
}[self]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class ProjectType(Enum):
|
|
25
|
+
FLUTTER = "flutter"
|
|
26
|
+
NEXTJS = "nextjs"
|
|
27
|
+
REACT_VITE = "react-vite"
|
|
28
|
+
RUST_SERVER = "rust-server"
|
|
29
|
+
NODEJS_SERVER = "nodejs-server"
|
|
30
|
+
PYTHON = "python"
|
|
31
|
+
GO_SERVER = "go-server"
|
|
32
|
+
|
|
33
|
+
@property
|
|
34
|
+
def display_name(self) -> str:
|
|
35
|
+
return {
|
|
36
|
+
ProjectType.FLUTTER: "Flutter",
|
|
37
|
+
ProjectType.NEXTJS: "Web (Next.js)",
|
|
38
|
+
ProjectType.REACT_VITE: "Web (React/Vite)",
|
|
39
|
+
ProjectType.RUST_SERVER: "Rust (Server)",
|
|
40
|
+
ProjectType.NODEJS_SERVER: "Node.js (Server)",
|
|
41
|
+
ProjectType.PYTHON: "Python",
|
|
42
|
+
ProjectType.GO_SERVER: "Go (Server)",
|
|
43
|
+
}[self]
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class PreferenceTier(Enum):
|
|
47
|
+
SIMPLE = "simple"
|
|
48
|
+
INTERMEDIATE = "intermediate"
|
|
49
|
+
INDUSTRY_STANDARD = "industry_standard"
|
|
50
|
+
|
|
51
|
+
@property
|
|
52
|
+
def display_name(self) -> str:
|
|
53
|
+
return {
|
|
54
|
+
PreferenceTier.SIMPLE: "Simple — modular, clean code basics",
|
|
55
|
+
PreferenceTier.INTERMEDIATE: "Intermediate — patterns, testing, conventions",
|
|
56
|
+
PreferenceTier.INDUSTRY_STANDARD: "Industry Standard — full architecture & delivery rules",
|
|
57
|
+
}[self]
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@dataclass
|
|
61
|
+
class DetectedTool:
|
|
62
|
+
name: str
|
|
63
|
+
installed: bool
|
|
64
|
+
version: str | None = None
|
|
65
|
+
path: str | None = None
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
@dataclass
|
|
69
|
+
class SkillGenContext:
|
|
70
|
+
target_platform: Platform
|
|
71
|
+
project_path: Path
|
|
72
|
+
project_type: ProjectType
|
|
73
|
+
preference_tier: PreferenceTier
|
|
74
|
+
detected_tools: dict[str, DetectedTool] = field(default_factory=dict)
|
|
75
|
+
|
|
76
|
+
@property
|
|
77
|
+
def output_path(self) -> Path:
|
|
78
|
+
from .path_rules import get_output_path
|
|
79
|
+
|
|
80
|
+
return get_output_path(self.target_platform, self.project_path)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from .models import Platform
|
|
6
|
+
|
|
7
|
+
# Platform → (hidden directory name | None, filename)
|
|
8
|
+
# Based on each tool's ACTUAL config-file convention.
|
|
9
|
+
PLATFORM_PATHS: dict[str, tuple[str | None, str]] = {
|
|
10
|
+
Platform.CURSOR.value: (".cursor", "rules.md"), # .cursor/rules.md
|
|
11
|
+
Platform.VSCODE.value: (".github", "copilot-instructions.md"), # .github/copilot-instructions.md
|
|
12
|
+
Platform.CLAUDE_CODE.value: (None, "CLAUDE.md"), # CLAUDE.md at project root
|
|
13
|
+
Platform.CODEX.value: (None, "AGENTS.md"), # AGENTS.md at project root
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def get_output_path(platform: Platform, project_root: Path) -> Path:
|
|
18
|
+
directory, filename = PLATFORM_PATHS[platform.value]
|
|
19
|
+
if directory:
|
|
20
|
+
return project_root / directory / filename
|
|
21
|
+
return project_root / filename
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def get_output_dir(platform: Platform, project_root: Path) -> Path:
|
|
25
|
+
directory, _ = PLATFORM_PATHS[platform.value]
|
|
26
|
+
if directory:
|
|
27
|
+
return project_root / directory
|
|
28
|
+
return project_root
|