Skip to content

Commit 0343d2e

Browse files
authored
Merge pull request #8 from alex-feel/alex-feel-dev
Make setup-python-environment.ps1 compatible with iex execution
2 parents 9f67964 + 06239ac commit 0343d2e

File tree

1 file changed

+95
-111
lines changed

1 file changed

+95
-111
lines changed
Lines changed: 95 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,10 @@
1-
<#
2-
.SYNOPSIS
3-
Sets up a complete Python development environment for Claude Code.
1+
# Claude Code Python Environment Setup for Windows
2+
# Downloads and configures Python development tools for Claude Code
3+
# Usage: .\setup-python-environment.ps1 [-SkipInstall] [-Force]
44

5-
.DESCRIPTION
6-
This script installs and configures Claude Code with Python-specific
7-
subagents, slash commands, system prompts, and MCP server integration.
8-
9-
It downloads configuration files from the claude-code-toolbox repository
10-
and sets up a launcher script for easy access.
11-
12-
.PARAMETER SkipInstall
13-
Skip Claude Code installation (useful if already installed).
14-
15-
.PARAMETER Force
16-
Force overwrite of existing configuration files.
17-
18-
.EXAMPLE
19-
.\setup-python-environment.ps1
20-
21-
.EXAMPLE
22-
.\setup-python-environment.ps1 -SkipInstall
23-
#>
24-
25-
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', '', Justification='Parameters are used in conditional logic')]
26-
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseBOMForUnicodeEncodedFile', '', Justification='UTF-8 without BOM is preferred')]
275
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWriteHost', '', Justification='Installation script needs console output')]
6+
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingInvokeExpression', '', Justification='Required for remote script execution')]
7+
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', '', Justification='Force parameter is used conditionally')]
288
param(
299
[switch]$SkipInstall,
3010
[switch]$Force
@@ -64,32 +44,30 @@ $Commands = @(
6444
# Helper functions
6545
function Write-Success {
6646
param([string]$Message)
67-
Write-Host " $Message" -ForegroundColor Green
47+
Write-Host " OK: $Message" -ForegroundColor Green
6848
}
6949

7050
function Write-Info {
7151
param([string]$Message)
72-
Write-Host " ℹ️ $Message" -ForegroundColor Yellow
52+
Write-Host " INFO: $Message" -ForegroundColor Yellow
7353
}
7454

7555
function Write-Warn {
7656
param([string]$Message)
77-
Write-Host " ⚠️ $Message" -ForegroundColor Yellow
57+
Write-Host " WARN: $Message" -ForegroundColor Yellow
7858
}
7959

8060
function Write-ErrorMsg {
8161
param([string]$Message)
82-
Write-Host " $Message" -ForegroundColor Red
62+
Write-Host " ERROR: $Message" -ForegroundColor Red
8363
}
8464

8565
function Write-Header {
86-
Write-Host "" # Empty line
87-
Write-Host "╔══════════════════════════════════════════════════════════════════════╗" -ForegroundColor Blue
88-
Write-Host "║ ║" -ForegroundColor Blue
89-
Write-Host "║ Claude Code Python Environment Setup for Windows ║" -ForegroundColor Blue
90-
Write-Host "║ ║" -ForegroundColor Blue
91-
Write-Host "╚══════════════════════════════════════════════════════════════════════╝" -ForegroundColor Blue
92-
Write-Host "" # Empty line
66+
Write-Host ""
67+
Write-Host "========================================================================" -ForegroundColor Blue
68+
Write-Host " Claude Code Python Environment Setup for Windows " -ForegroundColor Blue
69+
Write-Host "========================================================================" -ForegroundColor Blue
70+
Write-Host ""
9371
}
9472

9573
function Test-CommandExist {
@@ -130,7 +108,7 @@ function Save-FileFromUrl {
130108

131109
try {
132110
$response = Invoke-WebRequest -Uri $Url -UseBasicParsing
133-
$response.Content | Out-File -FilePath $Destination -Encoding UTF8 -Force
111+
[System.IO.File]::WriteAllText($Destination, $response.Content)
134112
Write-Success "Downloaded: $fileName"
135113
} catch {
136114
Write-ErrorMsg "Failed to download: $fileName"
@@ -146,8 +124,9 @@ if (-not $SkipInstall) {
146124
Write-Host "Step 1: Installing Claude Code..." -ForegroundColor Cyan
147125

148126
try {
149-
$installCommand = "iex ((New-Object Net.WebClient).DownloadString('$RepoBaseUrl/scripts/windows/install-claude-windows.ps1'))"
150-
powershell -NoProfile -ExecutionPolicy Bypass -Command $installCommand
127+
$installUrl = "$RepoBaseUrl/scripts/windows/install-claude-windows.ps1"
128+
$installScript = (New-Object Net.WebClient).DownloadString($installUrl)
129+
Invoke-Expression $installScript
151130
Write-Success "Claude Code installation complete"
152131
} catch {
153132
Write-ErrorMsg "Failed to install Claude Code"
@@ -167,36 +146,41 @@ if (-not $SkipInstall) {
167146
}
168147

169148
# Step 2: Create directories
170-
Write-Host "`nStep 2: Creating configuration directories..." -ForegroundColor Cyan
149+
Write-Host ""
150+
Write-Host "Step 2: Creating configuration directories..." -ForegroundColor Cyan
171151
if (New-DirectoryIfNotExist $ClaudeUserDir) { Write-Success "Created: $ClaudeUserDir" }
172152
if (New-DirectoryIfNotExist $AgentsDir) { Write-Success "Created: $AgentsDir" }
173153
if (New-DirectoryIfNotExist $CommandsDir) { Write-Success "Created: $CommandsDir" }
174154
if (New-DirectoryIfNotExist $PromptsDir) { Write-Success "Created: $PromptsDir" }
175155

176156
# Step 3: Download subagents
177-
Write-Host "`nStep 3: Downloading Python-optimized subagents..." -ForegroundColor Cyan
157+
Write-Host ""
158+
Write-Host "Step 3: Downloading Python-optimized subagents..." -ForegroundColor Cyan
178159
foreach ($agent in $Agents) {
179160
$url = "$RepoBaseUrl/agents/examples/$agent.md"
180161
$destination = Join-Path $AgentsDir "$agent.md"
181162
Save-FileFromUrl -Url $url -Destination $destination
182163
}
183164

184165
# Step 4: Download slash commands
185-
Write-Host "`nStep 4: Downloading slash commands..." -ForegroundColor Cyan
166+
Write-Host ""
167+
Write-Host "Step 4: Downloading slash commands..." -ForegroundColor Cyan
186168
foreach ($command in $Commands) {
187169
$url = "$RepoBaseUrl/slash-commands/examples/$command.md"
188170
$destination = Join-Path $CommandsDir "$command.md"
189171
Save-FileFromUrl -Url $url -Destination $destination
190172
}
191173

192174
# Step 5: Download Python developer system prompt
193-
Write-Host "`nStep 5: Downloading Python developer system prompt..." -ForegroundColor Cyan
175+
Write-Host ""
176+
Write-Host "Step 5: Downloading Python developer system prompt..." -ForegroundColor Cyan
194177
$promptUrl = "$RepoBaseUrl/system-prompts/examples/python-developer.md"
195178
$promptPath = Join-Path $PromptsDir "python-developer.md"
196-
Download-File -Url $promptUrl -Destination $promptPath
179+
Save-FileFromUrl -Url $promptUrl -Destination $promptPath
197180

198181
# Step 6: Configure Context7 MCP server
199-
Write-Host "`nStep 6: Configuring Context7 MCP server..." -ForegroundColor Cyan
182+
Write-Host ""
183+
Write-Host "Step 6: Configuring Context7 MCP server..." -ForegroundColor Cyan
200184
$mcpConfigPath = Join-Path $ClaudeUserDir "mcp.json"
201185
$mcpConfig = @'
202186
{
@@ -210,14 +194,15 @@ $mcpConfig = @'
210194
'@
211195

212196
try {
213-
$mcpConfig | Out-File -FilePath $mcpConfigPath -Encoding UTF8 -Force
197+
[System.IO.File]::WriteAllText($mcpConfigPath, $mcpConfig)
214198
Write-Success "Created MCP configuration"
215199
} catch {
216200
Write-Warn "Failed to create MCP configuration: $_"
217201
}
218202

219203
# Step 7: Create launcher script
220-
Write-Host "`nStep 7: Creating launcher script..." -ForegroundColor Cyan
204+
Write-Host ""
205+
Write-Host "Step 7: Creating launcher script..." -ForegroundColor Cyan
221206
$launcherPath = Join-Path $ClaudeUserDir "start-python-claude.ps1"
222207
$launcherContent = @'
223208
# Claude Code Python Environment Launcher
@@ -237,92 +222,91 @@ Write-Host "Starting Claude Code with Python developer configuration..." -Foregr
237222
'@
238223

239224
try {
240-
$launcherContent | Out-File -FilePath $launcherPath -Encoding UTF8 -Force
225+
[System.IO.File]::WriteAllText($launcherPath, $launcherContent)
241226
Write-Success "Created launcher script"
242227
} catch {
243228
Write-Warn "Failed to create launcher script: $_"
244229
}
245230

246231
# Step 8: Register global command
247-
Write-Host "`nStep 8: Registering global claude-python command..." -ForegroundColor Cyan
232+
Write-Host ""
233+
Write-Host "Step 8: Registering global claude-python command..." -ForegroundColor Cyan
248234
$localBinPath = Join-Path $env:USERPROFILE ".local\bin"
249235
if (-not (Test-Path $localBinPath)) {
250236
New-Item -ItemType Directory -Path $localBinPath -Force | Out-Null
251237
}
252238

253239
# Create batch file for easy execution
254240
$batchPath = Join-Path $localBinPath "claude-python.cmd"
255-
# Use single quotes and string concatenation to avoid parser issues with @echo
256-
$batchContent = '@echo off' + "`r`n" + "powershell -NoProfile -ExecutionPolicy Bypass -File `"$launcherPath`" %*"
257-
$batchContent | Out-File -FilePath $batchPath -Encoding ASCII
241+
$batchContent = "@echo off`r`npowershell -NoProfile -ExecutionPolicy Bypass -File `"$launcherPath`" %*"
242+
[System.IO.File]::WriteAllText($batchPath, $batchContent)
258243
Write-Success "Created global command: claude-python"
259244

260245
# Add .local\bin to PATH if not already there
261-
$currentUserPath = [System.Environment]::GetEnvironmentVariable('Path', 'User')
262-
if ($currentUserPath -notlike "*$localBinPath*") {
263-
$newUserPath = "$localBinPath;$currentUserPath"
264-
[System.Environment]::SetEnvironmentVariable('Path', $newUserPath, 'User')
246+
$userPath = [System.Environment]::GetEnvironmentVariable('Path', 'User')
247+
if (!$userPath) { $userPath = "" }
248+
if ($userPath -notlike "*$localBinPath*") {
249+
if ($userPath -eq "") {
250+
[System.Environment]::SetEnvironmentVariable('Path', $localBinPath, 'User')
251+
} else {
252+
[System.Environment]::SetEnvironmentVariable('Path', "$localBinPath;$userPath", 'User')
253+
}
265254
# Update current session PATH
266-
$currentSessionPath = $env:Path
267-
$env:Path = "$localBinPath;$currentSessionPath"
255+
$sessionPath = $env:Path
256+
if (!$sessionPath) { $sessionPath = "" }
257+
if ($sessionPath -eq "") {
258+
$env:Path = $localBinPath
259+
} else {
260+
$env:Path = "$localBinPath;$sessionPath"
261+
}
268262
Write-Success "Added $localBinPath to PATH"
269263
Write-Info "You may need to restart your terminal for PATH changes to take effect"
270264
}
271265

272266
# Final message
273-
Write-Host "" # Empty line
274-
Write-Host "╔══════════════════════════════════════════════════════════════════════╗" -ForegroundColor Green
275-
Write-Host "║ ║" -ForegroundColor Green
276-
Write-Host "║ ✨ Setup Complete! ✨ ║" -ForegroundColor Green
277-
Write-Host "║ ║" -ForegroundColor Green
278-
Write-Host "╚══════════════════════════════════════════════════════════════════════╝" -ForegroundColor Green
279-
Write-Host "" # Empty line
280-
281-
Write-Host "📝 Summary:" -ForegroundColor Yellow
282-
Write-Host " • Claude Code installation: " -NoNewline
283-
if ($SkipInstall) { Write-Host "Skipped" -ForegroundColor Gray } else { Write-Host "Completed" -ForegroundColor Green }
284-
Write-Host " • Python subagents: " -NoNewline
285-
Write-Host "$($Agents.Count) installed" -ForegroundColor Green
286-
Write-Host " • Slash commands: " -NoNewline
287-
Write-Host "$($Commands.Count) installed" -ForegroundColor Green
288-
Write-Host " • System prompt: " -NoNewline
289-
Write-Host "Configured" -ForegroundColor Green
290-
Write-Host " • MCP server: " -NoNewline
291-
Write-Host "Context7 configured" -ForegroundColor Green
292-
Write-Host " • Global command: " -NoNewline
293-
Write-Host "claude-python registered" -ForegroundColor Green
294-
295-
Write-Host "`n🚀 Quick Start:" -ForegroundColor Yellow
296-
Write-Host " • Global command: " -NoNewline
297-
Write-Host "claude-python" -ForegroundColor Cyan
298-
Write-Host (" • Full path: & `"" + $launcherPath + "`"")
299-
Write-Host (" • Manual: claude --append-system-prompt `"@" + $promptPath + "`"")
300-
301-
Write-Host "`n✨ What's Installed:" -ForegroundColor Yellow
302-
Write-Host " • 7 Python-optimized subagents (code review, testing, docs, etc.)"
303-
Write-Host " • 6 custom slash commands (/commit, /debug, /test, etc.)"
304-
Write-Host " • Context7 MCP server for up-to-date library documentation"
305-
Write-Host " • Comprehensive Python development system prompt"
306-
307-
Write-Host "`n📚 Available Commands (after starting Claude):" -ForegroundColor Yellow
308-
Write-Host "" -NoNewline
309-
Write-Host "/help" -ForegroundColor Cyan -NoNewline
310-
Write-Host " - See all available commands"
311-
Write-Host "" -NoNewline
312-
Write-Host "/agents" -ForegroundColor Cyan -NoNewline
313-
Write-Host " - List available subagents"
314-
Write-Host "" -NoNewline
315-
Write-Host "/commit" -ForegroundColor Cyan -NoNewline
316-
Write-Host " - Smart Git commits"
317-
318-
Write-Host "`n💡 Examples:" -ForegroundColor Yellow
319-
Write-Host " claude-python" -ForegroundColor Cyan
320-
Write-Host " `> Create a FastAPI app with async SQLAlchemy and pytest" -ForegroundColor Gray
321267
Write-Host ""
322-
Write-Host " claude-python" -ForegroundColor Cyan
323-
Write-Host " `> /commit fix: resolve database connection pooling issue" -ForegroundColor Gray
268+
Write-Host "========================================================================" -ForegroundColor Green
269+
Write-Host " Setup Complete! " -ForegroundColor Green
270+
Write-Host "========================================================================" -ForegroundColor Green
271+
Write-Host ""
272+
273+
Write-Host "Summary:" -ForegroundColor Yellow
274+
Write-Host " * Claude Code installation: $(if ($SkipInstall) { 'Skipped' } else { 'Completed' })"
275+
Write-Host " * Python subagents: $($Agents.Count) installed"
276+
Write-Host " * Slash commands: $($Commands.Count) installed"
277+
Write-Host " * System prompt: Configured"
278+
Write-Host " * MCP server: Context7 configured"
279+
Write-Host " * Global command: claude-python registered"
280+
281+
Write-Host ""
282+
Write-Host "Quick Start:" -ForegroundColor Yellow
283+
Write-Host " * Global command: claude-python"
284+
Write-Host " * Full path: powershell -File '$launcherPath'"
285+
Write-Host " * Manual: claude --append-system-prompt '@$promptPath'"
286+
287+
Write-Host ""
288+
Write-Host "What's Installed:" -ForegroundColor Yellow
289+
Write-Host " * 7 Python-optimized subagents (code review, testing, docs, etc.)"
290+
Write-Host " * 6 custom slash commands (/commit, /debug, /test, etc.)"
291+
Write-Host " * Context7 MCP server for up-to-date library documentation"
292+
Write-Host " * Comprehensive Python development system prompt"
324293

325-
Write-Host "`n📖 Documentation:" -ForegroundColor Yellow
326-
Write-Host " • Python Setup Guide: https://github.com/alex-feel/claude-code-toolbox/blob/main/docs/python-setup.md"
327-
Write-Host " • Claude Code Docs: https://docs.anthropic.com/claude-code"
294+
Write-Host ""
295+
Write-Host "Available Commands (after starting Claude):" -ForegroundColor Yellow
296+
Write-Host " * /help - See all available commands"
297+
Write-Host " * /agents - List available subagents"
298+
Write-Host " * /commit - Smart Git commits"
299+
300+
Write-Host ""
301+
Write-Host "Examples:" -ForegroundColor Yellow
302+
Write-Host " claude-python"
303+
Write-Host " > Create a FastAPI app with async SQLAlchemy and pytest"
304+
Write-Host ""
305+
Write-Host " claude-python"
306+
Write-Host " > /commit fix: resolve database connection pooling issue"
307+
308+
Write-Host ""
309+
Write-Host "Documentation:" -ForegroundColor Yellow
310+
Write-Host " * Python Setup Guide: https://github.com/alex-feel/claude-code-toolbox/blob/main/docs/python-setup.md"
311+
Write-Host " * Claude Code Docs: https://docs.anthropic.com/claude-code"
328312
Write-Host ""

0 commit comments

Comments
 (0)