Skip to content

Commit eb69d47

Browse files
committed
feat: set default models to Sonnet 4.6, add prettier and golangci-lint installer support
1 parent 72bb230 commit eb69d47

9 files changed

Lines changed: 148 additions & 7 deletions

File tree

installer/steps/dependencies.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,30 @@ def install_typescript_lsp() -> bool:
467467
return _run_bash_with_retry(npm_global_cmd("npm install -g @vtsls/language-server typescript"))
468468

469469

470+
def install_prettier() -> bool:
471+
"""Install prettier code formatter globally for TypeScript/JavaScript files."""
472+
if command_exists("prettier"):
473+
return True
474+
return _run_bash_with_retry(npm_global_cmd("npm install -g prettier"))
475+
476+
477+
def install_golangci_lint() -> bool:
478+
"""Install golangci-lint for comprehensive Go code linting.
479+
480+
Skips if Go is not installed, since golangci-lint requires it.
481+
Uses the official install script to place the binary in $(go env GOPATH)/bin.
482+
"""
483+
if command_exists("golangci-lint"):
484+
return True
485+
if not command_exists("go"):
486+
return False
487+
install_cmd = (
488+
"curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh"
489+
" | sh -s -- -b $(go env GOPATH)/bin"
490+
)
491+
return _run_bash_with_retry(install_cmd, timeout=120)
492+
493+
470494
def _is_ccusage_installed() -> bool:
471495
"""Check if ccusage is installed globally."""
472496
try:
@@ -818,6 +842,12 @@ def run(self, ctx: InstallContext) -> None:
818842
if _install_with_spinner(ui, "vtsls (TypeScript LSP server)", install_typescript_lsp):
819843
installed.append("typescript_lsp")
820844

845+
if _install_with_spinner(ui, "prettier (TypeScript formatter)", install_prettier):
846+
installed.append("prettier")
847+
848+
if _install_with_spinner(ui, "golangci-lint (Go linter)", install_golangci_lint):
849+
installed.append("golangci_lint")
850+
821851
if _install_with_spinner(ui, "ccusage (usage tracking)", install_ccusage):
822852
installed.append("ccusage")
823853

installer/tests/unit/steps/test_dependencies.py

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ def test_dependencies_check_returns_false(self):
3131
)
3232
assert step.check(ctx) is False
3333

34+
@patch("installer.steps.dependencies.install_golangci_lint", return_value=True)
35+
@patch("installer.steps.dependencies.install_prettier", return_value=True)
3436
@patch("installer.steps.dependencies._precache_npx_mcp_servers", return_value=True)
3537
@patch("installer.steps.dependencies.install_vexor")
3638
@patch("installer.steps.dependencies._install_plugin_dependencies")
@@ -49,6 +51,8 @@ def test_dependencies_run_installs_core(
4951
mock_plugin_deps,
5052
mock_vexor,
5153
_mock_precache,
54+
_mock_prettier,
55+
_mock_golangci_lint,
5256
):
5357
"""DependenciesStep installs all dependencies including Python tools."""
5458
from installer.context import InstallContext
@@ -769,3 +773,110 @@ def test_install_vexor_routes_to_mlx_on_macos_arm64(self, _mock_platform, mock_m
769773

770774
assert result is True
771775
mock_mlx.assert_called_once()
776+
777+
778+
class TestInstallPrettier:
779+
"""Test prettier global installation."""
780+
781+
def test_install_prettier_exists(self):
782+
"""install_prettier function exists."""
783+
from installer.steps.dependencies import install_prettier
784+
785+
assert callable(install_prettier)
786+
787+
@patch("installer.steps.dependencies.command_exists", return_value=True)
788+
def test_install_prettier_skips_if_already_installed(self, _mock_cmd):
789+
"""install_prettier returns True without installing when prettier is in PATH."""
790+
from installer.steps.dependencies import install_prettier
791+
792+
with patch("installer.steps.dependencies._run_bash_with_retry") as mock_run:
793+
result = install_prettier()
794+
795+
assert result is True
796+
mock_run.assert_not_called()
797+
798+
@patch("installer.steps.dependencies._run_bash_with_retry", return_value=True)
799+
@patch("installer.steps.dependencies.command_exists", return_value=False)
800+
def test_install_prettier_installs_via_npm(self, _mock_cmd, mock_run):
801+
"""install_prettier uses npm install -g prettier when not in PATH."""
802+
from installer.steps.dependencies import install_prettier
803+
804+
result = install_prettier()
805+
806+
assert result is True
807+
mock_run.assert_called_once()
808+
assert "prettier" in mock_run.call_args[0][0]
809+
assert "npm install -g" in mock_run.call_args[0][0]
810+
811+
@patch("installer.steps.dependencies._run_bash_with_retry", return_value=False)
812+
@patch("installer.steps.dependencies.command_exists", return_value=False)
813+
def test_install_prettier_returns_false_on_failure(self, _mock_cmd, mock_run):
814+
"""install_prettier returns False when npm install fails."""
815+
from installer.steps.dependencies import install_prettier
816+
817+
result = install_prettier()
818+
819+
assert result is False
820+
821+
822+
class TestInstallGolangciLint:
823+
"""Test golangci-lint installation."""
824+
825+
def test_install_golangci_lint_exists(self):
826+
"""install_golangci_lint function exists."""
827+
from installer.steps.dependencies import install_golangci_lint
828+
829+
assert callable(install_golangci_lint)
830+
831+
@patch("installer.steps.dependencies.command_exists", return_value=True)
832+
def test_install_golangci_lint_skips_if_already_installed(self, mock_cmd):
833+
"""install_golangci_lint returns True without installing when already in PATH."""
834+
from installer.steps.dependencies import install_golangci_lint
835+
836+
with patch("installer.steps.dependencies._run_bash_with_retry") as mock_run:
837+
result = install_golangci_lint()
838+
839+
assert result is True
840+
mock_run.assert_not_called()
841+
842+
@patch("installer.steps.dependencies.command_exists")
843+
def test_install_golangci_lint_skips_without_go(self, mock_cmd):
844+
"""install_golangci_lint returns False when go is not installed."""
845+
from installer.steps.dependencies import install_golangci_lint
846+
847+
mock_cmd.side_effect = lambda cmd: cmd != "golangci-lint" and False
848+
849+
with patch("installer.steps.dependencies._run_bash_with_retry") as mock_run:
850+
result = install_golangci_lint()
851+
852+
assert result is False
853+
mock_run.assert_not_called()
854+
855+
@patch("installer.steps.dependencies._run_bash_with_retry", return_value=True)
856+
@patch("installer.steps.dependencies.command_exists")
857+
def test_install_golangci_lint_uses_official_script(self, mock_cmd, mock_run):
858+
"""install_golangci_lint uses the official install.sh script."""
859+
from installer.steps.dependencies import install_golangci_lint
860+
861+
mock_cmd.side_effect = lambda cmd: cmd == "go"
862+
863+
result = install_golangci_lint()
864+
865+
assert result is True
866+
mock_run.assert_called_once()
867+
call_args = mock_run.call_args[0][0]
868+
assert "golangci-lint" in call_args
869+
assert "install.sh" in call_args
870+
assert "go env GOPATH" in call_args
871+
872+
@patch("installer.steps.dependencies._run_bash_with_retry", return_value=False)
873+
@patch("installer.steps.dependencies.command_exists")
874+
def test_install_golangci_lint_returns_false_on_failure(self, mock_cmd, mock_run):
875+
"""install_golangci_lint returns False when install script fails."""
876+
from installer.steps.dependencies import install_golangci_lint
877+
878+
mock_cmd.side_effect = lambda cmd: cmd == "go"
879+
880+
result = install_golangci_lint()
881+
882+
assert result is False

pilot/commands/learn.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
description: Extract reusable knowledge into skills - online learning system
3-
model: sonnet[1m]
3+
model: sonnet
44
---
55

66
# /learn - Online Learning System

pilot/commands/spec-implement.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
description: "Spec implementation phase - TDD loop for each task in the plan"
33
argument-hint: "<path/to/plan.md>"
44
user-invocable: false
5-
model: sonnet[1m]
5+
model: sonnet
66
---
77

88
# /spec-implement - Implementation Phase

pilot/commands/spec-plan.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
description: "Spec planning phase - explore codebase, design plan, get approval"
33
argument-hint: "<task description> or <path/to/plan.md>"
44
user-invocable: false
5-
model: opus[1m]
5+
model: opus
66
hooks:
77
Stop:
88
- command: uv run python "${CLAUDE_PLUGIN_ROOT}/hooks/spec_plan_validator.py"

pilot/commands/spec.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
description: Spec-driven development - plan, implement, verify workflow
33
argument-hint: "<task description>" or "<path/to/plan.md>"
44
user-invocable: true
5-
model: sonnet[1m]
5+
model: sonnet
66
---
77

88
# /spec - Unified Spec-Driven Development

pilot/commands/sync.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
description: Sync project rules and skills with codebase - reads existing rules/skills, explores code, updates documentation, creates new skills
33
user-invocable: true
4-
model: sonnet[1m]
4+
model: sonnet
55
---
66

77
# /sync - Sync Project Rules & Skills

pilot/commands/vault.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
description: Manage Team Vault - share and install rules, commands, skills across your team via sx
33
user-invocable: true
4-
model: sonnet[1m]
4+
model: sonnet
55
---
66

77
# /vault - Team Vault Management

pilot/settings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"model": "sonnet[1m]",
2+
"model": "sonnet",
33
"env": {
44
"CLAUDE_CODE_ENABLE_TASKS": "true",
55
"CLAUDE_CODE_HIDE_ACCOUNT_INFO": "true",

0 commit comments

Comments
 (0)