Skip to content

[PPSC-836] feat(install): add interactive MCP install wizard with hooks#199

Open
yiftach-armis wants to merge 16 commits into
mainfrom
feat/PPSC-836-interactive-mcp-install-wizard-v1
Open

[PPSC-836] feat(install): add interactive MCP install wizard with hooks#199
yiftach-armis wants to merge 16 commits into
mainfrom
feat/PPSC-836-interactive-mcp-install-wizard-v1

Conversation

@yiftach-armis
Copy link
Copy Markdown
Collaborator

Related Issue

Type of Change

  • New feature (non-breaking change which adds functionality)

Problem

Installing the Armis CLI MCP plugin required users to manually edit JSON configuration files for Claude Code, Cursor, and Windsurf — error-prone and undocumented.

Solution

Added an interactive install wizard (armis-cli install --interactive) powered by charmbracelet/huh that guides users through IDE selection, validates existing configurations, and safely writes MCP plugin entries. Includes:

  • Interactive TUI with IDE selection, theme picker, and confirmation prompts
  • Git hook integration (native hooks and pre-commit framework) that runs armis-cli scan repo automatically
  • Path injection hardening and safe file-write logic (atomic writes, backup creation) to prevent data loss
  • Comprehensive unit tests for hooks, validation, and plugin config generation

Testing

Automated Tests

  • Unit tests added/updated
  • All tests passing locally

Manual Testing

Ran armis-cli install --interactive against fresh and pre-configured Claude/Cursor/Windsurf setups; verified hook installation with both native git hooks and pre-commit configs.

Reviewer Notes

  • Lint warnings are pre-existing (gosec in internal/api/client_test.go and internal/auth/client.go) — not introduced by this PR
  • The charmbracelet/huh dependency is added for the interactive TUI forms

Checklist

  • Code follows project style guidelines
  • Pre-commit hooks pass
  • Self-review performed
  • No new warnings generated

…dation

Add interactive installation flow, theme selection, hook management
(native Git hooks and pre-commit framework), and plugin validation.
- Quote paths in hook command builders to handle spaces in usernames
- Add newline validation to WriteEnvFromValues preventing .env injection
- Use readJSONFileAsMapSafe in native_hooks.go to surface parse errors
- Call RemoveNativeHook during uninstall to clean up hook configs
- Fix exit code swallowed by head -c 0 pipe (use >/dev/null 2>&1)
- Add posixQuote helper for safe shell path escaping
- Fix RemovePreCommit end-marker search to start from start-marker
- Validate repoRoot as absolute path with .git directory (CWE-73)
- Validate APPDATA env var as absolute path (CWE-73)
- Fix error wrapping in validate.go (%s -> %w)
- Handle backup rename error in WriteEnvFromValues
- Guard lipgloss styling when colors disabled (accessible mode)
- Fix allCovered logic to only skip pre-commit when Claude is sole tool
- Download shared plugin when hooks need it (not just editors)
- Handle WriteManifest error instead of discarding it
- Update hook_init help text to reflect both hook modes
- Fix gosec G117 lint in validate_test.go
- Skip executable bit check on Windows in precommit_test.go
- validate.go: only show credential help text for 401 errors, not
  network/5xx failures
- precommit.go: support git worktrees/submodules by resolving hooks
  dir via git rev-parse with fallback to .git file parsing
- cli/interactive.go: check stderr TTY too (needed for TUI rendering)
- hook.go: fix misleading "automatically" wording in help text
- hooks.go: tighten isArmisHookCommand to match "armis-cli scan repo"
  specifically; add 10MB file size guard before reading settings
- native_hooks.go: tighten isArmisHookJSON to match specific adapter
  filenames; validate pluginDir is absolute in InstallNativeHook
- plugin.go: use os.CreateTemp for atomic writes (randomized temp name)
- install_interactive.go: pass accessible flag to validateAndReport for
  plain-text markers when colors disabled
The tmpPath variable from os.CreateTemp is in a known safe directory
(plugin dir). Add nolint:gosec directives on os.Remove calls.
- Centralize productionBaseURL in auth package, reuse in cmd and install
- validate.go: suppress false-positive CWE-295 (debug param != TLS skip)
- hooks.go: suppress CWE-22 on os.UserHomeDir (trusted OS source)
- native_hooks.go: suppress CWE-73 on APPDATA (validated as absolute)
- plugin.go: abort if backup rename fails (prevent data loss); suppress
  CWE-22 on final rename (known plugin dir path)
- precommit.go: return resolveHooksDir errors instead of swallowing
  (only treat missing .git as no-op)
- uninstall.go: report native hook removal errors as warnings
- install_interactive.go: remove unused pluginDir param from offerHookSetup
…scanner findings

Add //nolint:gosec on the os.Rename taint-analysis false positive
(plugin.go:431) that failed CI lint, and add armis:ignore comments
for the remaining CWE-73/CWE-22 security scanner findings on
precommit.go and native_hooks.go.
… scanner findings

Suppress false-positive findings from the Armis Security Scanner:
- CWE-78 on precommit.go:206 (posixQuote escapes shell metacharacters)
- CWE-22 on native_hooks.go:124 (pluginDir validated absolute + hardcoded segments)
- CWE-73 on precommit.go:29 (repoRoot validated absolute + hardcoded ".git")
- readJSONFileAsMapSafe: use operation-agnostic error message
- WriteEnvFromValues: copy .env to .bak instead of rename for rollback safety
- install command: add explicit --interactive flag to match PR description
- hook_init: handle flag parsing errors instead of ignoring them
- collectCredentials: detect huh.ErrUserAborted and cancel wizard on Ctrl+C
Suppress CWE-522, CWE-78, CWE-73 on WriteEnvFromValues, copyFile, and
buildCursorHooks — all paths from known install locations, not user input.
…improve credential validation

- Extract brandWarn color constant to eliminate duplicate inline definitions
- Mark --interactive and --non-interactive flags as mutually exclusive via Cobra
- Fix hook coverage logic: allCovered when ANY AI tool has native hooks (not only Claude alone)
- Return empty credentials on validation failure so .env is not written with bad values
- Add ARMIS_API_URL/ARMIS_REGION env var support to credential validation endpoint
- Remove unused HookConfigFormat function (dead code after manifest tracking refactor)
…ings

Add targeted armis:ignore comments for CWE-78, CWE-918, CWE-22,
CWE-59, CWE-347, CWE-502, CWE-522, CWE-312, CWE-253, and CWE-367
findings that were not suppressed by existing annotations due to
line-number mismatch or missing CWE specificity.
Copilot AI review requested due to automatic review settings May 26, 2026 15:03
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 26, 2026

Armis AppSecArmis AppSec Security Scan Results

🟠 HIGH issues found

Severity Count
🟠 HIGH 1

Total: 1

View all 1 findings

🟠 HIGH (1)

CWE-522 - Insecure Design (CWE-522

Location: internal/cmd/install_interactive.go:138

Insufficiently Protected Credentials): The installer asks the user for a client ID and client secret. If the user provides these values, the program saves them to a file on the local machine. The file is created without any encryption or additional protection, so anyone who can read that file could see the credentials in plain text. The code does not perform any extra checks or transformations before writing the data, so the user‑provided credentials can reach the part of the program that writes the file. Because the file is written to the local filesystem, an attacker would need access to the user's machine or the directory where the file is stored to exploit this, but the risk of exposing the credentials still exists.

Code snippet is redacted as it contains secrets.

CWEs: CWE-522: Insufficiently Protected Credentials

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 26, 2026

Test Coverage Report

total: (statements) 72.2%

Coverage by function
github.com/ArmisSecurity/armis-cli/cmd/armis-cli/main.go:19:			main					0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/agent.go:34:		Registry				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/agentdetect.go:29:	FlatResults				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/agentdetect.go:45:	NewScanner				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/agentdetect.go:53:	Scan					82.4%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:12:		resolvePath				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:23:		isUnderDir				81.8%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:46:		dirExists				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:56:		fileExists				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:67:		hasExtensionPrefix			80.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:88:		findExtensionVersion			64.3%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:111:	readVersionFromPackageJSON		71.4%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:127:	hasJetBrainsPlugin			100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:140:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:142:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:147:	CheckMCP				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:151:	DetectVersion				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:159:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:161:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:171:	CheckMCP				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:175:	DetectVersion				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:183:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:185:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:189:	CheckMCP				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:193:	DetectVersion				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:201:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:203:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:213:	CheckMCP				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:218:	DetectVersion				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:226:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:228:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:235:	CheckMCP				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:239:	DetectVersion				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:247:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:249:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:256:	CheckMCP				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:262:	DetectVersion				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:270:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:272:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:279:	CheckMCP				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:283:	DetectVersion				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:291:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:293:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:300:	CheckMCP				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:304:	DetectVersion				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:312:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:314:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:318:	CheckMCP				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:322:	DetectVersion				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:330:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:332:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:336:	CheckMCP				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:340:	DetectVersion				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:348:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:350:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:360:	CheckMCP				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:364:	DetectVersion				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:372:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:374:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:389:	CheckMCP				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:393:	DetectVersion				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:401:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:403:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:411:	CheckMCP				75.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:419:	DetectVersion				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:427:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:429:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:433:	CheckMCP				83.3%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:454:	DetectVersion				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:462:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:464:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:468:	CheckMCP				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:472:	DetectVersion				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/format.go:13:		FormatPlain				81.8%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/format.go:50:		FormatJSON				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/mcpconfig.go:19:	HasArmisMCP				83.3%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/mcpconfig.go:40:	HasArmisMCPInClaudeSettings		86.7%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/mcpconfig.go:68:	HasArmisMCPInZedSettings		66.7%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/mcpconfig.go:98:	HasArmisMCPInVSCodeFormat		66.7%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/mcpconfig.go:122:	hasArmisMCPInData			100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/platform_linux.go:13:	NewPlatform				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/platform_linux.go:17:	UserHomeDirs				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/platform_linux.go:25:	VSCodeExtensionsDir			0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/platform_linux.go:30:	JetBrainsPluginDirs			0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/platform_linux.go:35:	VSCodeUserConfigDir			0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/platform_linux.go:39:	CursorAppExists				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/platform_linux.go:43:	JunieBinaryPaths			0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/platform_linux.go:51:	ZedConfigDir				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/platform_linux.go:55:	IsRoot					0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/userprofile.go:13:	enumerateUserDirs			0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/userprofile.go:41:	currentUserOnly				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/userprofile.go:56:	globJetBrainsPluginDirs			0.0%
github.com/ArmisSecurity/armis-cli/internal/api/agents.go:30:			ReportAgentInventory			78.9%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:29:			Error					0.0%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:72:			copyWithContext				70.4%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:145:			WithHTTPClient				100.0%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:154:			WithUploadHTTPClient			100.0%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:162:			WithAllowLocalURLs			100.0%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:174:			NewClient				100.0%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:222:			IsDebug					100.0%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:236:			setAuthHeader				77.8%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:271:			StartIngest				72.3%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:431:			GetIngestStatus				82.6%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:472:			WaitForIngest				84.6%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:523:			FetchNormalizedResults			74.2%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:578:			FetchAllNormalizedResults		91.7%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:604:			GetScanResult				68.4%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:639:			WaitForScan				90.0%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:660:			formatBytes				100.0%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:682:			FetchArtifactScanResults		75.0%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:737:			ValidatePresignedURL			100.0%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:774:			DownloadFromPresignedURL		84.2%
github.com/ArmisSecurity/armis-cli/internal/auth/auth.go:58:			NewAuthProvider				95.2%
github.com/ArmisSecurity/armis-cli/internal/auth/auth.go:104:			GetAuthorizationHeader			100.0%
github.com/ArmisSecurity/armis-cli/internal/auth/auth.go:124:			GetTenantID				85.7%
github.com/ArmisSecurity/armis-cli/internal/auth/auth.go:141:			GetRegion				85.7%
github.com/ArmisSecurity/armis-cli/internal/auth/auth.go:156:			IsLegacy				100.0%
github.com/ArmisSecurity/armis-cli/internal/auth/auth.go:169:			GetRawToken				85.7%
github.com/ArmisSecurity/armis-cli/internal/auth/auth.go:197:			exchangeCredentials			87.9%
github.com/ArmisSecurity/armis-cli/internal/auth/auth.go:268:			refreshIfNeeded				100.0%
github.com/ArmisSecurity/armis-cli/internal/auth/auth.go:300:			parseJWTClaims				93.3%
github.com/ArmisSecurity/armis-cli/internal/auth/client.go:32:			Error					100.0%
github.com/ArmisSecurity/armis-cli/internal/auth/client.go:44:			NewAuthClient				100.0%
github.com/ArmisSecurity/armis-cli/internal/auth/client.go:100:			Authenticate				77.4%
github.com/ArmisSecurity/armis-cli/internal/auth/region_cache.go:34:		NewRegionCache				100.0%
github.com/ArmisSecurity/armis-cli/internal/auth/region_cache.go:40:		Load					82.4%
github.com/ArmisSecurity/armis-cli/internal/auth/region_cache.go:75:		Save					76.9%
github.com/ArmisSecurity/armis-cli/internal/auth/region_cache.go:105:		Clear					75.0%
github.com/ArmisSecurity/armis-cli/internal/auth/region_cache.go:115:		getFilePath				83.3%
github.com/ArmisSecurity/armis-cli/internal/auth/region_cache.go:132:		loadCachedRegion			100.0%
github.com/ArmisSecurity/armis-cli/internal/auth/region_cache.go:136:		saveCachedRegion			100.0%
github.com/ArmisSecurity/armis-cli/internal/auth/region_cache.go:140:		clearCachedRegion			100.0%
github.com/ArmisSecurity/armis-cli/internal/cli/color.go:60:			InitColors				85.2%
github.com/ArmisSecurity/armis-cli/internal/cli/color.go:107:			ColorsEnabled				100.0%
github.com/ArmisSecurity/armis-cli/internal/cli/color.go:113:			ColorsForced				100.0%
github.com/ArmisSecurity/armis-cli/internal/cli/color.go:119:			SetOutputToFile				100.0%
github.com/ArmisSecurity/armis-cli/internal/cli/color.go:125:			GetOutputToFile				0.0%
github.com/ArmisSecurity/armis-cli/internal/cli/color.go:129:			enableColors				100.0%
github.com/ArmisSecurity/armis-cli/internal/cli/color.go:136:			disableColors				100.0%
github.com/ArmisSecurity/armis-cli/internal/cli/color.go:151:			parseErrorMessage			92.9%
github.com/ArmisSecurity/armis-cli/internal/cli/color.go:182:			PrintError				100.0%
github.com/ArmisSecurity/armis-cli/internal/cli/color.go:195:			PrintErrorf				0.0%
github.com/ArmisSecurity/armis-cli/internal/cli/color.go:202:			PrintWarning				100.0%
github.com/ArmisSecurity/armis-cli/internal/cli/color.go:208:			PrintWarningf				100.0%
github.com/ArmisSecurity/armis-cli/internal/cli/interactive.go:11:		IsInteractive				0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/agent_detection.go:36:		init					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/agent_detection.go:41:		runAgentDetection			0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/agent_detection_collect.go:29:	init					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/agent_detection_collect.go:33:	runAgentDetectionCollect		0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/agent_detection_collect.go:84:	buildInventoryPayload			100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/auth.go:33:			init					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/auth.go:39:			runAuth					92.9%
github.com/ArmisSecurity/armis-cli/internal/cmd/context.go:24:			NewSignalContext			100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/context.go:33:			handleScanError				100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/help.go:30:			SetupHelp				91.7%
github.com/ArmisSecurity/armis-cli/internal/cmd/help.go:59:			styledUsageTemplate			100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/help.go:102:			defaultUsageTemplate			100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/help.go:109:			initColorsForHelp			35.3%
github.com/ArmisSecurity/armis-cli/internal/cmd/help.go:150:			styleHelpOutput				83.3%
github.com/ArmisSecurity/armis-cli/internal/cmd/hook.go:24:			init					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/hook_init.go:32:		init					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/hook_init.go:38:		runHookInit				0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/install.go:61:			init					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/install.go:70:			runInstall				0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/install.go:106:			showInstalledVersions			84.6%
github.com/ArmisSecurity/armis-cli/internal/cmd/install.go:129:			installAll				0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/install.go:198:			installTargets				33.3%
github.com/ArmisSecurity/armis-cli/internal/cmd/install.go:311:			printCredentialStatus			100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/install_interactive.go:16:	runInteractiveInstall			0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/install_interactive.go:221:	collectCredentials			0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/install_interactive.go:332:	validateAndReport			0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/install_interactive.go:355:	selectEditors				0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/install_interactive.go:415:	offerHookSetup				0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/install_theme.go:24:		armisTheme				0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/install_theme.go:62:		getInstallTheme				0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/output_helper.go:27:		Cleanup					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/output_helper.go:53:		ResolveOutput				96.4%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:168:			SetVersion				100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:176:			Execute					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:180:			init					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:211:			PrintUpdateNotification			81.2%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:253:			printUpdateNotificationOnce		75.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:266:			getEnvOrDefault				100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:273:			getEnvOrDefaultInt			100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:285:			getAPIBaseURL				100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:297:			getAuthProvider				100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:309:			getPageLimit				100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:316:			validatePageLimit			100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:326:			validateFailOn				100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:344:			getFailOn				100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/scan.go:92:			init					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/scan_image.go:156:		init					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/scan_repo.go:195:		init					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/uninstall.go:40:		init					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/uninstall.go:46:		runUninstall				0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/uninstall.go:65:		uninstallAll				33.8%
github.com/ArmisSecurity/armis-cli/internal/cmd/uninstall.go:183:		uninstallTargets			59.6%
github.com/ArmisSecurity/armis-cli/internal/cmd/uninstall.go:288:		confirm					100.0%
github.com/ArmisSecurity/armis-cli/internal/httpclient/client.go:31:		NewClient				92.3%
github.com/ArmisSecurity/armis-cli/internal/httpclient/client.go:61:		Do					86.1%
github.com/ArmisSecurity/armis-cli/internal/install/claude.go:23:		NewClaudeInstaller			75.0%
github.com/ArmisSecurity/armis-cli/internal/install/claude.go:35:		InstalledVersion			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/claude.go:40:		Install					14.3%
github.com/ArmisSecurity/armis-cli/internal/install/claude.go:72:		pluginCacheDir				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/claude.go:77:		PluginCacheDir				0.0%
github.com/ArmisSecurity/armis-cli/internal/install/claude.go:82:		EnvFilePath				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/claude.go:87:		GetInstalledVersion			76.2%
github.com/ArmisSecurity/armis-cli/internal/install/claude.go:119:		HasExistingEnv				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/claude.go:124:		registerMarketplace			83.3%
github.com/ArmisSecurity/armis-cli/internal/install/claude.go:141:		registerPlugin				75.0%
github.com/ArmisSecurity/armis-cli/internal/install/claude.go:170:		enablePlugin				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:55:		EditorByID				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:68:		ConfigPath				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:79:		IsDetected				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:89:		Register				75.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:98:		DetectedEditors				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:115:		NewEditorInstaller			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:125:		InstalledVersion			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:128:		PluginDir				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:131:		EnvFilePath				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:134:		HasExistingEnv				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:145:		FetchPlugin				0.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:171:		GetInstalledVersion			80.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:181:		RegisterJetBrains			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:187:		defaultConfigPath			83.3%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:224:		homeDir					75.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:232:		appSupportPath				29.4%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:265:		registerEditor				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:279:		registerMCPServersFormat		100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:293:		registerVSCodeFormat			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:312:		registerZedFormat			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:331:		stdServerEntry				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:338:		readJSONFileAsMap			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/hooks.go:19:		InstallHooks				0.0%
github.com/ArmisSecurity/armis-cli/internal/install/hooks.go:30:		installHooksToFile			89.3%
github.com/ArmisSecurity/armis-cli/internal/install/hooks.go:95:		RemoveHooks				0.0%
github.com/ArmisSecurity/armis-cli/internal/install/hooks.go:106:		removeHooksFromFile			74.3%
github.com/ArmisSecurity/armis-cli/internal/install/hooks.go:166:		isArmisHookEntry			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/hooks.go:178:		isArmisHookCommand			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/manifest.go:38:		ManifestPath				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/manifest.go:55:		ReadManifest				80.0%
github.com/ArmisSecurity/armis-cli/internal/install/manifest.go:72:		WriteManifest				66.7%
github.com/ArmisSecurity/armis-cli/internal/install/manifest.go:84:		NewManifest				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/manifest.go:95:		AddEditor				66.7%
github.com/ArmisSecurity/armis-cli/internal/install/manifest.go:103:		RemoveEditor				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/manifest.go:108:		SetClaude				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/manifest.go:113:		ConfigFormat				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:73:		HookClientByID				75.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:83:		ConfigPath				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:88:		IsDetected				80.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:98:		DetectHookClients			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:111:	hookConfigPath				75.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:122:	InstallNativeHook			72.7%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:146:	RemoveNativeHook			83.3%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:158:	installClientHook			85.7%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:175:	removeClientHook			50.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:188:	cursorHooksPath				50.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:194:	geminiHooksPath				50.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:200:	codexHooksPath				50.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:206:	copilotHooksPath			9.1%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:227:	clineHooksPath				16.7%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:251:	readJSONFileAsMapSafe			72.7%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:272:	installMergedHook			93.3%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:299:	removeMergedHook			0.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:333:	installCursorHook			94.1%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:364:	removeCursorHook			72.2%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:398:	installCopilotHook			94.1%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:429:	removeCopilotHook			0.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:436:	buildCursorHooks			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:459:	buildGeminiHooks			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:480:	buildCodexHooks				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:511:	buildCopilotHooks			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:528:	buildClineHooks				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:546:	hasArmisHookEntries			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:555:	filterNonArmisEntries			80.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:565:	isArmisHookJSON				80.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:582:	posixQuote				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:586:	quotedCommand				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:53:		newPluginInstaller			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:61:		InstalledVersion			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:66:		LatestVersion				0.0%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:75:		FetchAndInstall				0.0%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:97:		fetchLatestRelease			69.6%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:137:		downloadAndExtract			73.6%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:253:		createVenv				0.0%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:286:		validateGitHubURL			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:300:		extractFile				57.1%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:312:		writeJSON				66.7%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:323:		findPython				76.9%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:350:		writeEnvFromEnvironment			85.7%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:381:		WriteEnvFromValues			55.9%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:443:		copyFile				63.6%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:463:		venvPython				66.7%
github.com/ArmisSecurity/armis-cli/internal/install/precommit.go:25:		InstallPreCommit			71.4%
github.com/ArmisSecurity/armis-cli/internal/install/precommit.go:80:		RemovePreCommit				79.3%
github.com/ArmisSecurity/armis-cli/internal/install/precommit.go:133:		IsPreCommitInstalled			87.5%
github.com/ArmisSecurity/armis-cli/internal/install/precommit.go:149:		resolveHooksDir				39.1%
github.com/ArmisSecurity/armis-cli/internal/install/precommit.go:190:		DetectGitRoot				0.0%
github.com/ArmisSecurity/armis-cli/internal/install/precommit.go:199:		buildPreCommitSection			83.3%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:19:		NewUninstaller				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:28:		HasManifest				0.0%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:33:		PluginDir				0.0%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:38:		DeregisterEditor			0.0%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:59:		DeregisterAllEditors			80.6%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:110:		DeregisterClaude			64.7%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:144:		RemovePluginFiles			64.7%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:178:		editorConfigPath			0.0%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:189:		deregisterEditor			40.0%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:202:		deregisterFromFile			66.7%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:209:		deregisterMCPServersFormat		100.0%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:225:		deregisterVSCodeFormat			77.8%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:241:		deregisterZedFormat			77.8%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:257:		removeContinueFile			75.0%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:271:		removeFromMarketplace			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:276:		removeFromInstalledPlugins		100.0%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:281:		removeFromSettings			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:286:		removeJSONKey				55.6%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:301:		removeNestedJSONKey			61.5%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:321:		hasArmisEntry				83.3%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:343:		readAndParseJSON			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:355:		writeJSONAtomic				55.0%
github.com/ArmisSecurity/armis-cli/internal/install/validate.go:23:		ValidateCredentials			0.0%
github.com/ArmisSecurity/armis-cli/internal/install/validate.go:28:		resolveBaseURL				0.0%
github.com/ArmisSecurity/armis-cli/internal/install/validate.go:38:		validateCredentialsWithURL		100.0%
github.com/ArmisSecurity/armis-cli/internal/output/errno_unix.go:12:		isSyncNotSupported			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:55:			wrapText				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:78:			wrapLine				91.7%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:116:		formatRecommendations			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:186:		wrapTextWithFirstLinePrefix		90.9%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:225:		write					66.7%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:256:		Write					89.5%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:286:		Format					100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:291:		FormatWithOptions			88.1%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:380:		SyncColors				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:384:		sortFindingsBySeverity			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:395:		loadSnippetFromFile			69.4%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:511:		formatCodeSnippetWithFrame		91.1%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:604:		truncatePlainLine			0.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:616:		highlightColumns			93.5%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:661:		scanDuration				89.5%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:694:		pluralize				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:703:		suppressionSummaryText			80.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:731:		renderBriefStatus			87.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:788:		renderSummaryDashboard			59.5%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:875:		renderFindings				88.9%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:904:		renderFinding				54.5%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1016:		renderGroupedFindings			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1040:		groupFindings				96.8%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1097:		severityRank				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1104:		isGitRepo				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1111:		getGitBlame				38.1%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1149:		parseGitBlame				95.2%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1185:		maskEmail				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1208:		getTopLevelDomain			75.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1220:		getHumanDisplayTitle			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1234:		wrapTitle				93.9%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1293:		maskFixForDisplay			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1328:		formatFixSection			0.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1393:		formatProposedSnippet			0.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1476:		limitHunkContext			64.7%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1552:		parseDiffHunk				91.7%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1574:		parseDiffLines				94.6%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1665:		findInlineChanges			73.5%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1736:		computeLCS				92.3%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1788:		buildTokenPositions			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1804:		tokenizeLine				92.9%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1832:		isWordChar				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1839:		formatDiffWithColorsStyled		77.1%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1913:		extractDiffFilename			80.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1935:		formatDiffHunkLine			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1955:		formatDiffContextLine			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1966:		formatDiffRemoveLine			86.4%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:2007:		formatDiffAddLine			86.4%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:2049:		applyInlineHighlights			81.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:2091:		truncateDiffLine			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:2098:		truncateDiffLineWithFlag		66.7%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:2112:		adjustHighlightSpans			83.3%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:2134:		groupDiffHunks				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:2165:		collectRenderOps			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:2208:		renderChangeBlock			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:2267:		formatDiffHunkSeparator			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:2282:		formatValidationSection			0.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:2339:		getExposureDescription			0.0%
github.com/ArmisSecurity/armis-cli/internal/output/icons.go:24:			GetConfidenceIcon			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/json.go:15:			Format					100.0%
github.com/ArmisSecurity/armis-cli/internal/output/json.go:24:			FormatWithOptions			66.7%
github.com/ArmisSecurity/armis-cli/internal/output/json.go:32:			formatWithDebug				0.0%
github.com/ArmisSecurity/armis-cli/internal/output/json.go:58:			maskScanResultForOutput			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/json.go:78:			maskFindingSecrets			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/junit.go:48:			Format					100.0%
github.com/ArmisSecurity/armis-cli/internal/output/junit.go:55:			FormatWithOptions			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/junit.go:63:			formatWithSeverities			77.8%
github.com/ArmisSecurity/armis-cli/internal/output/junit.go:92:			isFailureSeverity			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/junit.go:102:		convertToJUnitCasesWithSeverities	100.0%
github.com/ArmisSecurity/armis-cli/internal/output/junit.go:135:		countFailuresWithSeverities		100.0%
github.com/ArmisSecurity/armis-cli/internal/output/output.go:26:		Error					0.0%
github.com/ArmisSecurity/armis-cli/internal/output/output.go:37:		Error					0.0%
github.com/ArmisSecurity/armis-cli/internal/output/output.go:58:		GetFormatter				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/output.go:75:		ShouldFail				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/output.go:94:		FilterActiveFindings			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/output.go:107:		CheckExit				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:174:		normalizeCWE				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:183:		normalizeCVE				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:193:		stripMarkdown				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:205:		Format					100.0%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:232:		firstNonEmpty				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:251:		stableRuleID				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:269:		buildRules				96.3%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:340:		convertToSarifResults			90.3%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:441:		buildMessageText			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:448:		severityToSarifLevel			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:467:		severityToSecurityScore			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:486:		generateHelpURI				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:510:		convertFixToSarif			90.5%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:627:		FormatWithOptions			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/styles.go:138:		DefaultStyles				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/styles.go:276:		NoColorStyles				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/styles.go:353:		GetStyles				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/styles.go:361:		SyncStylesWithColorMode			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/styles.go:386:		GetSeverityText				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/styles.go:414:		TerminalWidth				33.3%
github.com/ArmisSecurity/armis-cli/internal/output/syntax.go:21:		GetLexer				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/syntax.go:32:		GetChromaStyle				80.0%
github.com/ArmisSecurity/armis-cli/internal/output/syntax.go:45:		HighlightCode				81.2%
github.com/ArmisSecurity/armis-cli/internal/output/syntax.go:79:		HighlightLine				75.0%
github.com/ArmisSecurity/armis-cli/internal/output/syntax.go:88:		getTerminalFormatter			60.0%
github.com/ArmisSecurity/armis-cli/internal/output/syntax.go:103:		HighlightLineWithBackground		87.5%
github.com/ArmisSecurity/armis-cli/internal/output/syntax.go:126:		getBackgroundANSI			58.3%
github.com/ArmisSecurity/armis-cli/internal/output/syntax.go:158:		rgbToANSI256				0.0%
github.com/ArmisSecurity/armis-cli/internal/output/syntax.go:171:		parseHexColor				76.9%
github.com/ArmisSecurity/armis-cli/internal/output/writer.go:51:		validateOutputPath			92.3%
github.com/ArmisSecurity/armis-cli/internal/output/writer.go:88:		NewFileOutput				88.2%
github.com/ArmisSecurity/armis-cli/internal/output/writer.go:145:		Writer					100.0%
github.com/ArmisSecurity/armis-cli/internal/output/writer.go:150:		Close					100.0%
github.com/ArmisSecurity/armis-cli/internal/output/writer.go:167:		FormatFromExtension			100.0%
github.com/ArmisSecurity/armis-cli/internal/progress/progress.go:32:		IsCI					100.0%
github.com/ArmisSecurity/armis-cli/internal/progress/progress.go:60:		isTerminalWriter			100.0%
github.com/ArmisSecurity/armis-cli/internal/progress/progress.go:68:		NewReader				100.0%
github.com/ArmisSecurity/armis-cli/internal/progress/progress.go:83:		NewWriter				50.0%
github.com/ArmisSecurity/armis-cli/internal/progress/progress.go:117:		NewSpinner				100.0%
github.com/ArmisSecurity/armis-cli/internal/progress/progress.go:125:		NewSpinnerWithTimeout			100.0%
github.com/ArmisSecurity/armis-cli/internal/progress/progress.go:142:		NewSpinnerWithContext			100.0%
github.com/ArmisSecurity/armis-cli/internal/progress/progress.go:150:		SetWriter				100.0%
github.com/ArmisSecurity/armis-cli/internal/progress/progress.go:159:		Start					89.8%
github.com/ArmisSecurity/armis-cli/internal/progress/progress.go:275:		Stop					100.0%
github.com/ArmisSecurity/armis-cli/internal/progress/progress.go:310:		Update					100.0%
github.com/ArmisSecurity/armis-cli/internal/progress/progress.go:317:		GetElapsed				100.0%
github.com/ArmisSecurity/armis-cli/internal/progress/progress.go:324:		formatDuration				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/finding_type.go:9:		DeriveFindingType			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:48:		NewScanner				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:63:		WithPollInterval			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:69:		WithFetchRetryInterval			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:75:		WithSBOMVEXOptions			0.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:82:		WithPullPolicy				0.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:88:		ScanImage				0.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:119:		ScanTarball				77.8%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:231:		exportImage				0.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:285:		isDockerAvailable			42.9%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:300:		getDockerCommand			75.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:309:		validateDockerCommand			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:318:		imageExistsLocally			87.5%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:333:		determinePullBehavior			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:351:		isRetryableError			75.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:359:		buildScanResult				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:386:		convertNormalizedFindings		85.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:509:		shouldFilterByExploitability		100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:528:		cleanDescription			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:547:		isEmptyFinding				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:562:		generateFindingTitle			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/validate.go:11:		validateImageName			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/mask.go:22:			MaskFixSecrets				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/files.go:26:		ParseFileList				87.5%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/files.go:41:		addFile					87.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/files.go:94:		Files					100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/files.go:99:		RepoRoot				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/files.go:104:		ValidateExistence			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/gitchanges.go:52:		GitChangedFiles				82.6%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/gitchanges.go:103:	gitRepoRoot				80.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/gitchanges.go:128:	changedUncommitted			41.7%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/gitchanges.go:157:	changedStaged				75.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/gitchanges.go:170:	validateRef				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/gitchanges.go:183:	changedSinceRef				75.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/gitchanges.go:206:	filterToScanPath			95.8%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/gitchanges.go:259:	runGit					91.7%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/gitchanges.go:286:	parseLines				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/gitchanges.go:306:	combineAndDedupe			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/ignore.go:28:		LoadIgnorePatterns			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/ignore.go:36:		LoadSuppressionConfig			0.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/ignore.go:78:		LoadArmisIgnore				92.9%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/ignore.go:138:		parseArmisIgnoreFile			92.5%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/ignore.go:204:		Match					100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/ignore.go:216:		shouldSkipDir				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/inline.go:85:		ApplyInlineSuppression			97.2%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/inline.go:214:		parseInlineComment			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/inline.go:241:		isCommentLine				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/inline.go:255:		isFuncSignature				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/inline.go:268:		containsAny				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/inline.go:282:		findCommentStart			83.3%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/inline.go:322:		parseDirectiveParams			93.9%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/inline.go:380:		matchesInlineDirective			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/inline.go:416:		buildInlineSuppressionInfo		100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/inline.go:444:		countSuppressed				0.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/matcher.go:28:		MatchFinding				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/matcher.go:62:		cweMatches				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/matcher.go:78:		ApplySuppression			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/matcher.go:101:		recomputeSummary			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:46:		NewScanner				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:61:		WithPollInterval			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:67:		WithFetchRetryInterval			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:73:		WithIncludeFiles			0.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:79:		WithSBOMVEXOptions			0.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:85:		Scan					67.9%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:293:		tarGzDirectory				71.8%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:374:		isPathContained				75.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:383:		tarGzFiles				78.6%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:474:		safeAddSize				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:481:		calculateFilesSize			78.6%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:507:		calculateDirSize			76.9%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:554:		shouldSkip				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:585:		isTestFile				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:631:		isRetryableError			75.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:640:		buildScanResult				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:667:		convertNormalizedFindings		73.3%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:790:		shouldFilterByExploitability		100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:809:		cleanDescription			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:830:		generateFindingTitle			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:834:		isEmptyFinding				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/suppression.go:58:	NewSuppressionConfig			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/suppression.go:63:	IsEmpty					100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/suppression.go:77:	Add					100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/suppression.go:99:	CategoryMapping				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/suppression.go:112:	parseDirectiveLine			93.5%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/suppression.go:173:	hasDirectivePrefix			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/suppression.go:187:	validateCWE				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/sbom_vex.go:38:		NewSBOMVEXDownloader			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/sbom_vex.go:50:		Download				85.2%
github.com/ArmisSecurity/armis-cli/internal/scan/sbom_vex.go:102:		downloadAndSave				77.8%
github.com/ArmisSecurity/armis-cli/internal/scan/status.go:16:			FormatScanStatus			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/status.go:35:			FormatElapsed				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/status.go:48:			MapSeverity				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/testhelpers/findings.go:9:	CreateNormalizedFinding			0.0%
github.com/ArmisSecurity/armis-cli/internal/scan/testhelpers/findings.go:14:	CreateNormalizedFindingWithLabels	0.0%
github.com/ArmisSecurity/armis-cli/internal/scan/testhelpers/findings.go:19:	CreateNormalizedFindingFull		0.0%
github.com/ArmisSecurity/armis-cli/internal/scan/title.go:14:			GenerateFindingTitle			100.0%
github.com/ArmisSecurity/armis-cli/internal/update/update.go:63:		NewChecker				100.0%
github.com/ArmisSecurity/armis-cli/internal/update/update.go:79:		CheckCached				100.0%
github.com/ArmisSecurity/armis-cli/internal/update/update.go:97:		CheckInBackground			100.0%
github.com/ArmisSecurity/armis-cli/internal/update/update.go:117:		check					85.7%
github.com/ArmisSecurity/armis-cli/internal/update/update.go:160:		fetchLatestVersion			89.5%
github.com/ArmisSecurity/armis-cli/internal/update/update.go:194:		getCacheFilePath			66.7%
github.com/ArmisSecurity/armis-cli/internal/update/update.go:209:		readCache				84.6%
github.com/ArmisSecurity/armis-cli/internal/update/update.go:233:		writeCache				76.9%
github.com/ArmisSecurity/armis-cli/internal/update/update.go:257:		IsNewer					100.0%
github.com/ArmisSecurity/armis-cli/internal/update/update.go:280:		parseVersion				100.0%
github.com/ArmisSecurity/armis-cli/internal/update/update.go:303:		FormatNotification			100.0%
github.com/ArmisSecurity/armis-cli/internal/update/update.go:322:		getUpdateCommand			40.0%
github.com/ArmisSecurity/armis-cli/internal/util/cache.go:21:			GetCacheDir				75.0%
github.com/ArmisSecurity/armis-cli/internal/util/cache.go:41:			GetCacheFilePath			80.0%
github.com/ArmisSecurity/armis-cli/internal/util/format.go:7:			FormatCategory				100.0%
github.com/ArmisSecurity/armis-cli/internal/util/mask.go:109:			MaskSecretInLine			86.4%
github.com/ArmisSecurity/armis-cli/internal/util/mask.go:164:			maskValue				83.3%
github.com/ArmisSecurity/armis-cli/internal/util/mask.go:190:			MaskSecretInLines			100.0%
github.com/ArmisSecurity/armis-cli/internal/util/mask.go:204:			MaskSecretInMultiLineString		100.0%
github.com/ArmisSecurity/armis-cli/internal/util/mask.go:218:			MaskSecretsInStringMap			100.0%
github.com/ArmisSecurity/armis-cli/internal/util/path.go:13:			SanitizePath				90.9%
github.com/ArmisSecurity/armis-cli/internal/util/path.go:53:			SafeJoinPath				87.5%
github.com/ArmisSecurity/armis-cli/test/sample-repo/src/main.go:6:		main					0.0%
total:										(statements)				72.2%

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an interactive armis-cli install --interactive wizard to simplify MCP server installation across supported editors, including optional security scanning hooks (native client hooks + git pre-commit) and credential validation. This fits into the CLI’s existing installer/uninstaller flow by automating config file updates and adding guardrails (validation, atomic writes, backups).

Changes:

  • Introduces an interactive TUI install flow (theme/accessibility-aware) with credential collection + validation and editor selection.
  • Adds hook management: Claude settings hooks, native hook configs for multiple AI clients, and repo-level git pre-commit hook install/remove logic.
  • Hardens install/uninstall plumbing with atomic file writes, backups, config parsing safety, and shared production base URL centralization.

Reviewed changes

Copilot reviewed 24 out of 25 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
scripts/install.sh Adds additional scanner suppression annotation for installer verification/move logic.
scripts/install.ps1 Adds scanner suppression annotations around archive extraction paths.
internal/scan/image/image.go Adds suppression annotations for docker pull/save command execution.
internal/install/validate.go New credential validation helper (supports ARMIS_API_URL/ARMIS_REGION).
internal/install/validate_test.go Unit tests for credential validation success/failure modes.
internal/install/precommit.go New git pre-commit hook installer/remover with worktree/submodule support.
internal/install/precommit_test.go Unit tests covering pre-commit install/remove/idempotency/fallback behavior.
internal/install/plugin.go Adds .env writer with backup + atomic write semantics.
internal/install/plugin_test.go Unit tests for .env writing, backup creation, and permissions.
internal/install/native_hooks.go New native hook client detection + config install/remove for multiple tools.
internal/install/native_hooks_test.go Unit tests for native hook install/remove/merge/idempotency and detection.
internal/install/hooks.go New Claude Code settings hook install/remove (with file size sanity guard).
internal/install/hooks_test.go Unit tests for Claude hook install/remove/idempotency and JSON parse errors.
internal/httpclient/client.go Adds suppression annotation for an upstream-validated URL error branch.
internal/cmd/uninstall.go Enhances uninstall output styling and adds native hook removal for full uninstall.
internal/cmd/root.go Uses auth.ProductionBaseURL instead of duplicating the production URL constant.
internal/cmd/install.go Adds --interactive / --non-interactive flags and routes to wizard when appropriate.
internal/cmd/install_theme.go Adds a custom huh theme and disables it when colors are disabled.
internal/cmd/install_interactive.go New interactive install wizard logic: credentials, editors, hooks, manifest updates.
internal/cmd/hook.go Adds armis-cli hook command group for hook management.
internal/cmd/hook_init.go Adds armis-cli hook init to install/remove repo pre-commit hook.
internal/cli/interactive.go Adds cli.IsInteractive() helper (stdin+stderr TTY detection).
internal/auth/client.go Adds ProductionBaseURL constant and additional scanner suppressions.
go.mod Adds github.com/charmbracelet/huh dependency (and related indirect deps).
go.sum Updates checksums for newly added/updated dependencies.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/install/native_hooks.go Outdated
data["version"] = 1
}

hooks := buildCursorHooks(pluginDir).(map[string]interface{})
Comment thread internal/install/native_hooks.go Outdated
data["version"] = 1
}

hooks := buildCopilotHooks(pluginDir).(map[string]interface{})
Comment thread internal/cmd/install_interactive.go Outdated
return "", "", true, false
}
if err := validateAndReport(clientID, clientSecret, accessible); err != nil {
fmt.Fprintln(os.Stderr, " Proceeding without credential validation. You can fix the .env file later.")
Comment thread internal/cmd/uninstall.go
Comment on lines 224 to 229
case targetCopilot:
if err := u.DeregisterEditor(install.EditorVSCode); err != nil {
fmt.Fprintf(os.Stderr, " ✗ VS Code: %v\n", err)
printFail(fmt.Sprintf("VS Code: %v", err))
} else {
fmt.Fprintf(os.Stderr, " ✓ VS Code\n")
printSuccess("VS Code")
}
Comment thread internal/cmd/uninstall.go
Comment on lines 238 to 249
default:
id := install.EditorID(name)
e, ok := install.EditorByID(id)
if !ok {
fmt.Fprintf(os.Stderr, " ✗ Unknown editor: %s\n", name)
printFail(fmt.Sprintf("Unknown editor: %s", name))
continue
}
if err := u.DeregisterEditor(id); err != nil {
fmt.Fprintf(os.Stderr, " ✗ %s: %v\n", e.Name, err)
printFail(fmt.Sprintf("%s: %v", e.Name, err))
} else {
fmt.Fprintf(os.Stderr, " ✓ %s\n", e.Name)
printSuccess(e.Name)
}
- Replace unchecked type assertions with concrete return types for all
  buildHooks functions, eliminating potential panics
- Fix misleading credential skip message to clarify credentials are not saved
- Add native hook removal to per-target uninstall so editor hook configs
  are cleaned up alongside MCP deregistration
Copilot AI review requested due to automatic review settings May 26, 2026 15:25
Comment thread internal/cmd/install_interactive.go Dismissed
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 24 out of 25 changed files in this pull request and generated 2 comments.

Comment on lines +429 to +434
closed = true
// armis:ignore cwe:22 reason:cleanPath derived from known plugin dir + ".env", not external input
if err := os.Rename(tmpPath, cleanPath); err != nil { //nolint:gosec // G703: both paths from known plugin dir
_ = os.Remove(tmpPath) //nolint:gosec // G703: tmpPath from os.CreateTemp in known plugin dir
return fmt.Errorf("finalizing env file: %w", err)
}
Comment thread internal/install/precommit.go Outdated
gitEntry := filepath.Join(repoRoot, ".git")
// armis:ignore cwe:73 reason:repoRoot validated as absolute path above; .git is a hardcoded segment
if _, err := os.Stat(gitEntry); err != nil {
return fmt.Errorf("not a git repository (no .git): %s", repoRoot)
… write

- Distinguish ENOENT from other stat errors when checking .git directory
- Handle Windows os.Rename limitation by retrying after removing destination
The install wizard sets up MCP integrations, not the CLI scanner.
The 'armis-cli scan repo .' suggestion was unrelated to the install flow.
Copilot AI review requested due to automatic review settings May 26, 2026 19:00
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 24 out of 25 changed files in this pull request and generated 2 comments.

// armis:ignore cwe:73 reason:bakPath derived from cleanPath which is constructed from known plugin dir + ".env"
if err := copyFile(cleanPath, bakPath); err != nil {
return fmt.Errorf("could not back up %s: %w", filepath.Base(cleanPath), err)
}
Comment on lines +431 to +437
if err := os.Rename(tmpPath, cleanPath); err != nil { //nolint:gosec // G703: both paths from known plugin dir
// On Windows, Rename fails if destination exists; remove and retry.
_ = os.Remove(cleanPath) //nolint:gosec // G703: cleanPath from known plugin dir; already backed up above
if retryErr := os.Rename(tmpPath, cleanPath); retryErr != nil {
_ = os.Remove(tmpPath) //nolint:gosec // G703: tmpPath from os.CreateTemp in known plugin dir
return fmt.Errorf("finalizing env file: %w", retryErr)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants