• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

stacklok / toolhive-studio / 21358613544

26 Jan 2026 01:02PM UTC coverage: 52.139% (-1.1%) from 53.264%
21358613544

Pull #1513

github

web-flow
Merge fa98d2df3 into 74627ffa8
Pull Request #1513: feat(cli): add CLI alignment flow

2253 of 4537 branches covered (49.66%)

Branch coverage included in aggregate %.

195 of 477 new or added lines in 12 files covered. (40.88%)

2 existing lines in 2 files now uncovered.

3548 of 6589 relevant lines covered (53.85%)

121.36 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

73.02
/main/src/cli/constants.ts
1
/**
2
 * CLI Alignment Constants (THV-0020)
3
 */
4

5
import { homedir } from 'node:os'
2✔
6
import path from 'node:path'
7
import type { Platform } from './types'
8

9
/** Paths checked for package manager installations (Homebrew, Winget, etc.) */
10
export const EXTERNAL_CLI_PATHS: Record<Platform, string[]> = {
2✔
11
  darwin: ['/opt/homebrew/bin/thv', '/usr/local/bin/thv'],
12
  linux: ['/usr/local/bin/thv', '/usr/bin/thv'],
13
  win32: [
14
    path.join(
15
      process.env.ProgramFiles || 'C:\\Program Files',
4✔
16
      'toolhive',
17
      'thv.exe'
18
    ),
19
    path.join(
20
      process.env.LOCALAPPDATA || path.join(homedir(), 'AppData', 'Local'),
4✔
21
      'Programs',
22
      'toolhive',
23
      'thv.exe'
24
    ),
25
  ],
26
}
27

28
export function getDesktopCliPath(
29
  platform: Platform = process.platform as Platform
4✔
30
): string {
31
  const home = homedir()
4✔
32

33
  switch (platform) {
4✔
34
    case 'darwin':
35
    case 'linux':
36
      return path.join(home, '.toolhive', 'bin', 'thv')
2✔
37
    case 'win32':
38
      return path.join(
1✔
39
        process.env.LOCALAPPDATA || path.join(home, 'AppData', 'Local'),
2✔
40
        'ToolHive',
41
        'bin',
42
        'thv.exe'
43
      )
44
    default:
45
      throw new Error(`Unsupported platform: ${platform}`)
1✔
46
  }
47
}
48

49
export function getMarkerFilePath(): string {
50
  return path.join(homedir(), '.toolhive', '.cli-source')
1✔
51
}
52

53
export function getShellRcFiles(): Record<string, string[]> {
54
  const home = homedir()
3✔
55

56
  return {
3✔
57
    bash: [path.join(home, '.bashrc'), path.join(home, '.bash_profile')],
58
    zsh: [path.join(home, '.zshrc')],
59
    fish: [path.join(home, '.config', 'fish', 'config.fish')],
60
  }
61
}
62

63
export const SHELL_PATH_ENTRY = 'export PATH="$HOME/.toolhive/bin:$PATH"'
2✔
64

65
export const SHELL_PATH_MARKERS = {
2✔
66
  start: '# Added by ToolHive Studio - do not modify this block',
67
  end: '# End ToolHive Studio',
68
}
69

70
export const FISH_PATH_ENTRY = 'fish_add_path -g $HOME/.toolhive/bin'
2✔
71

72
export function getCliSourceFromPath(
73
  cliPath: string,
74
  platform: Platform = process.platform as Platform
9✔
75
): 'homebrew' | 'winget' | 'manual' {
76
  const normalizedPath = cliPath.toLowerCase()
9✔
77

78
  if (platform === 'darwin' || platform === 'linux') {
9!
79
    if (
9✔
80
      normalizedPath.includes('/homebrew/') ||
13✔
81
      normalizedPath.includes('/opt/homebrew/')
82
    ) {
83
      return 'homebrew'
5✔
84
    }
85
  }
86

87
  if (platform === 'win32') {
4!
88
    // Check for typical winget installation paths
NEW
89
    const programFiles = (process.env.ProgramFiles || '').toLowerCase()
×
NEW
90
    const localAppData = (process.env.LOCALAPPDATA || '').toLowerCase()
×
91

NEW
92
    if (
×
93
      normalizedPath.includes(programFiles) ||
×
94
      normalizedPath.includes(localAppData)
95
    ) {
96
      // Could be winget or manual - default to winget for program files
NEW
97
      if (normalizedPath.includes('programs')) {
×
NEW
98
        return 'winget'
×
99
      }
100
    }
101
  }
102

103
  return 'manual'
4✔
104
}
105

106
export function getUninstallInstructions(
107
  source: 'homebrew' | 'winget' | 'manual'
108
): string {
109
  switch (source) {
3✔
110
    case 'homebrew':
111
      return 'To uninstall, run:\n  brew uninstall toolhive'
1✔
112
    case 'winget':
113
      return 'To uninstall, run:\n  winget uninstall toolhive'
1✔
114
    case 'manual':
115
      return 'Please manually remove the external ToolHive CLI installation.'
1✔
116
  }
117
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc