-
Notifications
You must be signed in to change notification settings - Fork 1
fix(install): validate git/glibc upfront and tighten Gemini hook checks #54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -37,6 +37,14 @@ | |
|
|
||
| The installer downloads Autter into `~/.autter/bin`, adds it to your user `PATH`, configures supported coding agents and editors, and starts the background service. On macOS, Linux, and WSL it then starts onboarding when the shell is interactive. Automated or non-interactive installs can finish onboarding later. | ||
|
|
||
| ### System requirements | ||
|
|
||
| - **git** 2.22 or newer (required) | ||
| - **Linux**: glibc 2.35 or newer (Ubuntu 22.04+, Debian 12+, Fedora 36+). Ubuntu 20.04 and older WSL2 distros are not supported natively — use a newer WSL distro or run inside an `ubuntu:22.04` Docker container | ||
| - **macOS**: 11 (Big Sur) or newer | ||
| - **Windows**: 10 or newer | ||
| - **npm path**: Node.js 18+ | ||
|
|
||
| On macOS, Linux, and WSL, make `autter` available in the terminal you already have open (the installer prints this command at the end too): | ||
|
|
||
| ```bash | ||
|
|
@@ -47,9 +55,12 @@ | |
|
|
||
| ```bash | ||
| autter --version | ||
| autter debug | ||
| autter doctor # v1.6.10+ — focused setup validation (exits 1 on failure) | ||
| autter debug # full support dump (always exits 0) | ||
| ``` | ||
|
|
||
| `autter doctor` runs end-to-end checks (git proxy, hooks, checkpoint round-trip). On v1.6.9 and earlier, use `autter debug` instead. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 [deterministic] markdownlint: MD013 — Risk: 30/100 Line length: Expected: 80; Actual: 132 🛠 AI fix prompt (copy & paste into your coding agent)Flagged by Autter security & observability checks. |
||
|
|
||
| You do not need to configure each repository separately. Continue using Git, your IDE, and your coding agents as usual. | ||
|
|
||
| > Using Nix? See the [Nix installation guide](README-nix.md) for NixOS, nix-darwin, and Home Manager options. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -54,6 +54,8 @@ | |
|
|
||
| The npm package is a thin bootstrapper: it downloads the same release binary into `~/.autter/bin` and verifies its checksum, so hooks and self-updates work identically to the script installs. | ||
|
|
||
| **System requirements:** git 2.22+, Linux glibc 2.35+ (Ubuntu 22.04+), macOS 11+, Windows 10+, Node.js 18+ for the npm path. See [INSTALL.md](INSTALL.md) for details including Docker-based setup on older Linux distros. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 [deterministic] markdownlint: MD013 — Risk: 30/100 Line length: Expected: 80; Actual: 218 🛠 AI fix prompt (copy & paste into your coding agent)Flagged by Autter security & observability checks. |
||
|
|
||
| > **Git Bash is not WSL.** The bash installer needs a real Linux environment, so on Windows it only runs inside [WSL](https://learn.microsoft.com/windows/wsl/about) — in Git Bash it exits with instructions. Use the Windows command instead (it works from Git Bash too), and install the CLI where your coding agents actually run: agents launched from Windows need the native install, agents inside WSL need the WSL install. | ||
|
|
||
| Signed in to Autter? [**Settings → CLI setup**](https://app.autter.dev/cli/install) in the dashboard generates a single-use command that runs this same installer **and signs the machine in automatically** via a short-lived signed token — no separate login step. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -335,6 +335,16 @@ | |
| } | ||
| $os = 'windows' | ||
|
|
||
| # git is required — autter wraps git and cannot function without it. | ||
|
Check warning on line 338 in install.ps1
|
||
| try { | ||
| $null = & git --version 2>&1 | ||
|
Check failure on line 340 in install.ps1
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟠 [ai] Reject old Git versions in the PowerShell installer — Risk: 72/100 The PowerShell preflight treats a successful
🛠 AI fix prompt (copy & paste into your coding agent)Flagged by Autter security & observability checks. |
||
| if ($LASTEXITCODE -ne 0) { | ||
| Write-ErrorAndExit 'git is required but not found. Install Git for Windows (https://git-scm.com/download/win) and re-run the installer.' | ||
| } | ||
| } catch { | ||
| Write-ErrorAndExit 'git is required but not found. Install Git for Windows (https://git-scm.com/download/win) and re-run the installer.' | ||
| } | ||
|
|
||
| # Determine binary name and download URLs | ||
| $binaryName = "autter-$os-$arch" | ||
|
|
||
|
|
@@ -604,6 +614,20 @@ | |
| Move-Item -Force -Path $tmpFile -Destination $finalExe | ||
| try { Unblock-File -Path $finalExe -ErrorAction SilentlyContinue } catch { } | ||
|
|
||
| # Verify the binary runs before reporting success. | ||
| try { | ||
| $installedVersion = & $finalExe --version 2>&1 | Out-String | ||
| $installedVersion = $installedVersion.Trim() | ||
| if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrWhiteSpace($installedVersion)) { | ||
| Remove-Item -Force -ErrorAction SilentlyContinue $finalExe | ||
|
Check failure on line 622 in install.ps1
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 [ai] Restore the previous Windows executable on validation failure — Risk: 88/100
🛠 AI fix prompt (copy & paste into your coding agent)Flagged by Autter security & observability checks. |
||
| Write-ErrorAndExit "The autter binary could not run on this system:`n$installedVersion" | ||
| } | ||
| Write-Host "Installed autter $installedVersion" | ||
| } catch { | ||
| Remove-Item -Force -ErrorAction SilentlyContinue $finalExe | ||
| Write-ErrorAndExit "The autter binary could not run on this system: $($_.Exception.Message)" | ||
| } | ||
|
|
||
| # Refresh git.exe for existing wrapper users (it's a copy, not a symlink on Windows) | ||
| $gitShim = Join-Path $installDir 'git.exe' | ||
| if (Test-Path -LiteralPath $gitShim) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -277,6 +277,74 @@ | |
| ;; | ||
| esac | ||
|
|
||
| # Minimum glibc for Linux release binaries (built on Ubuntu 22.04). | ||
| MIN_GLIBC_MAJOR=2 | ||
| MIN_GLIBC_MINOR=35 | ||
|
|
||
| # Require git before downloading — autter wraps git and cannot function without it. | ||
| check_git() { | ||
|
Check failure on line 285 in install.sh
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟠 [ai] Enforce the documented minimum Git version before installing — Risk: 72/100 The new preflight only checks that
🛠 AI fix prompt (copy & paste into your coding agent)Flagged by Autter security & observability checks. |
||
| if ! command -v git >/dev/null 2>&1; then | ||
| error "git is required but not found. Install git 2.22 or newer, then re-run the installer." | ||
| fi | ||
| } | ||
|
|
||
| # Linux release binaries need glibc 2.35+ (Ubuntu 22.04). Ubuntu 20.04 / older WSL2 | ||
| # distros fail at runtime with GLIBC_2.32+ symbol errors — catch that up front. | ||
| check_linux_glibc() { | ||
| if [ "$OS" != "linux" ] || [ -n "${AUTTER_LOCAL_BINARY:-}" ]; then | ||
| return 0 | ||
| fi | ||
|
|
||
| if ! command -v ldd >/dev/null 2>&1; then | ||
| return 0 | ||
| fi | ||
|
|
||
| local glibc_version | ||
| glibc_version=$(ldd --version 2>&1 | head -n1 | grep -oE '[0-9]+\.[0-9]+' | head -n1) | ||
| if [ -z "$glibc_version" ]; then | ||
| return 0 | ||
| fi | ||
|
|
||
| local major minor | ||
| major=${glibc_version%%.*} | ||
| minor=${glibc_version#*.} | ||
|
|
||
| if [ "$major" -lt "$MIN_GLIBC_MAJOR" ] \ | ||
| || { [ "$major" -eq "$MIN_GLIBC_MAJOR" ] && [ "$minor" -lt "$MIN_GLIBC_MINOR" ]; }; then | ||
| error "Unsupported glibc version ($glibc_version). autter requires glibc ${MIN_GLIBC_MAJOR}.${MIN_GLIBC_MINOR} or newer (Ubuntu 22.04+, Debian 12+, Fedora 36+). | ||
|
|
||
| On Ubuntu 20.04 or older WSL2 distros, use a newer base image or run inside Docker: | ||
| docker run -it --rm -v \"\$PWD\":/work -w /work ubuntu:22.04 bash | ||
| # then re-run this installer inside the container" | ||
| fi | ||
| } | ||
|
|
||
| # Fail the install when the downloaded binary cannot execute (glibc mismatch, etc.). | ||
| verify_binary_runs() { | ||
| local bin="$1" | ||
| local output | ||
| if output=$("$bin" --version 2>&1); then | ||
| printf '%s' "$output" | ||
| return 0 | ||
| fi | ||
|
|
||
| rm -f "$bin" 2>/dev/null || true | ||
| if [ "$OS" = "linux" ] && printf '%s' "$output" | grep -q 'GLIBC_'; then | ||
| error "The autter binary could not run on this system (incompatible glibc). | ||
|
|
||
| $output | ||
|
|
||
| autter requires glibc ${MIN_GLIBC_MAJOR}.${MIN_GLIBC_MINOR} or newer (Ubuntu 22.04+). On Ubuntu 20.04 / older WSL2, switch to a newer distro or use Docker: | ||
| docker run -it --rm -v \"\$PWD\":/work -w /work ubuntu:22.04 bash" | ||
| fi | ||
| error "The autter binary could not run on this system: | ||
|
|
||
| $output" | ||
| } | ||
|
|
||
| check_git | ||
| check_linux_glibc | ||
|
|
||
| # Map OS to binary name | ||
| case $OS in | ||
| "darwin") | ||
|
|
@@ -459,11 +527,10 @@ | |
| warn "Failed to create ~/.local/bin/autter symlink. This is non-fatal." | ||
| fi | ||
|
|
||
| # Verify the binary runs before reporting success (catches glibc mismatches, etc.). | ||
| INSTALLED_VERSION=$(verify_binary_runs "${INSTALL_DIR}/autter") | ||
|
Check failure on line 531 in install.sh
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 [ai] Preserve the prior CLI when runtime validation fails — Risk: 88/100 The installer atomically replaces
🛠 AI fix prompt (copy & paste into your coding agent)Flagged by Autter security & observability checks. |
||
| success "Successfully installed autter into ${INSTALL_DIR}" | ||
| success "You can now run 'autter' from your terminal" | ||
|
|
||
| # Print installed version | ||
| INSTALLED_VERSION=$(${INSTALL_DIR}/autter --version 2>&1 || echo "unknown") | ||
| echo "Installed autter ${INSTALLED_VERSION}" | ||
|
|
||
| # Login user with install token if provided | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -101,6 +101,57 @@ | |
| } | ||
| } | ||
|
|
||
| function checkGit() { | ||
| try { | ||
| execFileSync('git', ['--version'], { encoding: 'utf8', timeout: 10_000, stdio: 'pipe' }); | ||
|
Check failure on line 106 in npm/install.js
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟠 [ai] Git prerequisite check does not enforce the minimum supported version — Risk: 74/100
🛠 AI fix prompt (copy & paste into your coding agent)Flagged by Autter security & observability checks. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟠 [ai] Make the npm Git preflight validate the minimum version — Risk: 72/100
🛠 AI fix prompt (copy & paste into your coding agent)Flagged by Autter security & observability checks. |
||
| } catch { | ||
| throw new Error( | ||
| 'git is required but not found. Install git 2.22 or newer, then re-run: npm install -g @autter/cli' | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| function checkLinuxGlibc() { | ||
| if (process.platform !== 'linux') return; | ||
| try { | ||
| const out = execFileSync('ldd', ['--version'], { encoding: 'utf8', timeout: 10_000 }); | ||
| const match = out.match(/(\d+)\.(\d+)/); | ||
| if (!match) return; | ||
| const major = Number(match[1]); | ||
| const minor = Number(match[2]); | ||
| if (major < 2 || (major === 2 && minor < 35)) { | ||
| throw new Error( | ||
| `Unsupported glibc version (${major}.${minor}). autter requires glibc 2.35+ (Ubuntu 22.04+, Debian 12+, Fedora 36+). ` + | ||
|
Check warning on line 124 in npm/install.js
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟠 [deterministic] Biome: lint/style/useTemplate — Risk: 55/100 Template literals are preferred over string concatenation. 🛠 AI fix prompt (copy & paste into your coding agent)Flagged by Autter security & observability checks. |
||
| 'On Ubuntu 20.04 / older WSL2, use a newer distro or run inside ubuntu:22.04 Docker.' | ||
| ); | ||
| } | ||
| } catch (err) { | ||
| if (err.message?.includes('Unsupported glibc')) throw err; | ||
| // ldd missing — rely on post-download binary verify | ||
| } | ||
| } | ||
|
|
||
| function verifyBinaryRuns(bin) { | ||
| try { | ||
| const out = execFileSync(bin, ['--version'], { encoding: 'utf8', timeout: 10_000 }); | ||
| return out.trim().split(/\s+/)[0] || null; | ||
| } catch (err) { | ||
| const detail = err.stderr?.toString() || err.stdout?.toString() || err.message || String(err); | ||
| try { | ||
| fs.rmSync(bin, { force: true }); | ||
| } catch { | ||
| // best effort | ||
| } | ||
| if (process.platform === 'linux' && detail.includes('GLIBC')) { | ||
| throw new Error( | ||
| `The autter binary could not run on this system (incompatible glibc).\n${detail}\n\n` + | ||
|
Check warning on line 147 in npm/install.js
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟠 [deterministic] Biome: lint/style/useTemplate — Risk: 55/100 Template literals are preferred over string concatenation. 🛠 AI fix prompt (copy & paste into your coding agent)Flagged by Autter security & observability checks. |
||
| 'autter requires glibc 2.35+ (Ubuntu 22.04+). On Ubuntu 20.04 / older WSL2, use a newer distro or Docker.' | ||
| ); | ||
| } | ||
| throw new Error(`The autter binary could not run on this system: ${detail}`); | ||
| } | ||
| } | ||
|
|
||
| // `autter --version` prints the bare version ("1.6.8", or "1.6.8 (debug)"). | ||
| function installedVersion(bin) { | ||
| try { | ||
|
|
@@ -188,6 +239,8 @@ | |
| } | ||
| } | ||
|
|
||
| verifyBinaryRuns(dest); | ||
|
Check failure on line 242 in npm/install.js
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 [ai] Do not delete the installed npm binary after a failed upgrade check — Risk: 86/100
🛠 AI fix prompt (copy & paste into your coding agent)Flagged by Autter security & observability checks. |
||
|
|
||
| await reportInstallPing(tag); | ||
| return { bin: dest, downloaded: true }; | ||
| } | ||
|
|
@@ -200,6 +253,14 @@ | |
| return; | ||
| } | ||
|
|
||
| try { | ||
| checkGit(); | ||
| checkLinuxGlibc(); | ||
| } catch (err) { | ||
| console.warn(`autter: ${err.message}`); | ||
| return; | ||
| } | ||
|
|
||
| let result; | ||
| try { | ||
| result = await ensureBinary(); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -486,8 +486,8 @@ | |
|
|
||
| let installers = get_all_installers(); | ||
| let mut installed_tools: HashSet<String> = HashSet::new(); | ||
| // Track agents whose hooks were updated (name, process_names) for restart warnings | ||
| let mut updated_agents: Vec<(String, Vec<String>)> = Vec::new(); | ||
| // Track agents whose hooks were checked (updated or already up to date) for restart warnings | ||
| let mut agents_for_restart: Vec<(String, Vec<String>)> = Vec::new(); | ||
| let mut not_detected: Vec<&str> = Vec::new(); | ||
|
|
||
| for installer in &installers { | ||
|
|
@@ -541,7 +541,7 @@ | |
| .map(|s| s.to_string()) | ||
| .collect(); | ||
| if !pnames.is_empty() { | ||
| updated_agents.push((name.to_string(), pnames)); | ||
| agents_for_restart.push((name.to_string(), pnames)); | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -552,6 +552,21 @@ | |
| statuses.insert(id.to_string(), InstallStatus::AlreadyInstalled); | ||
| detailed_results | ||
| .push((id.to_string(), InstallResult::already_installed())); | ||
|
|
||
| // Hooks may be up to date on disk but the agent still needs a | ||
|
Check warning on line 556 in src/commands/install_hooks.rs
|
||
| // restart to load them — track for the restart warning below. | ||
| if !options.dry_run { | ||
| let pnames: Vec<String> = installer | ||
| .process_names() | ||
| .iter() | ||
| .map(|s| s.to_string()) | ||
| .collect(); | ||
| if !pnames.is_empty() | ||
| && !agents_for_restart.iter().any(|(n, _)| n == name) | ||
| { | ||
| agents_for_restart.push((name.to_string(), pnames)); | ||
| } | ||
| } | ||
| } | ||
| Err(e) => { | ||
| let error_msg = e.to_string(); | ||
|
|
@@ -614,15 +629,15 @@ | |
| // Track restart detection for extras-only agents (e.g. JetBrains, VS Code) | ||
| if extras_changed | ||
| && !options.dry_run | ||
| && !updated_agents.iter().any(|(n, _)| n == name) | ||
| && !agents_for_restart.iter().any(|(n, _)| n == name) | ||
| { | ||
| let pnames: Vec<String> = installer | ||
| .process_names() | ||
| .iter() | ||
| .map(|s| s.to_string()) | ||
| .collect(); | ||
| if !pnames.is_empty() { | ||
| updated_agents.push((name.to_string(), pnames)); | ||
| agents_for_restart.push((name.to_string(), pnames)); | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -683,11 +698,12 @@ | |
| println!("{}", paint("1", " autter install-hooks --dry-run=false")); | ||
| } | ||
|
|
||
| // Check for running agents that had hooks updated and warn about restart | ||
| if !options.dry_run && !updated_agents.is_empty() { | ||
| // Warn when agents that use hooks are running — they must be restarted for | ||
| // attribution to take effect, including when hooks were already up to date. | ||
| if !options.dry_run && !agents_for_restart.is_empty() { | ||
| let mut any_running = false; | ||
|
|
||
| for (agent_name, pnames) in &updated_agents { | ||
| for (agent_name, pnames) in &agents_for_restart { | ||
| let refs: Vec<&str> = pnames.iter().map(|s| s.as_str()).collect(); | ||
| let pids = find_running_pids(&refs); | ||
| if !pids.is_empty() { | ||
|
|
@@ -726,7 +742,16 @@ | |
| "This is expected — once you commit and start a fresh session, attribution will work correctly." | ||
| ); | ||
| println!( | ||
| "If the issue persists, please open an issue at https://github.com/autter-dev/autter-cli/issues" | ||
| "If the issue persists, run 'autter doctor' (or 'autter debug' on older versions)." | ||
| ); | ||
| } else if !agents_for_restart.is_empty() { | ||
| println!(); | ||
| println!( | ||
| "{}", | ||
| paint( | ||
| "33", | ||
| "If any coding agent was open during hook setup, restart it now for AI attribution to take effect." | ||
| ) | ||
| ); | ||
| } | ||
| } | ||
|
|
@@ -772,7 +797,19 @@ | |
| let text = String::from_utf8_lossy(&o.stdout).into_owned(); | ||
| parse_git_version(&text) | ||
| } | ||
| Err(_) => None, | ||
| Err(_) => { | ||
| eprintln!(); | ||
| eprintln!( | ||
| "{}", | ||
| paint_err( | ||
| "1;31", | ||
| "WARNING: git not found — autter requires git to function." | ||
| ) | ||
| ); | ||
| eprintln!("Install git 2.22+ and re-run: autter install-hooks"); | ||
| eprintln!(); | ||
| return; | ||
| } | ||
| }; | ||
|
|
||
| if let Some(v) = version { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟡 [deterministic] markdownlint: MD013 — Risk: 30/100
Line length: Expected: 80; Actual: 210
🛠 AI fix prompt (copy & paste into your coding agent)
Flagged by Autter security & observability checks.