Skip to content

Commit e1ab4f0

Browse files
authored
Remove template version info from CLI, fix Claude user-invocable, cleanup dead code (#2081)
* Remove Template Version and Released from version output Templates are now bundled with the CLI, so showing them as separate artifacts with their own version and release date is no longer accurate. This also removes the GitHub API call that fetched the latest release, making the version command faster and eliminating a network dependency. * Remove unused datetime import * fix: inject user-invocable: true into Claude skill frontmatter The SkillsIntegration.setup() builds frontmatter manually without user-invocable. Add post-processing injection in ClaudeIntegration.setup(), matching the existing pattern for disable-model-invocation. * refactor: address review feedback - Factor _inject_user_invocable and _inject_disable_model_invocation into a shared _inject_frontmatter_flag(key, value) helper - Remove unused httpx, ssl, truststore imports and globals - Remove unused _github_token and _github_auth_headers helpers - Update setup() docstring to mention user-invocable * chore: remove httpx and truststore from dependencies Both are no longer used after removing the GitHub API call from the version command. Removes from PEP 723 script header and pyproject.toml. * fix: match EOL detection style in _inject_frontmatter_flag Handle \r\n, \n, and no-newline cases consistently with inject_argument_hint's pattern.
1 parent 535ddbe commit e1ab4f0

File tree

3 files changed

+15
-60
lines changed

3 files changed

+15
-60
lines changed

pyproject.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,8 @@ dependencies = [
77
"typer",
88
"click>=8.1",
99
"rich",
10-
"httpx[socks]",
1110
"platformdirs",
1211
"readchar",
13-
"truststore>=0.10.4",
1412
"pyyaml>=6.0",
1513
"packaging>=23.0",
1614
"pathspec>=0.12.0",

src/specify_cli/__init__.py

Lines changed: 0 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
# "rich",
77
# "platformdirs",
88
# "readchar",
9-
# "httpx",
109
# "json5",
1110
# ]
1211
# ///
@@ -39,7 +38,6 @@
3938
from typing import Any, Optional, Tuple
4039

4140
import typer
42-
import httpx
4341
from rich.console import Console
4442
from rich.panel import Panel
4543
from rich.text import Text
@@ -51,21 +49,6 @@
5149

5250
# For cross-platform keyboard input
5351
import readchar
54-
import ssl
55-
import truststore
56-
from datetime import datetime
57-
58-
ssl_context = truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
59-
client = httpx.Client(verify=ssl_context)
60-
61-
def _github_token(cli_token: str | None = None) -> str | None:
62-
"""Return sanitized GitHub token (cli arg takes precedence) or None."""
63-
return ((cli_token or os.getenv("GH_TOKEN") or os.getenv("GITHUB_TOKEN") or "").strip()) or None
64-
65-
def _github_auth_headers(cli_token: str | None = None) -> dict:
66-
"""Return Authorization header dict only when a non-empty token exists."""
67-
token = _github_token(cli_token)
68-
return {"Authorization": f"Bearer {token}"} if token else {}
6952

7053
def _build_agent_config() -> dict[str, dict[str, Any]]:
7154
"""Derive AGENT_CONFIG from INTEGRATION_REGISTRY."""
@@ -1429,45 +1412,11 @@ def version():
14291412
except Exception:
14301413
pass
14311414

1432-
# Fetch latest template release version
1433-
repo_owner = "github"
1434-
repo_name = "spec-kit"
1435-
api_url = f"https://api.github.com/repos/{repo_owner}/{repo_name}/releases/latest"
1436-
1437-
template_version = "unknown"
1438-
release_date = "unknown"
1439-
1440-
try:
1441-
response = client.get(
1442-
api_url,
1443-
timeout=10,
1444-
follow_redirects=True,
1445-
headers=_github_auth_headers(),
1446-
)
1447-
if response.status_code == 200:
1448-
release_data = response.json()
1449-
template_version = release_data.get("tag_name", "unknown")
1450-
# Remove 'v' prefix if present
1451-
if template_version.startswith("v"):
1452-
template_version = template_version[1:]
1453-
release_date = release_data.get("published_at", "unknown")
1454-
if release_date != "unknown":
1455-
# Format the date nicely
1456-
try:
1457-
dt = datetime.fromisoformat(release_date.replace('Z', '+00:00'))
1458-
release_date = dt.strftime("%Y-%m-%d")
1459-
except Exception:
1460-
pass
1461-
except Exception:
1462-
pass
1463-
14641415
info_table = Table(show_header=False, box=None, padding=(0, 2))
14651416
info_table.add_column("Key", style="cyan", justify="right")
14661417
info_table.add_column("Value", style="white")
14671418

14681419
info_table.add_row("CLI Version", cli_version)
1469-
info_table.add_row("Template Version", template_version)
1470-
info_table.add_row("Released", release_date)
14711420
info_table.add_row("", "")
14721421
info_table.add_row("Python", platform.python_version())
14731422
info_table.add_row("Platform", platform.system())

src/specify_cli/integrations/claude/__init__.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@ def _build_skill_fm(self, name: str, description: str, source: str) -> dict:
112112
)
113113

114114
@staticmethod
115-
def _inject_disable_model_invocation(content: str) -> str:
116-
"""Insert ``disable-model-invocation: true`` before the closing ``---``."""
115+
def _inject_frontmatter_flag(content: str, key: str, value: str = "true") -> str:
116+
"""Insert ``key: value`` before the closing ``---`` if not already present."""
117117
lines = content.splitlines(keepends=True)
118118

119119
# Pre-scan: bail out if already present in frontmatter
@@ -125,7 +125,7 @@ def _inject_disable_model_invocation(content: str) -> str:
125125
if dash_count == 2:
126126
break
127127
continue
128-
if dash_count == 1 and stripped.startswith("disable-model-invocation:"):
128+
if dash_count == 1 and stripped.startswith(f"{key}:"):
129129
return content
130130

131131
# Inject before the closing --- of frontmatter
@@ -137,8 +137,13 @@ def _inject_disable_model_invocation(content: str) -> str:
137137
if stripped == "---":
138138
dash_count += 1
139139
if dash_count == 2 and not injected:
140-
eol = "\r\n" if line.endswith("\r\n") else "\n"
141-
out.append(f"disable-model-invocation: true{eol}")
140+
if line.endswith("\r\n"):
141+
eol = "\r\n"
142+
elif line.endswith("\n"):
143+
eol = "\n"
144+
else:
145+
eol = ""
146+
out.append(f"{key}: {value}{eol}")
142147
injected = True
143148
out.append(line)
144149
return "".join(out)
@@ -150,7 +155,7 @@ def setup(
150155
parsed_options: dict[str, Any] | None = None,
151156
**opts: Any,
152157
) -> list[Path]:
153-
"""Install Claude skills, then inject argument-hint and disable-model-invocation."""
158+
"""Install Claude skills, then inject user-invocable, disable-model-invocation, and argument-hint."""
154159
created = super().setup(project_root, manifest, parsed_options, **opts)
155160

156161
# Post-process generated skill files
@@ -168,8 +173,11 @@ def setup(
168173
content_bytes = path.read_bytes()
169174
content = content_bytes.decode("utf-8")
170175

176+
# Inject user-invocable: true (Claude skills are accessible via /command)
177+
updated = self._inject_frontmatter_flag(content, "user-invocable")
178+
171179
# Inject disable-model-invocation: true (Claude skills run only when invoked)
172-
updated = self._inject_disable_model_invocation(content)
180+
updated = self._inject_frontmatter_flag(updated, "disable-model-invocation")
173181

174182
# Inject argument-hint if available for this skill
175183
skill_dir_name = path.parent.name # e.g. "speckit-plan"

0 commit comments

Comments
 (0)