usecli 0.1.47__tar.gz → 0.1.49__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.
- {usecli-0.1.47 → usecli-0.1.49}/PKG-INFO +1 -2
- {usecli-0.1.47 → usecli-0.1.49}/pyproject.toml +1 -2
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/core/base_command.py +8 -7
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/templates/command.py.j2 +1 -1
- usecli-0.1.47/src/usecli/cli/core/skill_generator.py +0 -153
- {usecli-0.1.47 → usecli-0.1.49}/LICENSE +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/README.md +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/__init__.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/__init__.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/commands/README.md +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/commands/__init__.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/commands/custom/README.md +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/commands/custom/__init__.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/commands/defaults/__init__.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/commands/defaults/base/__init__.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/commands/defaults/base/about_command.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/commands/defaults/base/help_command.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/commands/defaults/base/inspire_command.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/commands/defaults/base/internal/__init__.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/commands/defaults/base/internal/fzf_command.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/commands/defaults/core/__init__.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/commands/defaults/core/utils.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/commands/defaults/make/__init__.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/commands/defaults/make/make_command.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/commands/defaults/make/make_theme_command.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/commands/init_command.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/config/__init__.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/config/colors.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/core/__init__.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/core/error/__init__.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/core/error/handler.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/core/error/utils.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/core/exceptions/__init__.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/core/exceptions/base.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/core/exceptions/config.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/core/exceptions/usage.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/core/exceptions/validation.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/core/ui/__init__.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/core/ui/list.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/core/ui/title.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/core/ui/title.txt +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/core/validators/__init__.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/core/validators/network.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/core/validators/numeric.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/core/validators/path.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/core/validators/string.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/services/__init__.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/services/command_service.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/templates/theme.toml.j2 +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/templates/usecli.config.toml.j2 +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/themes/ayu_dark.toml +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/themes/catppuccin_frappe.toml +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/themes/catppuccin_latte.toml +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/themes/catppuccin_macchiato.toml +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/themes/catppuccin_mocha.toml +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/themes/default.toml +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/themes/dracula.toml +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/themes/gruvbox_dark.toml +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/themes/nord.toml +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/themes/tokyo_night.toml +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/utils/__init__.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/utils/interactive/__init__.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/utils/interactive/terminal_menu.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/menu.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/params.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/shared/__init__.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/shared/config/__init__.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/shared/config/globals.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/shared/config/manager.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/ui.py +0 -0
- {usecli-0.1.47 → usecli-0.1.49}/src/usecli/usecli.config.toml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: usecli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.49
|
|
4
4
|
Summary: A powerful Python CLI framework for building beautiful, developer-friendly command-line tools.
|
|
5
5
|
Author: Edward Boswell
|
|
6
6
|
Author-email: Edward Boswell <thememium@gmail.com>
|
|
@@ -14,7 +14,6 @@ Requires-Dist: click>=8.3.1
|
|
|
14
14
|
Requires-Dist: fzf-bin>=0.67.0
|
|
15
15
|
Requires-Dist: jinja2>=3.1.6
|
|
16
16
|
Requires-Dist: pyfiglet>=1.0.4
|
|
17
|
-
Requires-Dist: pyyaml>=6.0.2
|
|
18
17
|
Requires-Dist: rich>=14.3.1
|
|
19
18
|
Requires-Dist: simple-term-menu>=1.6.6
|
|
20
19
|
Requires-Dist: tomli>=2.4.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "usecli"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.49"
|
|
4
4
|
description = "A powerful Python CLI framework for building beautiful, developer-friendly command-line tools."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [{ name = "Edward Boswell", email = "thememium@gmail.com" }]
|
|
@@ -16,7 +16,6 @@ dependencies = [
|
|
|
16
16
|
"fzf-bin>=0.67.0",
|
|
17
17
|
"jinja2>=3.1.6",
|
|
18
18
|
"pyfiglet>=1.0.4",
|
|
19
|
-
"pyyaml>=6.0.2",
|
|
20
19
|
"rich>=14.3.1",
|
|
21
20
|
"simple-term-menu>=1.6.6",
|
|
22
21
|
"tomli>=2.4.0",
|
|
@@ -6,10 +6,9 @@ from abc import ABC, abstractmethod
|
|
|
6
6
|
from typing import TYPE_CHECKING, Any, ClassVar
|
|
7
7
|
|
|
8
8
|
import typer
|
|
9
|
-
from click import Argument, Option
|
|
10
9
|
from click.exceptions import Exit
|
|
11
10
|
from rich.console import Console
|
|
12
|
-
from typer.core import TyperCommand
|
|
11
|
+
from typer.core import TyperArgument, TyperCommand, TyperOption
|
|
13
12
|
|
|
14
13
|
from usecli.cli.config.colors import COLOR
|
|
15
14
|
from usecli.cli.core.ui.title import get_script_command_name
|
|
@@ -179,8 +178,8 @@ class CustomHelpCommand(TyperCommand):
|
|
|
179
178
|
self.params = []
|
|
180
179
|
if not self._has_interactive_option():
|
|
181
180
|
self.params.append(
|
|
182
|
-
|
|
183
|
-
["--interactive", "-i"],
|
|
181
|
+
TyperOption(
|
|
182
|
+
param_decls=["--interactive", "-i"],
|
|
184
183
|
is_flag=True,
|
|
185
184
|
help="Run in interactive mode.",
|
|
186
185
|
)
|
|
@@ -188,7 +187,7 @@ class CustomHelpCommand(TyperCommand):
|
|
|
188
187
|
|
|
189
188
|
def _has_interactive_option(self) -> bool:
|
|
190
189
|
return any(
|
|
191
|
-
isinstance(param,
|
|
190
|
+
isinstance(param, TyperOption)
|
|
192
191
|
and ("--interactive" in param.opts or "-i" in param.opts)
|
|
193
192
|
for param in getattr(self, "params", [])
|
|
194
193
|
)
|
|
@@ -217,10 +216,12 @@ class CustomHelpCommand(TyperCommand):
|
|
|
217
216
|
Raises:
|
|
218
217
|
Exit: After displaying help.
|
|
219
218
|
"""
|
|
220
|
-
arguments = [p for p in self.params if isinstance(p,
|
|
219
|
+
arguments = [p for p in self.params if isinstance(p, TyperArgument)]
|
|
221
220
|
argument_names = [p.name for p in arguments if p.name]
|
|
222
221
|
options = [
|
|
223
|
-
p
|
|
222
|
+
p
|
|
223
|
+
for p in self.params
|
|
224
|
+
if isinstance(p, TyperOption) and "--help" not in p.opts
|
|
224
225
|
]
|
|
225
226
|
|
|
226
227
|
arg_usage = " ".join(rf"\[{name.upper()}]" for name in argument_names)
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
"""Skill generator for OpenCode and Claude Code compatibility."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
from pathlib import Path
|
|
6
|
-
from typing import TYPE_CHECKING
|
|
7
|
-
|
|
8
|
-
import yaml
|
|
9
|
-
from jinja2 import Environment, FileSystemLoader, select_autoescape
|
|
10
|
-
|
|
11
|
-
if TYPE_CHECKING:
|
|
12
|
-
from typing import Any
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class SkillGenerator:
|
|
16
|
-
"""Generates AI assistant skills for OpenCode and Claude Code."""
|
|
17
|
-
|
|
18
|
-
SKILLS = [
|
|
19
|
-
"usecli-new",
|
|
20
|
-
"usecli-plan",
|
|
21
|
-
"usecli-apply",
|
|
22
|
-
"usecli-sync",
|
|
23
|
-
"usecli-verify",
|
|
24
|
-
"usecli-archive",
|
|
25
|
-
]
|
|
26
|
-
|
|
27
|
-
def __init__(self, templates_dir: Path | None = None) -> None:
|
|
28
|
-
"""Initialize the skill generator.
|
|
29
|
-
|
|
30
|
-
Args:
|
|
31
|
-
templates_dir: Directory containing Jinja2 templates.
|
|
32
|
-
Defaults to built-in templates.
|
|
33
|
-
"""
|
|
34
|
-
if templates_dir is None:
|
|
35
|
-
templates_dir = Path(__file__).parent.parent / "templates" / "skills"
|
|
36
|
-
|
|
37
|
-
self.templates_dir = templates_dir
|
|
38
|
-
self.env = Environment(
|
|
39
|
-
loader=FileSystemLoader(str(templates_dir)),
|
|
40
|
-
autoescape=select_autoescape(),
|
|
41
|
-
)
|
|
42
|
-
self.env.filters["escape_yaml"] = self._escape_yaml
|
|
43
|
-
self.env.filters["to_yaml"] = self._to_yaml
|
|
44
|
-
|
|
45
|
-
def _escape_yaml(self, text: str) -> str:
|
|
46
|
-
"""Escape special YAML characters in text.
|
|
47
|
-
|
|
48
|
-
Args:
|
|
49
|
-
text: The text to escape.
|
|
50
|
-
|
|
51
|
-
Returns:
|
|
52
|
-
YAML-escaped text.
|
|
53
|
-
"""
|
|
54
|
-
# Handle multi-line strings, quotes, special chars
|
|
55
|
-
if "\n" in text or '"' in text or "'" in text or ":" in text:
|
|
56
|
-
# Use literal block scalar for multi-line strings
|
|
57
|
-
if "\n" in text:
|
|
58
|
-
escaped = text.replace("\\", "\\\\")
|
|
59
|
-
return f'"{escaped.replace(chr(34), chr(92) + chr(34))}"'
|
|
60
|
-
# Escape quotes for single-line strings
|
|
61
|
-
return f'"{text.replace(chr(34), chr(92) + chr(34))}"'
|
|
62
|
-
return text
|
|
63
|
-
|
|
64
|
-
def _to_yaml(self, obj: list[Any] | dict[str, Any]) -> str:
|
|
65
|
-
"""Convert object to YAML string.
|
|
66
|
-
|
|
67
|
-
Args:
|
|
68
|
-
obj: List or dictionary to convert.
|
|
69
|
-
|
|
70
|
-
Returns:
|
|
71
|
-
YAML-formatted string.
|
|
72
|
-
"""
|
|
73
|
-
return yaml.dump(obj, default_flow_style=False).strip()
|
|
74
|
-
|
|
75
|
-
def generate_skill(
|
|
76
|
-
self,
|
|
77
|
-
skill_name: str,
|
|
78
|
-
target: str,
|
|
79
|
-
context: dict[str, Any],
|
|
80
|
-
) -> str:
|
|
81
|
-
"""Generate a skill file for the specified target.
|
|
82
|
-
|
|
83
|
-
Args:
|
|
84
|
-
skill_name: Name of the skill (e.g., 'usecli-explore')
|
|
85
|
-
target: Target platform ('opencode' or 'claude')
|
|
86
|
-
context: Template variables
|
|
87
|
-
|
|
88
|
-
Returns:
|
|
89
|
-
Generated skill content as string
|
|
90
|
-
|
|
91
|
-
Raises:
|
|
92
|
-
ValueError: If target is not 'opencode' or 'claude'
|
|
93
|
-
TemplateNotFound: If the skill template doesn't exist
|
|
94
|
-
"""
|
|
95
|
-
if target not in ("opencode", "claude"):
|
|
96
|
-
msg = f"Invalid target: {target}. Must be 'opencode' or 'claude'"
|
|
97
|
-
raise ValueError(msg)
|
|
98
|
-
|
|
99
|
-
template = self.env.get_template(f"{skill_name}/SKILL.md.j2")
|
|
100
|
-
return template.render(target=target, **context)
|
|
101
|
-
|
|
102
|
-
def generate_all_skills(
|
|
103
|
-
self,
|
|
104
|
-
target: str,
|
|
105
|
-
output_dir: Path,
|
|
106
|
-
version: str = "1.0.0",
|
|
107
|
-
generated_by: str = "useCli",
|
|
108
|
-
) -> list[Path]:
|
|
109
|
-
"""Generate all skills for a target platform.
|
|
110
|
-
|
|
111
|
-
Args:
|
|
112
|
-
target: 'opencode' or 'claude'
|
|
113
|
-
output_dir: Directory to write generated files
|
|
114
|
-
version: Version string for metadata
|
|
115
|
-
generated_by: Generator attribution string
|
|
116
|
-
|
|
117
|
-
Returns:
|
|
118
|
-
List of generated file paths
|
|
119
|
-
|
|
120
|
-
Raises:
|
|
121
|
-
ValueError: If target is not 'opencode' or 'claude'
|
|
122
|
-
"""
|
|
123
|
-
if target not in ("opencode", "claude"):
|
|
124
|
-
msg = f"Invalid target: {target}. Must be 'opencode' or 'claude'"
|
|
125
|
-
raise ValueError(msg)
|
|
126
|
-
|
|
127
|
-
generated = []
|
|
128
|
-
context = {
|
|
129
|
-
"version": version,
|
|
130
|
-
"generated_by": generated_by,
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
for skill_name in self.SKILLS:
|
|
134
|
-
content = self.generate_skill(
|
|
135
|
-
skill_name=skill_name,
|
|
136
|
-
target=target,
|
|
137
|
-
context=context,
|
|
138
|
-
)
|
|
139
|
-
|
|
140
|
-
if target == "opencode":
|
|
141
|
-
output_path = (
|
|
142
|
-
output_dir / ".opencode" / "skills" / skill_name / "SKILL.md"
|
|
143
|
-
)
|
|
144
|
-
else: # claude
|
|
145
|
-
output_path = (
|
|
146
|
-
output_dir / ".claude" / "skills" / skill_name / "SKILL.md"
|
|
147
|
-
)
|
|
148
|
-
|
|
149
|
-
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
150
|
-
output_path.write_text(content)
|
|
151
|
-
generated.append(output_path)
|
|
152
|
-
|
|
153
|
-
return generated
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{usecli-0.1.47 → usecli-0.1.49}/src/usecli/cli/commands/defaults/base/internal/fzf_command.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|