{"id":51599145,"url":"https://github.com/liamg/grabber","last_synced_at":"2026-07-11T20:32:29.736Z","repository":{"id":368794137,"uuid":"1154811097","full_name":"liamg/grabber","owner":"liamg","description":"Downloads files/directories from various URL-like inputs. Alternative to go-getter. Supports OCI.","archived":false,"fork":false,"pushed_at":"2026-07-02T08:21:43.000Z","size":127,"stargazers_count":6,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-02T09:16:10.328Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/liamg.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["liamg"]}},"created_at":"2026-02-10T19:59:34.000Z","updated_at":"2026-07-02T08:21:47.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/liamg/grabber","commit_stats":null,"previous_names":["liamg/grabber"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/liamg/grabber","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/liamg%2Fgrabber","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/liamg%2Fgrabber/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/liamg%2Fgrabber/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/liamg%2Fgrabber/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/liamg","download_url":"https://codeload.github.com/liamg/grabber/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/liamg%2Fgrabber/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35375153,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-11T02:00:05.354Z","response_time":104,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-11T20:32:28.842Z","updated_at":"2026-07-11T20:32:29.714Z","avatar_url":"https://github.com/liamg.png","language":"Go","funding_links":["https://github.com/sponsors/liamg"],"categories":[],"sub_categories":[],"readme":"# grabber\n\nA Go library for downloading files and directories from various sources using a URL string as input.\n\nGrabber is an alternative to [go-getter](https://github.com/hashicorp/go-getter) with a cleaner API and active development.\n\n## Why grabber?\n\n| | grabber | go-getter |\n|---|---|---|\n| Sparse checkout | ✅ | ❌ |\n| Programmatic credential injection | ✅ | ❌ (env vars / URL params only) |\n| HTTPS credential matching | ✅ (git-style host/path matching) | ❌ |\n| Git credential helper support | ✅ (via system `git`) | ✅ (shells out to `git`) |\n| SSH-to-HTTPS auto-transform | ✅ | ❌ |\n| OCI registry support | ✅ | ❌ |\n| Checksum verification | ✅ (URL param or explicit API) | ✅ (URL param only) |\n| Pure Go | ✅ (`git` required only if using credential helpers; `hg` required for Mercurial) | ❌ (shells out to git, hg, etc.) |\n| Zstandard / LZ4 archives | ✅ | ❌ |\n| Actively maintained | ✅ | ❌ [Maintenance-only](https://github.com/hashicorp/go-getter/graphs/commit-activity) |\n\n## Features\n\n- Download files and directories from Git, Mercurial, S3, GCS, OCI, HTTP, and local filesystems\n- **Sparse checkout** — only fetch the subdirectory you need from a Git repo\n- **Programmatic credential injection** — pass SSH keys, AWS credentials, GCP service account keys, OCI registry credentials, and HTTPS credentials via the Go API\n- **HTTPS credential matching** — configure HTTPS credentials with git-style host/path matching, used automatically for Git and HTTP protocols\n- **SSH-to-HTTPS auto-transform** — automatically convert SSH/SCP Git URLs to HTTPS (useful in CI environments without SSH key access)\n- **Custom TLS and proxying** — trust extra CAs, present mutual-TLS client certificates (per host), and route through HTTP proxies (global or per host) for the HTTP, OCI, and Git protocols — all via functional options, no environment variables\n- **SSRF protection** — outbound fetches are guarded against reaching loopback, link-local (cloud metadata), and private addresses by default; configurable and opt-out via `WithSSRFProtection`\n- **Pure Go** — no system `git` or other CLI tools required (except `hg` for Mercurial; system `git` is used for credential helper support if available)\n- **Checksum verification** — verify downloaded file integrity via URL query param (`?checksum=sha256:abc...`) or the explicit `GrabWithSHA256Checksum()` API\n- **Automatic archive extraction** — downloaded archives are detected and extracted by extension\n- **Subdirectory support** — use `//` in URLs to extract a subdirectory (e.g. `github.com/user/repo//sub/dir`)\n- **Protocol auto-detection** — URLs are automatically routed to the right protocol based on hostname, scheme, and path\n- **Extensible** — bring your own protocol implementations via `WithProtocols()`\n\n## Supported Protocols\n\n| Protocol | Prefix | Status | Description |\n|----------|--------|--------|-------------|\n| Git | `git::` | Implemented | Clone Git repos over HTTPS, SSH, or git:// |\n| Mercurial | `hg::` | Implemented | Clone Mercurial repos (requires `hg` CLI) |\n| S3 | `s3::` | Implemented | Download files/directories from Amazon S3 |\n| GCS | `gcs::` | Implemented | Download files/directories from Google Cloud Storage |\n| OCI | `oci::` | Implemented | Pull artifacts from OCI-compatible registries |\n| HTTP/HTTPS | `http::` | Implemented | Plain file downloads over HTTP/HTTPS |\n| File | `file::` | Implemented | Copy from local filesystem paths |\n\nProtocols are auto-detected from the URL.\n\n### Git\n\n**Supported URL formats:**\n\n| Format | Example |\n|--------|---------|\n| HTTPS | `https://github.com/user/repo.git` |\n| SSH | `ssh://git@github.com/user/repo.git` |\n| SCP-style | `git@github.com:user/repo.git` |\n| git:// | `git://github.com/user/repo.git` |\n\n**Auto-detected when:**\n- URL has `.git` suffix\n- URL uses `ssh://` or `git://` scheme\n- URL is SCP-style (`git@host:user/repo`)\n- Host is a known Git provider: `github.com`, `gitlab.com`, `bitbucket.org`, `codeberg.org`, `dev.azure.com`, `sr.ht`\n\n**Query parameters:**\n- `ref` - branch, tag, or commit SHA to check out\n- `depth` - shallow clone depth (e.g. `?depth=1`)\n\n**Subdirectory support:**\nUse `//` to specify a subdirectory: `github.com/user/repo//modules/vpc?ref=v1.0.0`\n\nWhen sparse checkout is enabled, only the specified subdirectory is checked out. Otherwise the full repo is cloned and the subdirectory is extracted.\n\n**Scheme fallback:**\nA clone is first attempted with the URL as given. On failure grabber falls back to the other scheme: an SSH/SCP URL falls back to its HTTPS equivalent, and an HTTPS/HTTP URL falls back to SSH when an SSH key is configured for the host (Azure DevOps SSH URLs are handled specially). `WithGitSSHToHTTPS()` forces the HTTPS form up front instead. Setting `WithConnectProbeTimeout(d)` makes an unreachable primary fail fast so the fallback is tried promptly rather than after a clone timeout.\n\n**Orphaned commit fallback:**\nWhen `ref` is a commit SHA that the git protocol can't reach (e.g. an orphaned commit that is no longer reachable from any branch or tag), grabber falls back to downloading a tarball of that commit from the hosting platform's HTTP API. GitHub, GitLab, and Bitbucket are supported. Credentials are resolved from the same sources as clones (URL userinfo, configured HTTPS credentials, the git credential helper) and, failing those, from well-known API token environment variables: `GH_TOKEN`/`GITHUB_TOKEN`, `GITLAB_TOKEN`/`GL_TOKEN`, and `BITBUCKET_TOKEN` (unless `WithNoSystemFallback()` is set, which disables the environment-variable lookup). The result is a plain source snapshot with no `.git` directory. SSH keys cannot be used for this HTTP fallback, so SSH-only setups need HTTP credentials configured for private repositories.\n\n### Mercurial\n\n\u003e **Note:** Mercurial support requires the `hg` CLI to be installed on the system.\n\n**Supported URL formats:**\n\n| Format | Example |\n|--------|---------|\n| HTTPS | `https://bitbucket.org/user/repo` |\n\n**Auto-detected when:**\n- Host is a known Mercurial provider: `bitbucket.org`\n\nSince Bitbucket also hosts Git repos (and Git has higher priority), use the `hg::` prefix to force Mercurial: `hg::https://bitbucket.org/user/repo`\n\n**Query parameters:**\n- `rev` — revision, tag, or branch to check out (e.g. `?rev=v1.0.0`)\n\n**Subdirectory support:**\nUse `//` to specify a subdirectory: `hg::bitbucket.org/user/repo//lib/core?rev=stable`\n\n### S3\n\n**Supported URL formats:**\n\n| Format | Example |\n|--------|---------|\n| s3:// scheme | `s3://bucket/key` |\n| Path-style | `s3.amazonaws.com/bucket/key` |\n| Path-style regional | `s3.us-west-2.amazonaws.com/bucket/key` |\n| Virtual-hosted | `bucket.s3.amazonaws.com/key` |\n| Virtual-hosted regional | `bucket.s3.us-west-2.amazonaws.com/key` |\n\n**Auto-detected when** (no `s3::` prefix needed):\n- URL uses `s3://` scheme\n- Hostname contains `s3` and `amazonaws.com`\n\nKeys ending in `/` are treated as directory prefixes - all objects under that prefix are downloaded.\n\n### GCS\n\n**Supported URL formats:**\n\n| Format | Example |\n|--------|---------|\n| Path-style googleapis | `storage.googleapis.com/bucket/key` |\n| Path-style cloud.google.com | `storage.cloud.google.com/bucket/key` |\n| Virtual-hosted | `bucket.storage.googleapis.com/key` |\n\n**Auto-detected when:**\n- Hostname is `storage.googleapis.com` or `storage.cloud.google.com`\n- Hostname ends with `.storage.googleapis.com`\n\nKeys ending in `/` are treated as directory prefixes - all objects under that prefix are downloaded.\n\n### OCI\n\n**Supported URL formats:**\n\n| Format | Example |\n|--------|---------|\n| With tag | `oci://ghcr.io/user/repo:v1.0.0` |\n| With digest | `oci://ghcr.io/user/repo@sha256:abc123...` |\n| Latest (default) | `oci://ghcr.io/user/repo` |\n\n**Auto-detected when:**\n- URL uses `oci://` scheme\n\n### HTTP/HTTPS\n\n**Supported URL formats:**\n\n| Format | Example |\n|--------|---------|\n| HTTPS | `https://example.com/path/to/file.tar.gz` |\n| HTTP | `http://example.com/path/to/file.tar.gz` |\n| No scheme (defaults to HTTPS) | `example.com/path/to/file.tar.gz` |\n\n**Auto-detected when:**\n- URL uses `http://` or `https://` scheme\n- URL has no scheme (defaults to HTTPS)\n\nHTTP is the lowest-priority protocol, so it acts as a fallback when no other protocol matches.\n\n### File\n\n**Supported URL formats:**\n\n| Format | Example |\n|--------|---------|\n| file:// scheme | `file:///path/to/source` |\n| Absolute path | `/path/to/source` |\n| Relative path | `./relative/path` |\n\n**Auto-detected when:**\n- URL uses `file://` scheme\n- URL is an absolute filesystem path\n- URL starts with `./` or `../`\n\nIf the source is a directory, all contents are copied recursively. If it's a file, it's copied as a single file (and may be auto-extracted if it's an archive).\n\n## Options\n\nOptions are passed to `grabber.New()`:\n\n```go\ng := grabber.New(\n    grabber.WithGitSSHKey(privateKey),\n    grabber.WithAWSCredentials(keyID, secret, token, region),\n)\n```\n\n| Option | Description |\n|--------|-------------|\n| `WithSparseCheckout(bool)` | Enable sparse checkout for Git subdirectories (default: `false`) |\n| `WithAutoExtract(bool)` | Enable automatic archive extraction (default: `true`) |\n| `WithGitSSHKey([]byte)` | Default SSH private key for Git authentication |\n| `WithGitSSHKeyForHost(host, []byte)` | SSH private key scoped to a specific host (takes precedence over the default) |\n| `WithGitDepth(int)` | Override shallow clone depth for Git (default: 1; 0 = full clone) |\n| `WithGitInsecureSkipHostKeyVerify()` | Skip SSH host key verification |\n| `WithGitKnownHosts([]byte)` | Verify SSH host keys against known_hosts data in memory (allows unknown hosts, rejects changed keys) |\n| `WithNoSystemFallback()` | Disable all ambient/system fallbacks (SSH agent, `git credential` helper, archive env-var tokens, `~/.ssh/known_hosts`, and the `hg` subprocess) |\n| `WithAWSCredentials(keyID, secret, token, region)` | Static AWS credentials for S3 |\n| `WithGCPCredentials(serviceAccountKey)` | GCP service account key for GCS |\n| `WithOCICredentials(username, password)` | Default registry credentials for OCI |\n| `WithOCICredentialForRegistry(registry, username, password)` | OCI credentials scoped to a specific registry (takes precedence over the default) |\n| `WithOCIPlainHTTP()` | Use HTTP instead of HTTPS for OCI registries |\n| `WithHTTPSCredential(host, user, pass)` | Add an HTTPS credential matched by host |\n| `WithHTTPSCredentialForPath(host, path, user, pass)` | Add an HTTPS credential matched by host and path prefix |\n| `WithHTTPCredentialRequestFunction(f)` | Resolve credentials dynamically (HTTP/Git/OCI) when no static credential matches — an in-memory replacement for an on-disk git credential helper |\n| `WithGitSSHToHTTPS()` | Force SSH/SCP Git URLs to HTTPS before cloning (no SSH attempt) |\n| `WithConnectProbeTimeout(d)` | Fast-fail (and trigger the Git ssh↔https fallback) with a short TCP connect probe before a download/clone |\n| `WithTLSCACert(pem)` | Trust an additional CA for HTTPS connections (HTTP, OCI, and Git protocols); repeatable |\n| `WithClientCertificate(certPEM, keyPEM)` | Default TLS client certificate for mutual TLS |\n| `WithClientCertificateForHost(host, certPEM, keyPEM)` | TLS client certificate scoped to a specific host (takes precedence over the default) |\n| `WithHTTPProxy(url, user, pass)` | Global HTTP proxy for HTTP, OCI, and Git (HTTPS) requests |\n| `WithHTTPProxyForHost(host, url, user, pass)` | HTTP proxy scoped to a specific host (preferred over the global proxy when it matches) |\n| `WithHTTPTransport(*http.Transport)` | Base transport for the HTTP/OCI protocols (e.g. with an SSRF-guarded dialer); cloned per download with the TLS/proxy options layered on top |\n| `WithSSRFProtection(ssrf.Level)` | SSRF guard level: `None`, `Loopback`, or `Internal` (default) |\n| `WithCustomSSRFProtection(func(net.IP) bool)` | Guard outbound connections with a custom \"is this IP blocked?\" predicate |\n| `WithSSRFAllowHosts(hosts...)` | Allowlist hosts/IPs/CIDRs that bypass the SSRF guard |\n| `WithProtocols(...Protocol)` | Override the default set of protocols |\n\nWhen AWS/GCP credentials are not provided, the respective SDK default credential chains are used (env vars, shared config, IAM roles, etc.).\n\nGit clones default to `depth=1` (shallow) for performance, since go-git is slower than system `git` for full clones and full history is rarely needed. Commit hash refs (`?ref=abc1234`) automatically use a full clone so the commit is reachable. URL query parameters (`?depth=1`) override all defaults.\n\n### SSRF Protection\n\nWhen grabber fetches a URL that an untrusted party controls (for example a\nTerraform module `source` in a CI run), the SSRF guard prevents it from reaching\naddresses that are only meant to be reachable internally. It is **on by default**\nat the `Internal` level — blocking loopback, RFC1918 private ranges, IPv6 ULA,\nlink-local (including the `169.254.169.254` cloud metadata endpoint), and\nmulticast.\n\nLevels (`WithSSRFProtection(level)`):\n\n| Level | Blocks |\n|-------|--------|\n| `ssrf.None` | nothing (opt out) |\n| `ssrf.Loopback` | loopback and the unspecified address |\n| `ssrf.Internal` (default) | loopback + private + link-local + ULA + multicast |\n\nSpecific hosts can be allowlisted with `WithSSRFAllowHosts(...)`, which accepts\nhostnames (matched case-insensitively), IP literals, and CIDR ranges; matching\ntargets bypass the guard entirely. Use `WithCustomSSRFProtection(func(net.IP) bool)`\nfor a bespoke policy. The guard\nworks at two layers: a dialer check on the HTTP/OCI transports (which catches DNS\nrebinding and redirect-to-internal, since each dial is re-checked on the resolved\nIP), and a pre-fetch host check for Git and Mercurial (which use their own\ntransports). s3/gcs only ever connect to fixed cloud endpoints, so they are not\nguarded. A configured proxy is exempt (the connection goes to the trusted proxy,\nnot the target).\n\n\u003e **Note:** the default blocks `127.0.0.1`/`localhost`, so tests or tools that\n\u003e fetch from a local server must pass `WithSSRFProtection(ssrf.None)`.\n\n### HTTPS Credential Matching\n\nHTTPS credentials are matched using git-style semantics: host must match (case-insensitive), and if a path is specified it must be a prefix of the URL path. The most specific match (longest path prefix) wins.\n\nCredentials for HTTP, Git-over-HTTPS, and OCI are resolved in this order: credentials embedded in the URL → a matching static credential (`WithHTTPSCredential`/`WithOCICredentials`) → the dynamic function from `WithHTTPCredentialRequestFunction` (consulted only when nothing static matches) → the system git credential helper (unless disabled via `WithNoSystemFallback`). The dynamic function receives the protocol, host, and path and returns a username/password (either may be nil) plus a boolean; returning `false` defers to the next source.\n\n```go\ng := grabber.New(\n    // Matches any URL on github.com\n    grabber.WithHTTPSCredential(\"github.com\", \"user\", \"token\"),\n\n    // Matches only URLs under github.com/my-org/... (takes priority over the above)\n    grabber.WithHTTPSCredentialForPath(\"github.com\", \"/my-org\", \"org-user\", \"org-token\"),\n)\n```\n\nCredentials are applied automatically to both Git (HTTPS clones) and HTTP downloads. For Git, HTTPS credentials are checked after embedded URL credentials but before system `git credential fill`.\n\n### SSH-to-HTTPS Auto-Transform\n\nWhen `WithGitSSHToHTTPS()` is enabled, SSH and SCP-style Git URLs are automatically converted to HTTPS before cloning:\n\n- `git@github.com:user/repo.git` → `https://github.com/user/repo.git`\n- `ssh://git@github.com/user/repo.git` → `https://github.com/user/repo.git`\n\nThis is useful in CI environments where SSH keys are not available but HTTPS tokens are configured via `WithHTTPSCredential()`.\n\n## Archive Extraction\n\nWhen `WithAutoExtract()` is enabled (the default), downloaded files are automatically detected and extracted by extension:\n\n| Format | Extensions |\n|--------|------------|\n| Tar | `.tar` |\n| Tar + Gzip | `.tar.gz`, `.tgz` |\n| Tar + Bzip2 | `.tar.bz2`, `.tbz2` |\n| Tar + XZ | `.tar.xz`, `.txz` |\n| Tar + Zstandard | `.tar.zst`, `.tzst` |\n| Tar + LZ4 | `.tar.lz4` |\n| Zip | `.zip` |\n| Gzip | `.gz` |\n| Bzip2 | `.bz2` |\n| XZ | `.xz` |\n| Zstandard | `.zst` |\n| LZ4 | `.lz4` |\n\n## Checksum Verification\n\nDownloaded files can be verified against an expected checksum. This works for single-file downloads only (not directories).\n\n**Via URL query parameter:**\n\n```go\n// With explicit algorithm\nerr := g.Grab(ctx, \"https://example.com/file.tar.gz?checksum=sha256:e3b0c44...\", \"./output\")\n\n// Without algorithm prefix — defaults to SHA-256\nerr := g.Grab(ctx, \"https://example.com/file.tar.gz?checksum=e3b0c44...\", \"./output\")\n```\n\n**Via explicit API (recommended):**\n\n```go\nerr := g.GrabWithSHA256Checksum(ctx, \"https://example.com/file.tar.gz\", \"./output\", \"e3b0c44...\")\n```\n\nWhen both a URL parameter and an explicit checksum are provided, the explicit one takes precedence.\n\nThe URL parameter supports other algorithms via the `algo:hex` format (e.g. `?checksum=sha512:cf83e13...`). Supported algorithms: `md5`, `sha1`, `sha256`, `sha512`.\n\nChecksum verification runs on the raw downloaded file, before archive extraction.\n\n## Usage\n\n```go\npackage main\n\nimport (\n    \"context\"\n    \"log\"\n\n    \"github.com/liamg/grabber\"\n)\n\nfunc main() {\n    g := grabber.New(\n        grabber.WithGitSSHKey(privateKeyBytes),\n    )\n\n    // Clone a Git repo subdirectory\n    err := g.Grab(context.Background(), \"github.com/user/repo//modules/vpc?ref=v1.0.0\", \"./vpc\")\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    // Download from S3\n    err = g.Grab(context.Background(), \"s3.amazonaws.com/my-bucket/config.tar.gz\", \"./config\")\n    if err != nil {\n        log.Fatal(err)\n    }\n}\n```\n\n## CLI\n\nA CLI tool is included for testing and quick downloads:\n\n```bash\ngo install github.com/liamg/grabber/cmd/grabber@latest\n```\n\n```bash\n# Download a file\ngrabber https://example.com/file.tar.gz ./output\n\n# Clone a Git repo subdirectory\ngrabber github.com/user/repo//modules/vpc ./vpc\n\n# Download with checksum verification\ngrabber -c e3b0c44298fc1c14... https://example.com/file.tar.gz ./output\n\n# Copy a local file\ngrabber ./path/to/source ./destination\n\n# Print version information\ngrabber --version\n```\n\nRun `grabber --help` for all available flags.\n\nRelease binaries are built with version metadata embedded via `-ldflags`, so\n`grabber --version` on a released binary reports the tag, commit, and build\ndate. `go install` builds report `dev`.\n\n## Installation\n\n**Library:**\n\n```\ngo get github.com/liamg/grabber\n```\n\n**CLI:**\n\n```\ngo install github.com/liamg/grabber/cmd/grabber@latest\n```\n\n## Status\n\nEarly development. API is not yet stable.\n\n## Known Limitations\n\n- **Git credential helpers require system `git`** — go-git doesn't support `credential.helper` from `~/.gitconfig`, so grabber shells out to `git credential fill` when `git` is on `PATH`. Without system `git`, credential helpers won't work — use `WithGitSSHKey()`, `WithHTTPSCredential()`, or embed credentials in the URL instead. This shell-out (like the SSH agent and known_hosts defaults) is a system fallback and can be turned off entirely with `WithNoSystemFallback()`.\n\n## License\n\n[Unlicense](./LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fliamg%2Fgrabber","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fliamg%2Fgrabber","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fliamg%2Fgrabber/lists"}