> ## Documentation Index
> Fetch the complete documentation index at: https://docs.unhook.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Cross-Platform CLI Setup

> Implementation guide for cross-platform CLI binary distribution and installation

## Overview

The `@unhook/cli` package has been enhanced to work seamlessly across all major platforms (macOS, Windows, Linux, ARM/x64) using a hybrid approach that downloads platform-specific binaries during installation.

## Architecture

### Build System

* **GitHub Actions**: Builds binaries for all supported platforms
* **Release Assets**: Uploads binaries to GitHub releases with standardized naming
* **Platforms Supported**:
  * `linux-x64` (glibc)
  * `linux-arm64` (glibc)
  * `linux-x64-musl` (Alpine Linux)
  * `linux-arm64-musl` (Alpine Linux ARM64)
  * `darwin-x64` (macOS Intel)
  * `darwin-arm64` (macOS Apple Silicon)
  * `win32-x64` (Windows 64-bit)

### Installation Flow

<Steps>
  <Step title="Package Installation">
    User runs `npm install @unhook/cli`
  </Step>

  <Step title="Postinstall Hook">
    `scripts/install.cjs` executes automatically
  </Step>

  <Step title="Platform Detection">
    Detects OS, architecture, and libc variant (musl vs glibc)
  </Step>

  <Step title="Binary Download">
    Downloads appropriate binary from GitHub releases
  </Step>

  <Step title="Installation">
    Stores binary in `~/.unhook/bin/{version}/` with proper permissions
  </Step>
</Steps>

### Runtime Flow

<Steps>
  <Step title="Command Execution">
    User runs `unhook [command]`
  </Step>

  <Step title="Wrapper Execution">
    `bin/cli.cjs` wrapper script executes
  </Step>

  <Step title="Binary Location">
    Wrapper detects platform and locates downloaded binary
  </Step>

  <Step title="Transparent Execution">
    Spawns platform-specific binary with user arguments
  </Step>

  <Step title="Result Return">
    Returns binary exit code transparently to user
  </Step>
</Steps>

## File Structure

```
apps/cli/
├── bin/
│   └── cli.cjs                 # CommonJS CLI wrapper
├── scripts/
│   └── install.cjs             # Installation script
├── tests/
│   └── integration/
│       └── cross-platform.test.ts  # Integration tests
├── package.json                # Updated configuration
└── README.md                   # User documentation
```

## Implementation Details

### Platform Detection

The CLI intelligently detects the target platform and architecture:

```javascript theme={null}
const platformMap = { win32: 'win32', darwin: 'darwin', linux: 'linux' };
const archMap = { x64: 'x64', arm64: 'arm64' };

// Linux-specific: Detect musl vs glibc
if (platform === 'linux') {
  if (fs.existsSync('/lib/ld-musl-x86_64.so.1') || 
      fs.existsSync('/lib/ld-musl-aarch64.so.1')) {
    targetArch = `${arch}-musl`;
  }
}
```

### Binary Naming Convention

Binaries follow this pattern: `unhook-{platform}-{arch}[.exe]`

<CardGroup cols={2}>
  <Card title="macOS Examples">
    * `unhook-darwin-arm64` (Apple Silicon)
    * `unhook-darwin-x64` (Intel)
  </Card>

  <Card title="Linux Examples">
    * `unhook-linux-x64` (glibc)
    * `unhook-linux-x64-musl` (Alpine)
    * `unhook-linux-arm64` (ARM64 glibc)
    * `unhook-linux-arm64-musl` (ARM64 Alpine)
  </Card>

  <Card title="Windows Examples">
    * `unhook-win32-x64.exe` (64-bit)
  </Card>
</CardGroup>

### Version Management

* Binaries are stored in versioned directories: `~/.unhook/bin/{version}/`
* Old versions are automatically cleaned up during installation
* Multiple versions can coexist temporarily during upgrades

## Edge Cases & Robustness

### Network Issues

<AccordionGroup>
  <Accordion title="Corporate Firewalls">
    **Problem**: Users behind corporate firewalls or with poor connectivity

    **Solution**:

    * Respect `HTTP_PROXY`, `HTTPS_PROXY` environment variables
    * 30-second timeout with clear error messages
    * Graceful fallback with manual install instructions

    ```javascript theme={null}
    request.setTimeout(30000, () => {
      console.error('❌ Download timeout: The download took too long. Please try again.');
      process.exit(1);
    });
    ```
  </Accordion>

  <Accordion title="Permission Issues">
    **Problem**: Users without write permissions to home directory

    **Solution**:

    * Clear error messages with specific instructions
    * Platform-specific guidance (sudo on Linux/macOS, admin on Windows)
    * Alternative installation paths suggested
  </Accordion>
</AccordionGroup>

### Platform-Specific Handling

<Tabs>
  <Tab title="macOS">
    **Security (Gatekeeper)**:

    ```javascript theme={null}
    // Remove quarantine attribute
    execSync(`xattr -d com.apple.quarantine "${binPath}"`, { stdio: 'ignore' });
    ```

    **Code Signing**: macOS binaries are signed and notarized during CI
  </Tab>

  <Tab title="Linux">
    **Libc Detection**:

    ```javascript theme={null}
    // Detect musl by checking for loader
    if (fs.existsSync('/lib/ld-musl-x86_64.so.1')) {
      targetArch = `${arch}-musl`;
    }
    ```

    **Variants**: Support both glibc and musl variants for Alpine Linux compatibility
  </Tab>

  <Tab title="Windows">
    **Executable Extensions**:

    ```javascript theme={null}
    const ext = os.platform() === 'win32' ? '.exe' : '';
    ```

    **Permission Handling**: Windows-specific permission management
  </Tab>
</Tabs>

### CI/CD Environments

**Problem**: CI systems shouldn't download binaries during installation

**Solution**:

```javascript theme={null}
// Skip installation in CI
if (require('is-ci')) {
  process.exit(0);
}
```

## Testing Strategy

### Integration Tests

Comprehensive test suite covering:

1. **Platform Detection**: Verify correct platform/arch identification
2. **URL Construction**: Ensure proper download URLs
3. **Error Handling**: Test failure scenarios
4. **Package Configuration**: Validate package.json settings
5. **Platform-Specific Behavior**: Test OS-specific features

### Test Execution

```bash theme={null}
# Run all integration tests
bun test tests/integration/cross-platform.test.ts

# Run with coverage
bun test --coverage tests/integration/
```

## Troubleshooting

<AccordionGroup>
  <Accordion title="&#x22;Binary not found&#x22; errors">
    ```bash theme={null}
    # Force reinstall
    npm install @unhook/cli --force

    # Manual install
    node ./node_modules/@unhook/cli/scripts/install.cjs
    ```
  </Accordion>

  <Accordion title="Permission denied on Linux/macOS">
    ```bash theme={null}
    chmod +x ~/.unhook/bin/*/unhook-*
    ```
  </Accordion>

  <Accordion title="macOS security warnings">
    ```bash theme={null}
    xattr -d com.apple.quarantine ~/.unhook/bin/*/unhook-darwin-*
    ```
  </Accordion>

  <Accordion title="Corporate proxy issues">
    ```bash theme={null}
    export HTTP_PROXY=http://proxy.company.com:8080
    export HTTPS_PROXY=http://proxy.company.com:8080
    npm install @unhook/cli
    ```
  </Accordion>
</AccordionGroup>

## Performance Considerations

<CardGroup cols={2}>
  <Card title="One-time Download" icon="download">
    Binaries are cached locally after first install
  </Card>

  <Card title="Version Management" icon="clock-rotate-left">
    Only current version kept, old versions cleaned up
  </Card>

  <Card title="Efficient Detection" icon="gauge-high">
    Fast platform/arch detection using Node.js APIs
  </Card>

  <Card title="Minimal Overhead" icon="timer">
    CLI wrapper adds \~10ms startup time
  </Card>
</CardGroup>

## Security Considerations

<Warning>
  All security measures are implemented to ensure safe binary distribution:
</Warning>

* **Verified Downloads**: Binaries downloaded from official GitHub releases only
* **Code Signing**: macOS binaries are signed and notarized
* **No Build Tools Required**: Users don't need compilers or build chains
* **Quarantine Removal**: Automatic handling of macOS security restrictions

## Future Enhancements

1. **Checksum Verification**: Verify binary integrity using SHA checksums
2. **Delta Updates**: Only download changed parts of binaries
3. **Mirror Support**: Allow alternative download sources
4. **Offline Mode**: Bundle common binaries with the package
5. **Auto-updates**: Automatic binary updates when package is updated

## Contributing

When adding support for new platforms:

<Steps>
  <Step title="Update CI">
    Update the GitHub Actions workflow (`.github/workflows/cli-github-release.yml`)
  </Step>

  <Step title="Add Platform Mapping">
    Add platform mapping in both `install.cjs` and `cli.cjs`
  </Step>

  <Step title="Update Documentation">
    Update documentation and tests
  </Step>

  <Step title="Test on Platform">
    Test on the target platform before releasing
  </Step>
</Steps>

## References

* [GitHub Releases API](https://docs.github.com/en/rest/releases)
* [Node.js os module](https://nodejs.org/api/os.html)
* [npm postinstall hooks](https://docs.npmjs.com/cli/v7/using-npm/scripts)
* [Bun build targets](https://bun.sh/docs/bundler)
