{
  "markdown": "<p align=\"center\">\n  <img src=\"site/logo-lockup.svg\" alt=\"GoDrop\" width=\"420\">\n</p>\n\n<p align=\"center\">\n  <strong>Upload a file, get a hard-to-guess URL.</strong><br>\n  A drop box your coding agents can use: one Go binary, no database, your disk.\n</p>\n\n<p align=\"center\">\n  <a href=\"https://github.com/fatihbaltaci/GoDrop/actions/workflows/ci.yml\"><img src=\"https://github.com/fatihbaltaci/GoDrop/actions/workflows/ci.yml/badge.svg\" alt=\"CI\"></a>\n  <a href=\"https://pkg.go.dev/github.com/fatihbaltaci/GoDrop\"><img src=\"https://pkg.go.dev/badge/github.com/fatihbaltaci/GoDrop.svg\" alt=\"Go Reference\"></a>\n  <a href=\"LICENSE\"><img src=\"https://img.shields.io/badge/license-MIT-blue.svg\" alt=\"License: MIT\"></a>\n</p>\n\n<p align=\"center\">\n  <img src=\"site/demo.svg\" alt=\"Uploading photo.jpg with curl and getting back a hard-to-guess URL\" width=\"779\">\n</p>\n\nThat is the whole idea. Downloads need no token; uploads and deletes do.\n\n<details>\n<summary>The same thing as text, for copying</summary>\n\n```bash\ncurl -X POST \\\n  -H \"Authorization: Bearer $GODROP_TOKEN\" \\\n  -F \"file=@photo.jpg\" \\\n  https://files.example.com/upload\n```\n\n```json\n{\n  \"files\": [\n    {\n      \"url\": \"https://files.example.com/f/20260815-143022-8f4e2c91b7934b38a72d1c0e5b6a4f3d/photo.jpg\",\n      \"name\": \"photo.jpg\",\n      \"size_bytes\": 12345\n    }\n  ]\n}\n```\n\n</details>\n\n---\n\n## Why this exists: screenshots in pull requests\n\nCoding agents write the code, run the tests and open the pull request. Asking\nthem for a screenshot is the cheapest way to review the branches you are never\ngoing to check out and run yourself. They can take one: they start the app,\ndrive a browser and capture the page. Then they cannot attach it.\n\n**GitHub has no supported API for attaching an image to a pull request.** The\nweb interface takes a drag and drop, and that is the whole of it\n([cli/cli#4228](https://github.com/cli/cli/issues/4228),\n[#1895](https://github.com/cli/cli/issues/1895),\n[#12960](https://github.com/cli/cli/issues/12960) \"critical for agentic\nworkflows\", [community#28219](https://github.com/orgs/community/discussions/28219)).\nWhat is left is committing binaries into the repository, an undocumented\nupload endpoint that can stop working on any deploy, or a bucket with a policy,\na key and a bill attached to it.\n\nAn agent that can run `curl` can do this instead:\n\n```bash\nURL=$(curl -sS -X POST -H \"Authorization: Bearer $GODROP_TOKEN\" \\\n  -F \"file=@login-after-fix.png\" $GODROP_URL/upload | jq -r '.files[0].url')\n\ngh pr comment 42 --body \"Login page after the fix:\n\n![login]($URL)\"\n```\n\nThe identifier carries 128 random bits and the URL needs no token to open, so\nGitHub renders it inline for everyone on the thread. The file itself is on your\nown disk, which is where a picture of your unreleased work belongs, and it can\ndelete itself: `-H \"X-Expires-In: 30d\"`.\n\nNothing about this is specific to screenshots. It is the same three lines for a\nvideo of a flaky test, a profile, a build log too long for a comment, or a\ngenerated report. What an agent needs to do it by itself, including a skill it\ncan install, is in [For AI agents](#for-ai-agents).\n\n## Install\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/fatihbaltaci/GoDrop/v1.3.1/install.sh | sh\n```\n\nThe script picks the right binary for your machine, **verifies its SHA-256\nchecksum** against the published `SHA256SUMS`, installs it, and hands over to a\nsetup wizard that writes your configuration, creates your first token and\nchecks that the internet can actually reach you.\n\n**No root anywhere.** The binary goes to `~/.local/bin`, the configuration to\n`~/.godrop`, and the uploads into a docker volume, so updating and removing\nGoDrop later are the work of the same account. Run it as root, or set\n`GODROP_BIN_DIR=/usr/local/bin`, to install it for everybody instead. The one\nthing that does need root, once, is being in the `docker` group; setup checks\nthat before it writes anything.\n\nOther ways:\n\n```bash\n# Docker: comes back up after a reboot, and after a crash\ndocker run -d --name godrop --restart always \\\n  -p 8747:8747 \\\n  -e GODROP_TOKENS=$(openssl rand -hex 16) \\\n  -v godrop-data:/data \\\n  ghcr.io/fatihbaltaci/godrop\n\n# Debian or Ubuntu: installs the systemd service and creates its user.\n# Download the .deb for your architecture from the releases page:\n# https://github.com/fatihbaltaci/GoDrop/releases/latest\nsudo dpkg -i godrop_1.3.1_linux_amd64.deb\n\n# Fedora, RHEL or openSUSE\nsudo rpm -i godrop_1.3.1_linux_amd64.rpm\n\n# From source (Go 1.26+). Binaries built this way send no telemetry at all.\ngo install github.com/fatihbaltaci/GoDrop/cmd/godrop@latest\n```\n\nEvery package, archive and checksum is on the [releases\npage](https://github.com/fatihbaltaci/GoDrop/releases/latest), and the\ncontainer image is at\n[ghcr.io/fatihbaltaci/godrop](https://github.com/fatihbaltaci/GoDrop/pkgs/container/godrop).\n\n### Platforms\n\n| | Server | CLI | Notes |\n| --- | :---: | :---: | --- |\n| **Linux** (amd64, arm64) | ✅ | ✅ | Where it is meant to run: `.deb`, `.rpm`, `.apk`, container image, systemd unit |\n| **macOS** (Intel, Apple silicon) | ✅ | ✅ | Fine for development and small installs; no systemd, so use Docker or start it yourself |\n| **Windows** (amd64, arm64) | ⚠️ | ✅ | The binary works and is tested in CI, but there is no service wrapper, no installer script and no firewall guidance. Take the zip from Releases |\n| **FreeBSD** | 🔧 | 🔧 | Compiles and passes tests; no binaries published |\n\nThe suite runs on Linux, macOS and Windows for every change, and each release\nartefact carries [signed build\nprovenance](https://docs.github.com/actions/security-for-github-actions/using-artifact-attestations):\n\n```bash\ngh attestation verify godrop_1.3.1_linux_amd64.tar.gz --repo fatihbaltaci/GoDrop\n```\n\n## Guided setup\n\n```console\n$ godrop init\n\n  GoDrop 1.3.1 setup\n  Upload a file, get a hard-to-guess URL.\n\n  Public address\n  ? Public URL              https://files.example.com\n  Service\n  ? How should it run?      docker compose\n  HTTPS\n  ? Certificate             GoDrop gets one from Let's Encrypt\n  Limits\n  ? Settings                Recommended: 100MB per file, 20GB quota, no expiry\n\nChecks\n  ✓ storage                docker volume godrop-data\n  ✓ output directory       /home/you/.godrop\n  ✓ docker compose         available\n  ✓ port                   443 is free\n\nWritten\n  ✓ /home/you/.godrop/.env  (chmod 600, contains your token)\n  ✓ /home/you/.godrop/docker-compose.yml\n  ✓ /home/you/.godrop/sample.png  (a picture, so the first example below uploads something)\n\nYour API token\n\n  ┌─────────────────────────────────────┐\n  │ gd_7f3a9c2e1b8d4a6f0c5e2d9b3a7f1e4c │\n  └─────────────────────────────────────┘\n\n  ⚠ shown once and never again, so copy it now\n\nStarting\n  ✓ containers started\n\nVerifying\n  ✓ firewall               ufw allows port 443\n  ✓ firewall               ufw allows port 80\n  ✓ external access        reachable (HTTP 200, from FRA)\n\nUse it\n      curl -X POST -H \"Authorization: Bearer gd_7f3a…\" \\\n        -F \"file=@/home/you/.godrop/sample.png\" https://files.example.com/upload\n      ...\n\nAnonymous heartbeat\n  - once a day: {install_id, version, os, arch, deploy}\n  → turn it off any time with: godrop telemetry off\n```\n\nFour questions, and the last one is a choice between the recommended limits and\nsetting them yourself. Everything the answers depend on is checked before a\nsingle file is written, so a setup that cannot work says so at the start rather\nthan at the end, and the service is started and verified here rather than left\nas a command to paste. The picture is there so that the first command you paste\nuploads a real file.\n\nAnswering \"GoDrop gets one from Let's Encrypt\" is all HTTPS takes: it obtains\nthe certificate itself and renews it, so there is no proxy to install and\nnothing to configure. The question only offers it for a name Let's Encrypt can\nactually issue for, and the listen port question disappears, because serving\nTLS means 443.\n\nChanging your mind later is the same command with the setting on it. The token,\nthe uploads and every answer you do not mention stay where they are, and the\nservice restarts into the change:\n\n```bash\ngodrop init --base-url https://files.example.com   # or --port, --retention, --tls…\n```\n\nEvery question shows its default and can be answered with a flag instead, so CI\nand agents run the same code path without a terminal. Prompts are skipped\nautomatically when there is no TTY; `--no-input` makes that explicit:\n\n```bash\ngodrop init --no-input \\\n  --base-url https://files.example.com \\\n  --data-dir /var/lib/godrop \\\n  --max-total-size 20GB --json\n```\n\nThe wizard only offers what the host can do: systemd appears on Linux, not on\nmacOS or Windows, and the commands it prints use the right shell.\n\n## The API\n\nNine endpoints, no SDK, no client library: an agent that can call `curl` has\neverything, and `GET /llms.txt` describes this exact instance in plain text.\n\n| Method | Path | Auth | Purpose |\n| --- | --- | :---: | --- |\n| `POST` | `/upload` | ✅ | multipart, one or more `file` fields |\n| `PUT` | `/upload/{name}` | ✅ | raw request body |\n| `GET`/`HEAD` | `/f/{id}/{name}` · `/f/{id}.{ext}` | | download; supports Range and ETag |\n| `DELETE` | `/f/{id}/{name}` · `/f/{id}.{ext}` | ✅ | delete |\n| `GET` | `/healthz` | | liveness |\n| `GET` | `/readyz` | | readiness: is storage writable |\n| `GET` | `/stats` | ✅ | file count, bytes, quota, uptime |\n| `GET` | `/llms.txt` · `/openapi.yaml` | | machine-readable description |\n| `GET` | `/skill.md` | | the agent skill, installable by URL |\n\n```bash\n# Several files at once: all succeed or none do, and the response lists them\n# in the order they were sent\ncurl -X POST -H \"Authorization: Bearer $GODROP_TOKEN\" \\\n  -F \"file=@a.png\" -F \"file=@b.pdf\" -F \"file=@notes.txt\" \\\n  https://files.example.com/upload\n\n# A file that deletes itself: 30m, 12h, 7d, 30d\ncurl -X POST -H \"Authorization: Bearer $GODROP_TOKEN\" \\\n  -H \"X-Expires-In: 7d\" \\\n  -F \"file=@invoice.pdf\" \\\n  https://files.example.com/upload\n#   ?expires=7d does the same thing, for clients that cannot set a header\n\n# Upload without multipart\ncurl -X PUT --data-binary @report.pdf \\\n  -H \"X-Expires-In: 24h\" \\\n  -H \"Authorization: Bearer $GODROP_TOKEN\" \\\n  https://files.example.com/upload/report.pdf\n\n# Download (no token), or force a download instead of inline rendering\ncurl -O https://files.example.com/f/20260815-143022-8f4e…/photo.jpg\ncurl -O \"https://files.example.com/f/20260815-143022-8f4e….jpg?dl=1\"\n\n# Delete\ncurl -X DELETE -H \"Authorization: Bearer $GODROP_TOKEN\" \\\n  https://files.example.com/f/20260815-143022-8f4e…/photo.jpg\n```\n\nBoth `Authorization: Bearer <token>` and `X-API-Key: <token>` are accepted.\n\nAn upload answers with one entry per file, in the order they were sent, and\nwith `Location` pointing at the first:\n\n```json\n{\n  \"files\": [\n    { \"url\": \"https://files.example.com/f/20260815-143022-8f4e…/a.png\", \"name\": \"a.png\", \"size_bytes\": 8123 },\n    { \"url\": \"https://files.example.com/f/20260815-143024-b71d…/b.pdf\", \"name\": \"b.pdf\", \"size_bytes\": 91234,\n      \"expires_at\": \"2026-08-22T14:30:24Z\" }\n  ]\n}\n```\n\nOne shape whatever was sent, so nothing has to branch on how many files there\nwere. The identifier, the extension and therefore the media type are all in the\nURL, so the response does not repeat them; the name is there because the\ncosmetic part of the URL is a slug and cannot give it back. `expires_at`\nappears only when the upload asked for one, and `GODROP_RETENTION` is a\nmaximum, so a longer request is capped at it.\n\nWithout a JSON parser to hand, the header is the whole answer:\n\n```bash\ncurl -sS -D- -o /dev/null -X POST -H \"Authorization: Bearer $GODROP_TOKEN\" \\\n  -F \"file=@photo.jpg\" https://files.example.com/upload | grep -i '^location:'\n```\n\n**Status codes:** `201` uploaded · `204` deleted · `400` malformed body or too\nmany files · `401` bad token · `404` unknown id, or the name's extension does\nnot match the stored file · `413` file too large · `415` not multipart · `429`\nrate limited (honour `Retry-After`) · `507` quota full.\n\n## For AI agents\n\nGoDrop is built to be driven by coding agents rather than by a person at a\nbrowser. Give one a base URL and a token and it can discover the rest:\n\n```bash\ncurl https://files.example.com/llms.txt       # the whole API as plain text\ncurl https://files.example.com/openapi.yaml   # machine-readable schema\ncurl https://files.example.com/skill.md       # an agent skill it can keep\n```\n\n- Every command accepts `--json`, and in that mode prints **nothing but** the\n  document, so parsing never breaks\n- Colour and interactive prompts switch themselves off when there is no\n  terminal, so an agent can never get stuck on a form\n- One request per file, no multipart client library, no SDK to keep up to date:\n  `curl` and `jq` are the whole toolchain\n\n```bash\ngodrop token create --name claude-code --json | jq -r .token\ngodrop doctor --json | jq '.ok'\n```\n\n### Agent skills\n\nGoDrop ships an [agent skill](skills/godrop/SKILL.md): the instructions a\ncoding agent needs to upload a file and hand back a link, without being told\nhow. Install it with GoDrop itself:\n\n```bash\ngodrop skill install --scope user          # available in every project\ngodrop skill install                       # or just this repository\ngodrop skill install --agent claude        # Claude Code's own directory\n```\n\nOr with the GitHub CLI, which knows where every agent keeps them:\n\n```bash\ngh skill install fatihbaltaci/GoDrop godrop --scope user\n```\n\nEvery running instance serves the same skill at `/skill.md`, so an agent that\nhas been given nothing but a hostname can install it without the repository or\nthe binary:\n\n```bash\nnpx skills add https://files.example.com/skill.md\n```\n\nThe skill holds no secrets. It reads `GODROP_URL` and `GODROP_TOKEN` from the\nenvironment, so it is safe to commit alongside a project:\n\n```bash\nexport GODROP_URL=https://files.example.com\nexport GODROP_TOKEN=$(godrop token create --name claude-code --json | jq -r .token)\n```\n\nWith those two values in its environment, an agent can finish a pull request\nwithout anyone opening a browser:\n\n```bash\n# after the agent has captured ./screenshots/checkout.png\nURL=$(curl -sS -X POST -H \"Authorization: Bearer $GODROP_TOKEN\" \\\n  -H \"X-Expires-In: 30d\" -F \"file=@screenshots/checkout.png\" \\\n  $GODROP_URL/upload | jq -r '.files[0].url')\n\ngh pr comment \"$PR\" --body \"Checkout, after the fix:\n\n![checkout]($URL)\"\n```\n\n### Model Context Protocol\n\nNot every agent has a shell. A desktop assistant, an IDE panel or a workflow\nnode can produce a chart, a report or a screenshot and then have nowhere to put\nit, because it cannot run `curl`. For those, GoDrop serves an MCP endpoint at\n`/mcp`, behind the same token as everything else:\n\n```bash\nclaude mcp add --transport http godrop https://files.example.com/mcp \\\n  --header \"Authorization: Bearer $GODROP_TOKEN\"\n```\n\nAny client that takes a URL and a header works the same way, whether it is\nconfigured through a command or through a `mcpServers` block of JSON.\n\n| Tool | What it does |\n| --- | --- |\n| `upload_file` | Stores a file and returns the public URL, with an optional `expires_in` |\n| `delete_file` | Removes a file, given the URL the upload returned |\n| `storage_stats` | What is stored, and the limits this instance enforces |\n\nThe endpoint is built on protocol revision `2026-07-28`, the one that took the\nsessions out of MCP: there is no handshake and no session identifier, every\nrequest carries its own version and capabilities, and the server keeps nothing\nbetween them. That is the same way the rest of GoDrop works, which is why the\nendpoint is one file and not a dependency.\n\nClients built on the older revisions still open with a handshake, and they are\nanswered as well: the same three tools, and still no session assigned, so there\nis nothing to carry, resume or tear down in either era. Both paths are checked\nagainst the official MCP Inspector.\n\nFiles travel base64 encoded inside JSON, so `upload_file` takes at most 16MB.\nAn agent that *can* run a shell should keep using `POST /upload`: it streams,\nit has no size limit beyond the configured one, and it is one request either\nway.\n\n#### Files that are already on the machine\n\n`godrop mcp` is the same protocol over stdin and stdout, for a client that runs\na command instead of calling a URL:\n\n```json\n{\"mcpServers\": {\"godrop\": {\"command\": \"godrop\", \"args\": [\"mcp\"]}}}\n```\n\nThat is the whole configuration. The address and the token come from the\ninstallation on this machine, so the client is never told a secret, and every\nmessage is passed through to `/mcp` unchanged, so the tools are the same ones.\n\nIt adds one that only works there. `upload_local_file` takes a **path** and\nstreams the file, which means no base64, no 16MB ceiling and nothing held in\nmemory: a 60MB build artefact goes up in a second and comes back as a URL.\n\n```bash\ngodrop mcp --root ~/screenshots   # refuse to read anything outside this\n```\n\nWorth setting when an agent runs unattended: without it the command can read\nany file the user can, which is the point of it and also the risk.\n\n## Tokens\n\n```console\n$ godrop token create --name claude-code\n  gd_7f3a9c2e1b8d4a6f0c5e2d9b3a7f1e4c      # shown once, usable immediately\n\n$ godrop token list\n  NAME          CREATED       LAST USED\n  claude-code   2 min ago     just now\n  ci            12 days ago   3 hours ago\n\n$ godrop token revoke ci                    # effective within a second\n```\n\nEvery one of these commands, and `godrop telemetry`, `godrop health` and\n`godrop uninstall` with them, works on the installation this machine has, not\non the shell's idea of one: on a compose deployment they run where the files\nare, in the service's own container.\n\nTokens are stored as **SHA-256 digests** in `<data-dir>/tokens.json` (mode\n`0600`). A leaked file cannot be turned back into a working token, and a backup\nrestored onto another machine keeps working, which machine-bound encryption\nwould break for no security gain. A running server notices new and revoked\ntokens without a restart.\n\nGive every agent, script and machine its own token: revoking one leaves the\nrest alone, and `LAST USED` is how you find out which of them is still wired\ninto something.\n\nThere are two places a token can come from, and both are accepted at once.\n`GODROP_TOKENS` in the environment is the one the service starts with: it is\nwhat the generated `.env` holds, because a compose deployment has no data\ndirectory on the host to write a file into until the container has made the\nvolume, and it is the only thing that works on Fly and Railway. It has no name,\nso it is not a row in `godrop token list`; the list says where it is instead.\n`tokens.json` is what `godrop token create` adds to afterwards, and the only\nkind that can be revoked without a restart.\n\nOn a compose installation that file is inside the container. The commands are\nthe same ones: GoDrop runs them where the file is, using the same binary the\nservice runs, rather than writing a token nothing would read.\n\n## Command line\n\nEvery command documents itself. This is that output, generated from the binary\nso it cannot drift:\n\n<!-- BEGIN CLI -->\n\n<details>\n<summary><code>godrop --help</code></summary>\n\n```console\n$ godrop --help\nGoDrop is a tiny self-hosted file host.\n\nStart the server with \"godrop serve\"; the container image does that by itself.\n\nUsage:\n  godrop [flags]\n  godrop [command]\n\nAvailable Commands:\n  completion  Generate the autocompletion script for the specified shell\n  doctor      Diagnose the installation and print how to fix what is broken\n  health      Probe a running instance (used by the container HEALTHCHECK)\n  help        Help about any command\n  init        Guided setup: configure, generate a token, start and verify\n  mcp         Serve the Model Context Protocol on stdin and stdout\n  serve       Start the HTTP server\n  skill       Install the agent skill that teaches a coding agent to use GoDrop\n  telemetry   Inspect or change the anonymous heartbeat\n  token       Create, list and revoke API tokens\n  uninstall   Remove GoDrop from this machine\n  update      Update GoDrop to the latest release\n  version     Print version information\n\nFlags:\n  -h, --help       help for godrop\n      --json       machine-readable output\n      --no-color   disable coloured output\n  -v, --version    version for godrop\n\nUse \"godrop [command] --help\" for more information about a command.\n```\n\n</details>\n\n<details>\n<summary><code>godrop serve --help</code></summary>\n\n```console\n$ godrop serve --help\nStart the HTTP server.\n\nEverything is configured through the environment, so there are no flags to\nlearn and the same settings work under systemd, Docker and a bare shell. See\n.env.example for the annotated list, or run \"godrop doctor\" to see what the\ncurrent environment actually resolves to.\n\nPlain http is fine on loopback, on a private network or over Tailscale. On a\npublic address, GODROP_TLS=auto gets a certificate from Let's Encrypt and\nrenews it, and GODROP_TLS_CERT with GODROP_TLS_KEY uses one you already have.\nNeither needs a reverse proxy.\n\nUsage:\n  godrop serve [flags]\n\nFlags:\n  -h, --help   help for serve\n\nGlobal Flags:\n      --json       machine-readable output\n      --no-color   disable coloured output\n```\n\n</details>\n\n<details>\n<summary><code>godrop init --help</code></summary>\n\n```console\n$ godrop init --help\nWalks through the handful of decisions GoDrop needs, writes the configuration\nfiles, creates your first API token and, if you like, starts the service and\nconfirms that the outside world can actually reach it.\n\nEvery answer can be supplied as a flag instead; with --no-input the same wizard\nruns without asking anything, which is what CI and agents should use. Prompts\nare skipped automatically when there is no terminal.\n\nUsage:\n  godrop init [flags]\n\nFlags:\n      --base-url string         public URL, e.g. https://files.example.com\n      --data-dir string         where uploaded files are stored (default /var/lib/godrop as root, ~/.local/share/godrop otherwise)\n      --deployment string       compose, systemd or env (default \"compose\")\n      --force                   overwrite existing configuration files\n  -h, --help                    help for init\n      --limits                  set the size, quota, retention and port questions yourself\n      --max-file-size string    per-file limit, e.g. 100MB (default \"100MB\")\n      --max-total-size string   storage quota, empty for unlimited (default \"20GB\")\n      --no-external-check       do not ask godrop.sh to verify reachability\n      --no-input                never prompt; use flags and defaults (for CI and agents)\n      --out-dir string          where to write the generated files (default: working directory)\n      --port string             listen port (default \"8747\")\n      --retention string        delete files after this long, e.g. 30d\n      --start                   start the service when setup finishes (interactive setup does anyway; --start=false stops it)\n      --telemetry               send the anonymous daily heartbeat (default true)\n      --tls string              auto (Let's Encrypt), file, proxy or none\n      --tls-cert string         certificate chain in PEM, with --tls=file\n      --tls-key string          private key in PEM, with --tls=file\n      --token-name string       name for the generated token (default \"default\")\n\nGlobal Flags:\n      --json       machine-readable output\n      --no-color   disable coloured output\n```\n\n</details>\n\n<details>\n<summary><code>godrop token --help</code></summary>\n\n```console\n$ godrop token --help\nManage the API tokens that authorise uploads and deletes.\n\nTokens are stored as SHA-256 digests, so the clear-text value is shown exactly\nonce, when it is created. A running server notices changes within a\nsecond, with no restart needed.\n\nUsage:\n  godrop token [command]\n\nAvailable Commands:\n  create      Create a new API token\n  list        List tokens (names only, values are not recoverable)\n  revoke      Revoke a token by name\n\nFlags:\n      --data-dir string   data directory (default $GODROP_DATA_DIR or ./data)\n  -h, --help              help for token\n\nGlobal Flags:\n      --json       machine-readable output\n      --no-color   disable coloured output\n\nUse \"godrop token [command] --help\" for more information about a command.\n```\n\n</details>\n\n<details>\n<summary><code>godrop token create --help</code></summary>\n\n```console\n$ godrop token create --help\nCreate a new API token\n\nUsage:\n  godrop token create [flags]\n\nFlags:\n  -h, --help          help for create\n      --name string   label for this token (e.g. claude-code, ci, blog)\n\nGlobal Flags:\n      --data-dir string   data directory (default $GODROP_DATA_DIR or ./data)\n      --json              machine-readable output\n      --no-color          disable coloured output\n```\n\n</details>\n\n<details>\n<summary><code>godrop token list --help</code></summary>\n\n```console\n$ godrop token list --help\nList tokens (names only, values are not recoverable)\n\nUsage:\n  godrop token list [flags]\n\nFlags:\n  -h, --help   help for list\n\nGlobal Flags:\n      --data-dir string   data directory (default $GODROP_DATA_DIR or ./data)\n      --json              machine-readable output\n      --no-color          disable coloured output\n```\n\n</details>\n\n<details>\n<summary><code>godrop token revoke --help</code></summary>\n\n```console\n$ godrop token revoke --help\nRevoke a token by name\n\nUsage:\n  godrop token revoke <name> [flags]\n\nFlags:\n  -h, --help   help for revoke\n\nGlobal Flags:\n      --data-dir string   data directory (default $GODROP_DATA_DIR or ./data)\n      --json              machine-readable output\n      --no-color          disable coloured output\n```\n\n</details>\n\n<details>\n<summary><code>godrop doctor --help</code></summary>\n\n```console\n$ godrop doctor --help\nChecks configuration, storage, security posture, network reachability and\navailable updates, then prints the exact command that fixes each problem.\n\nRun it on the server for the full picture, or point it at a remote instance\nwith --url. Exits non-zero when a check fails, so it works as a deployment\ngate.\n\nThe token for a remote check is read from GODROP_TOKEN, so that it stays out\nof the process list and the shell history:\n\n  GODROP_TOKEN=gd_... godrop doctor --url https://files.example.com\n\nUsage:\n  godrop doctor [flags]\n\nFlags:\n      --check-url string   reachability service (default https://godrop.sh/api/check)\n  -h, --help               help for doctor\n      --offline            skip every check that needs the network\n      --token string       API token for the round-trip check; prefer GODROP_TOKEN, which does not appear in the process list\n      --url string         diagnose a remote instance at this base URL\n\nGlobal Flags:\n      --json       machine-readable output\n      --no-color   disable coloured output\n```\n\n</details>\n\n<details>\n<summary><code>godrop skill --help</code></summary>\n\n```console\n$ godrop skill --help\nAgent skills are folders holding a SKILL.md that tells a coding agent how\nto do something. GoDrop ships one, so an agent that has never seen it can\nupload a file and hand back a link without being told how.\n\nThe skill needs no secrets: it reads GODROP_URL and GODROP_TOKEN from the\nenvironment, so the same file is safe to commit alongside a project.\n\nIt can also be installed with the GitHub CLI, which supports every agent:\n\n  gh skill install fatihbaltaci/GoDrop godrop --scope user\n\nUsage:\n  godrop skill [command]\n\nAvailable Commands:\n  install     Write the skill into an agent's skill directory\n  show        Print the skill, so it can be piped somewhere else\n\nFlags:\n  -h, --help   help for skill\n\nGlobal Flags:\n      --json       machine-readable output\n      --no-color   disable coloured output\n\nUse \"godrop skill [command] --help\" for more information about a command.\n```\n\n</details>\n\n<details>\n<summary><code>godrop skill install --help</code></summary>\n\n```console\n$ godrop skill install --help\nWrite the skill into an agent's skill directory.\n\nProject scope (the default) installs into the working directory, so the skill\ntravels with the repository. User scope installs into your home directory,\nwhere every project can see it.\n\nUsage:\n  godrop skill install [flags]\n\nFlags:\n      --agent string   shared (most agents) or claude; use --dir for anything else (default \"shared\")\n      --dir string     install into this directory instead, overriding --agent and --scope\n      --force          replace an existing skill\n  -h, --help           help for install\n      --scope string   project or user (default \"project\")\n\nGlobal Flags:\n      --json       machine-readable output\n      --no-color   disable coloured output\n```\n\n</details>\n\n<details>\n<summary><code>godrop skill show --help</code></summary>\n\n```console\n$ godrop skill show --help\nPrint the skill, so it can be piped somewhere else\n\nUsage:\n  godrop skill show [flags]\n\nFlags:\n  -h, --help   help for show\n\nGlobal Flags:\n      --json       machine-readable output\n      --no-color   disable coloured output\n```\n\n</details>\n\n<details>\n<summary><code>godrop update --help</code></summary>\n\n```console\n$ godrop update --help\nDownload the newest release and put it in place of this binary.\n\nNothing is replaced until the download has been checked against the published\nSHA256SUMS and the new binary has been run and seen to report its own version,\nso a failed update leaves the working installation exactly as it was. The file\nis then swapped with a rename, which is atomic: a server that is already\nrunning keeps serving from the binary it started with, and restarts into the\nnew one.\n\nInstallations owned by something else are refused rather than overwritten. Use\napt, dnf or brew for those.\n\nWhen setup configured a service on this machine, that service is moved onto the\nnew release too: a compose deployment is pulled and recreated, a systemd one is\nrestarted. The configuration, the token and the uploads are untouched.\n\nUsage:\n  godrop update [flags]\n\nFlags:\n      --check            report whether a newer release exists, without installing it\n  -h, --help             help for update\n      --version string   install this release instead of the newest, e.g. v1.2.0\n\nGlobal Flags:\n      --json       machine-readable output\n      --no-color   disable coloured output\n```\n\n</details>\n\n<details>\n<summary><code>godrop telemetry --help</code></summary>\n\n```console\n$ godrop telemetry --help\nGoDrop sends one anonymous heartbeat per day:\n\n    {install_id, version, os, arch, deploy}\n\nThat is the whole payload. No file names, no identifiers, no counters, no\naddresses, no base URL. Use `godrop telemetry status --json` to see the exact\nbody that would be transmitted.\n\nUsage:\n  godrop telemetry [command]\n\nAvailable Commands:\n  off         Disable the anonymous heartbeat\n  on          Enable the anonymous heartbeat\n  status      Show whether telemetry is active and what would be sent\n\nFlags:\n      --data-dir string   data directory (default $GODROP_DATA_DIR or ./data)\n  -h, --help              help for telemetry\n\nGlobal Flags:\n      --json       machine-readable output\n      --no-color   disable coloured output\n\nUse \"godrop telemetry [command] --help\" for more information about a command.\n```\n\n</details>\n\n<details>\n<summary><code>godrop health --help</code></summary>\n\n```console\n$ godrop health --help\nProbe a running instance (used by the container HEALTHCHECK)\n\nUsage:\n  godrop health [flags]\n\nFlags:\n  -h, --help         help for health\n      --url string   URL to probe (default: the local listen address)\n\nGlobal Flags:\n      --json       machine-readable output\n      --no-color   disable coloured output\n```\n\n</details>\n\n<details>\n<summary><code>godrop version --help</code></summary>\n\n```console\n$ godrop version --help\nPrint version information\n\nUsage:\n  godrop version [flags]\n\nFlags:\n  -h, --help   help for version\n\nGlobal Flags:\n      --json       machine-readable output\n      --no-color   disable coloured output\n```\n\n</details>\n\n<!-- END CLI -->\n\n## Configuration\n\nEverything is an environment variable. Sizes accept `100MB`, `2GB`, `512KB`;\ndurations accept `30d`, `12h`, `90m`; rates accept `60/m`, `10/s`, `100/h`.\n\n| Variable | Default | Meaning |\n| --- | --- | --- |\n| `GODROP_TOKENS` | *(required)* | Comma-separated API tokens |\n| `GODROP_BASE_URL` | *(from request)* | Public URL used in responses |\n| `GODROP_ADDR` | `:8747` (`:443` with TLS) | Listen address |\n| `GODROP_DATA_DIR` | `./data` | Where files live (`/data` in the image) |\n| `GODROP_TLS` | `off` | `auto` for Let's Encrypt, `file` for your own certificate |\n| `GODROP_TLS_DOMAINS` | *(from base URL)* | Names to get a certificate for |\n| `GODROP_TLS_EMAIL` | *(none)* | Expiry warnings from Let's Encrypt |\n| `GODROP_TLS_CACHE_DIR` | `<data dir>/acme` | Account key and certificates |\n| `GODROP_TLS_CERT` / `GODROP_TLS_KEY` | *(none)* | Full chain and key, in PEM |\n| `GODROP_HTTP_ADDR` | `:80` with TLS | Redirect and challenge listener, `off` to disable |\n| `GODROP_MAX_FILE_SIZE` | `100MB` | Per-file limit → `413` |\n| `GODROP_MAX_FILES_PER_REQUEST` | `20` | Files per multipart request |\n| `GODROP_MAX_TOTAL_SIZE` | *(unlimited)* | Storage quota → `507` |\n| `GODROP_RETENTION` | *(forever)* | Delete uploads older than this |\n| `GODROP_CACHE_MAX_AGE` | `8760h` | How long caches may hold a download; also how long a deleted one can outlive the delete. `0` forbids caching |\n| `GODROP_RATE_LIMIT` | *(off)* | Uploads per token |\n| `GODROP_AUTH_RATE_LIMIT` | *(off)* | Failed authentications per client address |\n| `GODROP_CORS_ORIGINS` | `*` | Browser origins allowed to call the API |\n| `GODROP_READ_HEADER_TIMEOUT` | `10s` | Slow-header protection |\n| `GODROP_READ_TIMEOUT` / `GODROP_WRITE_TIMEOUT` | `0` | Body timeouts, off on purpose |\n| `GODROP_IDLE_TIMEOUT` | `120s` | Keep-alive idle timeout |\n| `GODROP_SHUTDOWN_TIMEOUT` | `30s` | Grace period for in-flight transfers |\n| `GODROP_LOG_FORMAT` / `GODROP_LOG_LEVEL` | `json` / `info` | Logging |\n| `GODROP_ACCESS_LOG` | `true` | Per-request log lines |\n| `GODROP_TELEMETRY` | `on` | Anonymous daily heartbeat |\n\n> The body timeouts default to `0` deliberately. A 100MB file over a slow\n> connection is legitimate and takes minutes; a `WriteTimeout` would cut it off\n> mid-transfer. The size limit, not the clock, is what bounds an upload.\n\nSee [`.env.example`](.env.example) for the annotated version.\n\n## How it works\n\n```\ndata/2026/08/15/20260815-143022-8f4e2c91b7934b38a72d1c0e5b6a4f3d.jpg\n     └── date ──┘└── identifier: timestamp + 128 random bits ──┘└ext┘\n```\n\nThe identifier *is* the index. It carries its own location, so a lookup needs\nno database and no directory scan; the timestamp keeps directories small and\nmakes retention a directory-level operation; the 128 random bits make URLs\nunguessable. The extension is the only metadata kept. The MIME type is derived\nfrom it at download time.\n\n**There is no listing endpoint, by design.** Keep the URL an upload returns.\n\nRetention only ever deletes uploads. `tokens.json` and the telemetry markers\nshare the directory, and sweeping those away by age would revoke every token.\n\n## Diagnosis\n\n```console\n$ godrop doctor\n\n  Configuration\n  ✓ tokens               2 token(s) configured\n  ✓ base_url             https://files.example.com\n  ⚠ storage quota        no quota set; uploads can fill the disk\n      → set GODROP_MAX_TOTAL_SIZE=20GB\n\n  Storage\n  ✓ writable             /var/lib/godrop is writable\n  ✓ usage                142 file(s), 834.2MB of 20.0GB (4%)\n  ✓ disk space           38.2GB free of 79.0GB\n  ✗ persistence          /data is inside the container, not a volume\n      → mount a volume: docker run -v godrop-data:/data …\n\n  Network\n  ✓ dns                  files.example.com → 5.9.1.2\n  ✓ tls                  valid, 67 days left (E5)\n  ✗ external             not reachable from the internet: connection refused\n      → open the port in your provider's firewall (security group)\n\n  End to end\n  ✗ proxy body limit     a proxy rejected a tiny upload with 413\n      → nginx: client_max_body_size 100m;\n```\n\nRun it from any shell on the server: it reads the `.env` setup wrote, so the\ndiagnosis is of your installation rather than of an empty environment. A\ncompose deployment keeps its files in a volume only the container can see, so\nthe container is asked about those and this machine answers for the network;\none report comes out of the two.\n\nIt exits non-zero when a check fails, so it works as a deployment gate:\n`godrop doctor --json | jq '.checks[] | select(.status==\"fail\")'`.\n\nThe reachability check asks <https://godrop.sh/api/check> to fetch your\n`/healthz` from the public internet, the only way to catch a cloud firewall,\nwhich is invisible from inside the machine. Only the URL is sent; skip it with\n`--offline`.\n\nTo diagnose an instance from your own machine, pass its address and a token.\nThe token goes in the environment, not on the command line, where the process\nlist and the shell history would both keep a copy:\n\n```bash\nGODROP_TOKEN=gd_... godrop doctor --url https://files.example.com\n```\n\n## Updating\n\n```bash\ngodrop update --check     # is there a newer release?\ngodrop update             # install it, and move the service onto it\n```\n\nNothing is replaced until the download has been checked against the published\n`SHA256SUMS` **and** the new binary has been run and seen to report its own\nversion, so a failed update leaves the working installation exactly as it was.\nThe swap itself is a rename, which is atomic: a running server keeps serving\nfrom the binary it started with and picks up the new one when it restarts.\n\nThe service is moved on too, because the binary you update is the command line\nand the service may be a container running a different copy. A compose\ndeployment is pulled and recreated, which replaces the container and keeps the\nnamed volume, so the uploads and the token survive it; a systemd deployment is\nrestarted. Re-running the installer, or `godrop init`, over an installation\nthat already exists does exactly the same thing rather than asking the\nquestions again:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/fatihbaltaci/GoDrop/v1.3.1/install.sh | sh   # again: this is an update\n```\n\nAn installation that belongs to a package manager is refused rather than\noverwritten, with the command that does the job instead:\n\n| Installed with | Update with |\n| --- | --- |\n| `install.sh`, or a downloaded archive | `godrop update` |\n| `.deb` | `sudo apt update && sudo apt install --only-upgrade godrop` |\n| `.rpm` | `sudo dnf upgrade godrop` |\n| Docker | `docker pull ghcr.io/fatihbaltaci/godrop` |\n| `go install` | `go install github.com/fatihbaltaci/GoDrop/cmd/godrop@latest` |\n\n## Deploying\n\n### On your own machine, a LAN or Tailscale\n\nTLS is not required. GoDrop speaks plain http, and on a network where nobody\ncan read the traffic that is the right choice rather than a compromise:\n\n```bash\nGODROP_TOKENS=$(openssl rand -hex 16) \\\nGODROP_BASE_URL=http://localhost:8747 \\\ngodrop serve\n```\n\nSet `GODROP_BASE_URL` to whatever the client will actually type, because that\nis what the returned URLs are built from: `http://localhost:8747`,\n`http://100.101.102.103:8747` for a Tailscale address, or\n`http://nas.local:8747` on a home network. Leave it unset and the URL is\nderived from the request, which also works.\n\n`godrop doctor` judges plain http by who could be listening. Loopback and\nTailscale pass, because nothing readable leaves the machine in the first case\nand the connection is already encrypted in the second. A LAN address warns:\ntokens are readable by anything else on that network. A public address fails.\n\n### A public server\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/fatihbaltaci/GoDrop/v1.3.1/install.sh | sh    # installs and runs `godrop init`\n```\n\nThe wizard asks how you want the certificate, and \"GoDrop gets one for me\" is\nthe first answer. See [HTTPS](#https) below for what each answer does.\n\n`deploy/` holds a [Caddy](deploy/Caddyfile) and an [nginx](deploy/nginx.conf)\nconfiguration for anyone who wants a proxy anyway, and a hardened\n[`godrop.service`](deploy/godrop.service) for systemd. Whichever proxy you use,\n**raise its body size limit** to match `GODROP_MAX_FILE_SIZE`. `godrop doctor`\ntests this for you.\n\nThe `.deb` and `.rpm` packages do the systemd part for you: they install the\nunit, create an unprivileged `godrop` user, and put the configuration in\n`/etc/godrop/godrop.env` (kept across upgrades) with uploads in\n`/var/lib/godrop`.\n\n### Fly.io\n\n```bash\nfly launch --no-deploy --copy-config\nfly volumes create godrop_data --size 10\nfly secrets set GODROP_TOKENS=$(openssl rand -hex 16)\nfly deploy\n```\n\n### Railway\n\nCreate a service from this repository, **add a volume mounted at `/data`**, and\nset `GODROP_TOKENS` and `GODROP_BASE_URL`. Without the volume, uploads vanish\non the next deploy.\n\n### Render\n\nUse [`render.yaml`](render.yaml) as a blueprint. The persistent disk requires a\npaid instance and pins the service to one instance, because GoDrop stores files\non local disk and does not scale horizontally, by design.\n\n## HTTPS\n\nGoDrop can serve https itself, so a public install needs no proxy at all:\n\n```bash\nGODROP_TLS=auto\nGODROP_BASE_URL=https://files.example.com\n```\n\nThat is the whole configuration. On the first request GoDrop gets a\ncertificate from Let's Encrypt, keeps it in `<data dir>/acme` and renews it\nlong before it expires.\n\n**Open 443 and 80** to the internet. Port 80 answers the certificate\nchallenge and redirects anyone who typed `http://`, so an install that opens\nonly 443 waits for a certificate that never arrives. On a VPS that means both\nthe host firewall and your provider's, which is invisible from inside the\nmachine:\n\n```bash\nsudo ufw allow 443,80/tcp\n# and the same two ports in the AWS security group, Hetzner firewall or GCP rule\n```\n\n`godrop init` and `godrop doctor` both check the two ports and say which one\nis missing. If port 80 is genuinely unavailable, set `GODROP_HTTP_ADDR=off`\nand the certificate is still issued over 443 alone, through `acme-tls/1`.\n\nAlready have a certificate, from certbot, your company CA or your cloud\nprovider? Name the two files and nothing else changes:\n\n```bash\nGODROP_TLS_CERT=/etc/letsencrypt/live/files.example.com/fullchain.pem\nGODROP_TLS_KEY=/etc/letsencrypt/live/files.example.com/privkey.pem\n```\n\n`godrop doctor` then reports how many days that certificate has left, and\nwhether anyone else on the machine can read the key.\n\nIn Docker it is the same two variables and the two ports:\n\n```bash\ndocker run -d --name godrop --restart always \\\n  -p 443:443 -p 80:80 \\\n  -e GODROP_TOKENS=$(openssl rand -hex 16) \\\n  -e GODROP_TLS=auto \\\n  -e GODROP_BASE_URL=https://files.example.com \\\n  -v godrop-data:/data \\\n  ghcr.io/fatihbaltaci/godrop\n```\n\n| Your situation | Setting |\n| --- | --- |\n| Public domain, nothing in front | `GODROP_TLS=auto` |\n| A certificate you already have | `GODROP_TLS_CERT` and `GODROP_TLS_KEY` |\n| Caddy, nginx, Traefik or a cloud load balancer in front | leave TLS off |\n| Loopback, a LAN, Tailscale, a private network | leave TLS off |\n\nTurning TLS on moves the listener to `:443` and starts a second one on `:80`,\nunless you set `GODROP_ADDR` or `GODROP_HTTP_ADDR` yourself. Under systemd\nthat needs `AmbientCapabilities=CAP_NET_BIND_SERVICE`, which the shipped unit\nalready has; in Docker, publish `-p 443:443 -p 80:80`.\n\nA certificate can only be issued for a public name that resolves to this\nmachine. `nas.local`, `10.0.0.5` and a Tailscale name are all refused at\nstartup, with the reason, rather than failing in a retry loop afterwards.\n\n## Security\n\n- **Unguessable identifiers**: 128 bits from `crypto/rand`; no enumeration\n  endpoint exists\n- **No path traversal, structurally**: the storage path is derived from the\n  validated identifier alone; a client-supplied name never takes part in it\n- **Active content is never rendered**: `.html`, `.svg`, `.xml` and friends are\n  always sent as downloads, with `nosniff` and `Content-Security-Policy:\n  default-src 'none'; sandbox` on every response\n- **Names cannot lie**: `/f/<id>/setup.exe` does not resolve to a stored `.jpg`\n- **Constant-time token comparison**, digests at rest, tokens never logged\n- **Fails closed**: the server refuses to start without a token\n- **Bounded everything**: per-file size, per-request size, file count, storage\n  quota, and optional per-token and per-address rate limits\n- **Logs are not a key ring**: the random half of an identifier is cut short\n  before it is written to a log, so a log reader cannot rebuild a download URL\n- **A delete is not an unpublish**: the server stops answering for the URL at\n  once, and an expiring upload tells caches to hold it no longer than that, but\n  a URL already shared may still be served by a cache nobody here controls, and\n  GitHub's image proxy keeps its own copy of anything rendered in a thread.\n  Check a screenshot before uploading it. `GODROP_CACHE_MAX_AGE` is the knob\n  for an operator who would rather a delete took effect everywhere quickly\n\n[SECURITY.md](SECURITY.md) sets out what GoDrop defends, what it deliberately\ndoes not, and a hardening checklist. Found something? Open a security advisory\non GitHub rather than an issue.\n\n## Telemetry\n\nGoDrop sends one anonymous heartbeat per day:\n\n```json\n{\"event\":\"heartbeat\",\"distinct_id\":\"a3f19c…\",\n \"properties\":{\"version\":\"1.3.1\",\"os\":\"linux\",\"arch\":\"arm64\",\"deploy\":\"docker\"}}\n```\n\nThat is the entire payload: no file names, no counts, no addresses, no base\nURL. It exists to answer \"how many installations are there, on what, and how\nmany are stuck on an old version\". Setup does not ask about it: it says what is\nsent, at the end, along with the command that stops it.\n\n```bash\ngodrop telemetry status --json   # shows the exact body that would be sent\ngodrop telemetry off             # or GODROP_TELEMETRY=off\n```\n\nBinaries built from source have no telemetry key compiled in and never report.\n\n## Development\n\n```bash\nmake test         # everything, with the race detector\nmake cover        # coverage, failing below 100%\nmake fuzz         # fuzz the input sanitisers\nmake run          # a local server on port 48080\nmake docker       # build the image\nmake snapshot     # build every release artefact locally, without publishing\nmake docs         # regenerate the command line reference above\n```\n\nThe website lives in [`site/`](site) and [`worker/`](worker), and is deployed\nseparately from the binary. See [`worker/README.md`](worker/README.md).\n\nReleases come from [GoReleaser](https://goreleaser.com) via\n[`.goreleaser.yaml`](.goreleaser.yaml): binaries, archives, checksums, Linux\npackages and the changelog. CI builds the whole set on every change, so a tag\nnever fails on something that could have been caught earlier.\n\nEvery statement in `internal/` is covered by a test, and CI fails if that ever\nslips. `cmd/godrop` is a three-line shim around `os.Exit` and is excluded.\nThe fuzz corpus in `internal/server/testdata/` includes a case that fuzzing\nfound: a file name that produced `..` inside a URL segment.\n\n---\n\n<p align=\"center\">\n  <sub>Sponsored by</sub>\n</p>\n\n<p align=\"center\">\n  <a href=\"https://getanteon.com/\">\n    <picture>\n      <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/getanteon/anteon/master/assets/anteon-logo-db.svg\">\n      <img src=\"https://raw.githubusercontent.com/getanteon/anteon/master/assets/anteon-logo-wb.svg\" alt=\"Anteon\" height=\"36\">\n    </picture>\n  </a>\n  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n  <a href=\"https://gurubase.io/\">\n    <picture>\n      <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://gurubase.io/media/gurubase-dark-logo.png\">\n      <img src=\"https://gurubase.io/media/gurubase-light-logo.png\" alt=\"Gurubase\" height=\"34\">\n    </picture>\n  </a>\n</p>\n\n<p align=\"center\">\n  <sub>\n    The gopher is after the Go mascot by\n    <a href=\"https://reneefrench.blogspot.com/\">Renée French</a>, CC BY 3.0.\n  </sub>\n</p>\n",
  "bytes": 48023,
  "sha": "656f93c707db8305d8bcbcb906b0570649f059f0e0a00d73867cedb53fd51d36",
  "repo_slug": "fatihbaltaci/godrop",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_fatihbaltaci_godrop_eacd869a/readme"
}