{"id":51461990,"url":"https://github.com/alecgard/share-file","last_synced_at":"2026-07-06T06:31:11.334Z","repository":{"id":356750548,"uuid":"1233843766","full_name":"alecgard/share-file","owner":"alecgard","description":"Publish files to a shareable URL backed by a GitHub gist.","archived":false,"fork":false,"pushed_at":"2026-05-09T16:27:27.000Z","size":63,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-09T16:36:02.207Z","etag":null,"topics":["ai-tools","file-sharing","github-gists"],"latest_commit_sha":null,"homepage":"","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alecgard.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2026-05-09T12:34:45.000Z","updated_at":"2026-05-09T16:27:05.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/alecgard/share-file","commit_stats":null,"previous_names":["alecgard/share-file"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/alecgard/share-file","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alecgard%2Fshare-file","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alecgard%2Fshare-file/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alecgard%2Fshare-file/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alecgard%2Fshare-file/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alecgard","download_url":"https://codeload.github.com/alecgard/share-file/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alecgard%2Fshare-file/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35180933,"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-06T02:00:07.184Z","response_time":106,"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":["ai-tools","file-sharing","github-gists"],"created_at":"2026-07-06T06:31:10.583Z","updated_at":"2026-07-06T06:31:11.322Z","avatar_url":"https://github.com/alecgard.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# share-file\n\nPublish any single file — HTML page, image, PDF, screenshot, dashboard, audio\nclip, video, source file, generated report — to a shareable URL backed by a\nsecret GitHub gist. Anyone with the link can view it through a static viewer\nhosted on GitHub Pages.\n\n- Uses your existing GitHub auth via the `gh` CLI.\n- Single bash script, no build step.\n- Works from a terminal or as a tool an agent can call.\n- Updates reuse the same URL.\n\n## Install\n\n```bash\nmkdir -p ~/.local/bin \u0026\u0026 \\\n  curl -fsSL https://raw.githubusercontent.com/alecgard/share-file/main/bin/share-file \\\n    -o ~/.local/bin/share-file \u0026\u0026 \\\n  chmod +x ~/.local/bin/share-file\n```\n\n## Share a file\n\n```bash\n$ share-file dashboard.html\nSource:   https://gist.github.com/\u003cyou\u003e/abc123\nRendered: https://alecgard.github.io/share-file/?abc123#k=Woa-2A8tTA-P3KfHS6ohUA\n(copied to clipboard)\n```\n\nEncrypted client-side by default — the decryption key is appended to the rendered URL as a fragment (`#k=...`), which browsers never send to any server, so GitHub stores only ciphertext. The full URL is the secret. Lose it and the content is unrecoverable. See [Plain shares](#plain-shares) for the unencrypted alternative.\n\nHere's a [live example](https://alecgard.github.io/share-file/?64a8a8cd0fbf41caac9ba9fca7fc353c) (plain, unencrypted).\n\n## Use it from an agent\n\n### Claude Code\n\nInstall the agent skill so [Claude Code](https://claude.ai/code) (or any agent\nthat loads skills) can call `share-file` for you:\n\n```bash\nmkdir -p ~/.claude/skills/share-file \u0026\u0026 \\\n  curl -fsSL https://raw.githubusercontent.com/alecgard/share-file/main/skill/SKILL.md \\\n    -o ~/.claude/skills/share-file/SKILL.md\n```\n\nThen ask the agent things like \"share this dashboard with my team\" or \"give me a link to\nthat screenshot\" — it'll call `share-file --json` and reply with the rendered\nURL (encrypted by default, so the URL is the secret — only share through a\nchannel you trust). For project-scoped install, drop it in\n`.claude/skills/share-file/` inside the repo instead.\n\n### Claude Desktop\n\nDownload and drop the extension into Claude Desktop:\n\n\nDownload [**share-file.mcpb**](https://github.com/alecgard/share-file/releases/latest/download/share-file.mcpb)\nand double-click it — Claude Desktop handles the install. (On Linux, drag it\ninto **Settings → Extensions**.)\n\nThen ask Claude \"share this PDF\" or \"give me a link to the chart you just made\"\nand the rendered URL comes back inline.\n\n## Common operations\n\n### Update an existing share (URL stays the same)\n\nFor encrypted shares (the default), pass `\u003cgist-id\u003e#k=\u003ckey\u003e` so the same key is reused and the URL stays stable:\n\n```bash\nshare-file --update \"abc123#k=...\" dashboard.html\n```\n\nFor plain shares, the bare gist ID works:\n\n```bash\nshare-file --no-encrypt --update abc123 dashboard.html\n```\n\nA full rendered URL is accepted anywhere an ID is, as a convenience for paste-from-clipboard.\n\nMode switches (plain↔encrypted) are supported and warn that the rendered URL changes.\n\n### Read from stdin\n\n```bash\necho \"$html\" | share-file --stdin --filename report.html\n```\n\n`--filename` is required so the viewer can detect the MIME type.\n\n### JSON output for scripts and agents\n\n```bash\n$ share-file --json /path/to/chart.png\n{\n  \"gist_id\": \"abc123\",\n  \"source_url\": \"https://gist.github.com/\u003cyou\u003e/abc123\",\n  \"rendered_url\": \"https://alecgard.github.io/share-file/?abc123#k=Woa-2A8tTA-P3KfHS6ohUA\",\n  \"filename\": \"chart.png\",\n  \"mime_type\": \"image/png\",\n  \"encoding\": \"base64\",\n  \"encrypted\": true\n}\n```\n\n## Plain shares\n\nPass `--no-encrypt` to skip client-side encryption. The gist is still secret (unguessable), but anyone with the gist ID reads the content directly:\n\n```bash\n$ share-file --no-encrypt --desc \"Q3 results\" dashboard.html\nSource:   https://gist.github.com/\u003cyou\u003e/abc123\nRendered: https://alecgard.github.io/share-file/?abc123\n```\n\n`--public` is an independent visibility flag: a public (listed) gist shows up on your GitHub gist profile (default is secret/unlisted). It can combine with or without `--no-encrypt` — encrypted public gists are allowed but unusual.\n\n```bash\nshare-file --public --no-encrypt --desc \"Q3 results\" dashboard.html\n```\n\n## Encrypted shares (default)\n\nWithout flags, content is AES-128-CBC encrypted client-side (HMAC-SHA256 authenticated) before upload, and the master key is appended to the rendered URL as a fragment.\n\n- The browser fragment (`#...`) is never sent to any server, so GitHub stores only ciphertext and the public viewer never sees the key.\n- Filename and MIME type are inside the encrypted blob; only the gist ID and the `[ShareFile] \u003cdesc\u003e` description are visible to GitHub.\n- The full URL is the secret. Anyone with it gets in; lose it and the content is unrecoverable — no copy is kept anywhere.\n- `--desc` is honored under encryption (server-visible, useful for labeling) — avoid putting sensitive metadata in it.\n- To update an encrypted share, pass `\u003cid\u003e#k=\u003ckey\u003e` so the same key is reused and the URL stays stable: `share-file --update \"\u003cid\u003e#k=\u003ckey\u003e\" file`. (A full rendered URL is accepted too, for convenience.)\n\n### View locally without the viewer\n\n```bash\nshare-file --view \"abc123#k=Woa-2A8tTA-P3KfHS6ohUA\"\n```\n\nFetches, decrypts locally, and opens the result in your default browser via a temporary local HTML wrapper — no viewer involved, no third-party JS sees the content. The wrapper lives in a private temp dir (0700/0600) under `$TMPDIR` and is left in place so browser refresh keeps working; the OS reaps it on its own schedule. Works for plain shares too (just pass the gist ID). Markdown and other text types are shown as plain text in a `\u003cpre\u003e` block since there's no in-browser renderer. A full rendered URL is also accepted as a convenience for paste-from-clipboard.\n\nFor scripts and agents, `--read` returns the decoded content as JSON (`{filename, mime_type, encoding, content}`) instead of opening a browser:\n\n```bash\nshare-file --read \"abc123#k=...\"\n```\n\n### List your shares\n\n```bash\n$ share-file --created\n2026-05-09  encrypted  https://alecgard.github.io/share-file/?abc123#k=Woa-2A8tTA-P3KfHS6ohUA\n2026-05-09  plain      https://alecgard.github.io/share-file/?def456\n2026-05-08  encrypted  https://alecgard.github.io/share-file/?ghi789  (key not on this machine)\n```\n\nLists every share-file gist on your account. Encrypted ones include the decryption key when share-file has seen it on this machine — keys are cached at `~/.config/share-file/keys/\u003cgist_id\u003e` whenever you create, update, view, or read an encrypted share. `--created --json` for machine-readable output.\n\n## Supported file types\n\nRenders inline in the viewer:\n\n- HTML (sandboxed iframe)\n- Images: PNG, JPG, GIF, SVG, WebP\n- PDFs\n- Audio and video\n- Plain text, Markdown, JSON, XML, source code\n\nAnything else is offered as a download link.\n\nSize limit: 900KB encoded payload (~675KB raw for binaries; the gist API gets\nunreliable above 1MB).\n\n## Self-host your own viewer\n\nBy default shares render through the public viewer at\n`alecgard.github.io/share-file/`. The viewer is static and only fetches the\ngist by ID, so there's no shared backend.\n\nYou might want your own viewer for: a dedicated rate-limit bucket, your own\ndomain or team-scoped instance, or independence from the public viewer's\nuptime. Gists you created against the public viewer keep working in your\nviewer (and vice versa) — the gist ID travels.\n\nOne command does the whole thing — forks the repo, enables GitHub Pages on\nthe fork, and points your local `share-file` at the new viewer:\n\n```bash\ngh repo clone alecgard/share-file\ncd share-file\n./bin/setup\n```\n\nRe-running is safe — it skips steps already done. After ~30s your viewer is\nlive at `https://\u003cyou\u003e.github.io/share-file/`.\n\n### How the script picks a viewer\n\nResolution order:\n\n1. `$SHARE_FILE_VIEWER` env var (overrides everything; useful per-shell)\n2. `~/.config/share-file/viewer` (written by `bin/setup`)\n3. Public default (`https://alecgard.github.io/share-file/`)\n\nTo switch viewers later without re-running setup:\n\n```bash\necho \"https://my-team.github.io/share-file/\" \u003e ~/.config/share-file/viewer\n```\n\n## Limits and caveats\n\n- **Unguessable, not authenticated.** Anyone with the URL can view. With encryption (the default), the URL itself is the secret — share it through a channel you trust. Without encryption (`--no-encrypt`), the gist ID alone is enough.\n- **Rate limit.** Unauthenticated GitHub API allows 60 requests/hour per\n  viewer IP. Self-hosting gives you your own rate-limit bucket.\n- **Single file per share.** Multi-file artifacts: inline assets or use a CDN.\n- **GitHub visibility.** With encryption GitHub sees only ciphertext plus the `[ShareFile] \u003cdesc\u003e` description (the description is always server-visible). Without encryption, gists are unguessable but readable by anyone with the ID, including GitHub.\n\n## Upgrade\n\n```bash\nshare-file --upgrade\n```\n\nRe-downloads the latest script (and the agent skill, if it's installed at `~/.claude/skills/share-file/`) from the upstream repo, overwriting the current install in place. Self-hosters can point at their fork with `SHARE_FILE_UPSTREAM=\u003cowner\u003e/\u003crepo\u003e`. Refuses to run if the script lives inside a git clone — use `git pull` there.\n\n## Uninstall\n\nRemoves the script, the agent skill, and the local config (cached\ndecryption keys for `--created` listings live here too):\n\n```bash\nrm -f ~/.local/bin/share-file \u0026\u0026 \\\n  rm -rf ~/.claude/skills/share-file ~/.config/share-file\n```\n\nFor the Claude Desktop extension, remove **share-file** from\n**Settings → Extensions** in the Desktop app.\n\nAlready-published gists are not deleted — manage them at\n\u003chttps://gist.github.com\u003e.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falecgard%2Fshare-file","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falecgard%2Fshare-file","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falecgard%2Fshare-file/lists"}