{"id":50900896,"url":"https://github.com/gurgeous/gshoot","last_synced_at":"2026-06-16T02:30:50.838Z","repository":{"id":362345831,"uuid":"1232385755","full_name":"gurgeous/gshoot","owner":"gurgeous","description":"Magically import/export CSVs from Google Sheets","archived":false,"fork":false,"pushed_at":"2026-06-03T21:06:07.000Z","size":16303,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-03T21:08:01.683Z","etag":null,"topics":["csv","golang","google-sheets"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gurgeous.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":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-05-07T22:03:29.000Z","updated_at":"2026-06-03T21:06:12.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/gurgeous/gshoot","commit_stats":null,"previous_names":["gurgeous/gshoot"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/gurgeous/gshoot","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gurgeous%2Fgshoot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gurgeous%2Fgshoot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gurgeous%2Fgshoot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gurgeous%2Fgshoot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gurgeous","download_url":"https://codeload.github.com/gurgeous/gshoot/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gurgeous%2Fgshoot/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34388669,"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-06-16T02:00:06.860Z","response_time":126,"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":["csv","golang","google-sheets"],"created_at":"2026-06-16T02:30:50.233Z","updated_at":"2026-06-16T02:30:50.832Z","avatar_url":"https://github.com/gurgeous.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![test](https://github.com/gurgeous/gshoot/actions/workflows/ci.yml/badge.svg)](https://github.com/gurgeous/gshoot/actions/workflows/ci.yml)\n\n\u003cimg src=\"./logo.svg\" width=\"60%\"\u003e\n\n# gshoot\n\n`gshoot` is a CLI to magically import and export CSVs from Google Sheets. It has a few carefully chosen features along those lines.\n\nFor example, if I'm analyzing my local zoo I might run `gshoot up Zoo zoo.csv --numeric --layout --filter` to create a nice-looking Google Sheet. If I add more rows to `zoo.csv`, I can run `gshoot up Zoo zoo.csv --refill` to add the new data without messing up the Google Sheet. For some projects I do this dozens of times a day. Some examples:\n\n```sh\n# download the Google Sheets spreadsheet file \"Zoo\" to /tmp/zoo.csv\n$ gshoot down Zoo -o /tmp/zoo.csv\n\n# upload zoo.csv back into the Zoo Google Sheets file\n$ gshoot up Zoo /tmp/zoo.csv\n```\n\nThat's it, that's the whole thing. Be sure to check out our [authentication](#authentication) docs if you haven't been through this before with Google Sheets.\n\n### Demo\n\nNormally I'd put a CLI demo in here to show what `gshoot` can do, but the actual output isn't that exciting. Instead, here's a screenshot of the incredible welcome screen that shows up the first time you run the thing. Yes, it's animated and alpha blended. It's possible I took this too far\n\n\u003cimg src=\"./demo.gif\" /\u003e\n\nIt looks pretty great if you pipe the download into [tennis](https://github.com/gurgeous/tennis)\n\n\u003cimg width=\"60%\" src=\"https://github.com/user-attachments/assets/c0ea68d2-72b5-45d2-96da-259c3e6719e6\" /\u003e\n\n### Installation\n\nOn macOS use brew:\n\n```\n$ brew install gurgeous/tap/gshoot\n```\n\nFor Linux, see the [latest release on GitHub](https://github.com/gurgeous/gshoot/releases/latest). You'll find macOS builds in there too, but they are difficult to run since they are unsigned. Windows is not yet supported.\n\n### Important Features\n\n- download a CSV from a Google Sheets file (and maybe a specific sheet)\n- upload a CSV into a Google Sheets file (and maybe replace/merge into an existing sheet)\n- `up --replace` mode to overwrite an existing sheet\n- `up --refill` mode to merge data into an existing sheet, leaving other columns untouched\n- `up` has lots of little helpers to make life easier like `--filter`, `--layout`, `--numeric` and `--open`\n\n### Options\n\n```\n$ gshoot --help\n\nMagically upload/download CSVs from Google Sheets.\n\nCommands:\n  auth login     Login via OAuth. (start here!)\n  auth logout    Logout of OAuth.\n  auth status    Show auth status.\n  down           Download a Google Sheet as CSV.\n  up             Upload a CSV to Google Sheets.\n  list           List your Google Sheets.\n  peek           List sheets in a spreadsheet.\n  wipe           Wipe/delete all data from a spreadsheet.\n```\n\n### Up, Up, Up\n\nThere are three different modes for `gshoot up`.\n\n1. **safe** (default). A new sheet will be added to the file. The sheet name comes from the CSV filename, so `Something Awesome.tsv` becomes `Something Awesome`. When run repeatedly, you will see new sheets like `Something Awesome`, `Something Awesome_2`, `Something Awesome_3`...\n2. **`--replace`** will find/create the sheet in that file and overwrite it with the CSV data.\n3. **`--refill`** will merge the CSV data into an existing sheet. It will update old rows and add new ones as necessary. gshoot won't really mess with unknown columns, but it will _extend_ formulas and formatting into new rows.\n\nWhen using `up`, gshoot will find or create the spreadsheet file as necessary. The target sheet name comes from the CSV filename, which you can override with `--sheet`. I almost always use `--filter`, `--layout`, `--numeric` and `--open` too.\n\n### Down, Down, Down\n\n`gshoot down` is much simpler. By default it downloads the first sheet, but you can override with `--sheet`.\n\n### Other Commands\n\nThese are a few other commands for convenience:\n\n- `list` - list recently edited spreadsheet files\n- `peek` - list the sheets in a spreadsheet file\n- `wipe` - delete all sheets from a spreadsheet file\n\n### Authentication\n\nGetting `gshoot` to talk to Google Sheets is challenging, to put it mildly. Don't blame me, I do not work for Google and I did not design this system. `gshoot` talks to Google Sheets as you, using a _Google Cloud project_ that _you create_. Again, I would like to apologize in advance. This is just incredibly complicated and error-prone.\n\nI recommend these three well-written tutorials:\n\n- [gogcli](https://github.com/openclaw/gogcli/blob/main/docs/quickstart.md#2-get-an-oauth-client)\n- [gws](https://github.com/googleworkspace/cli/blob/main/README.md#manual-oauth-setup-google-cloud-console)\n- [UCSB CS156](https://ucsb-cs156.github.io/topics/oauth/google_oauth_consent_screen.html)\n\nThe goal here is something like:\n\n| Step                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                | Helpful Screenshot_Had_To_Use_Long_Name_Here                                                                                                                                                                                                                                 |\n| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| 1. Create a new **Google Cloud Project** to contain your OAuth setup. SELECT YOUR PROJECT!! You might have to wait a second before you can do that, Google is slow.                                                                                                                                                                                                                                                                                                                                 | \u003cimg width=\"543\" height=\"473\" alt=\"image\" src=\"https://github.com/user-attachments/assets/fddca4c0-acb9-40d0-9072-b80724deceeb\" /\u003e                                                                                                                                           |\n| 2. In your new project, enable these two Google APIs: **Google Drive** and **Google Sheets**. If your project doesn't enable these two APIs, nothing will work. Ever.                                                                                                                                                                                                                                                                                                                               | \u003cimg width=\"381\" height=\"265\" alt=\"image\" src=\"https://github.com/user-attachments/assets/5501aeb8-204a-4a62-9574-c3a0ea45f90a\" /\u003e                                                                                                                                           |\n| 3. Configure the **OAuth Consent Screen**. Pick whatever name/email you want, you are the only human alive who will see this screen. If your Google account is a \"Google Workspace\" account with a custom domain, set this up as **Internal Audience**. Otherwise use **External Audience**. If you use **External Audience**, add your email as the sole test user. This is required. No test user, no access for you. Is it strange Google doesn't automatically do this for you? I think so too! | \u003cimg width=\"535\" height=\"430\" alt=\"image\" src=\"https://github.com/user-attachments/assets/74cc4456-c081-4113-b070-6a0e675fa107\" /\u003e\u003cbr\u003e\u003cbr\u003e\u003cimg width=\"413\" height=\"383\" alt=\"image\" src=\"https://github.com/user-attachments/assets/7ef82e92-930d-4398-ba63-0331745cebe0\" /\u003e |\n| 4. Create a **Desktop OAuth Client**. Yes, I know that `gshoot` has nothing to do with desktop and this is very confusing. This is just what Google calls this kind of authentication.                                                                                                                                                                                                                                                                                                              | \u003cimg width=\"315\" height=\"410\" alt=\"image\" src=\"https://github.com/user-attachments/assets/40bc40b8-1070-488d-89b5-951a21580e00\" /\u003e                                                                                                                                           |\n| 5. Download the **OAuth Client Secrets JSON** file from your \"Desktop App\". Google gives it a really simple name like `client_secret_XXXXXXXXXXXX.com.json`.                                                                                                                                                                                                                                                                                                                                        | \u003cimg width=\"247\" height=\"541\" alt=\"image\" src=\"https://github.com/user-attachments/assets/3eccd6e9-5594-41c0-a473-2bca72e8a4ca\" /\u003e                                                                                                                                           |\n\nand finally we get to the part where gshoot can actually do something:\n\n```sh\n$ gshoot auth login --client-secret client_secret_XXXXXXXXXXXX.com.json\n```\n\n### Changelog\n\n#### 0.1.0 (unreleased)\n\n- initial release\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgurgeous%2Fgshoot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgurgeous%2Fgshoot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgurgeous%2Fgshoot/lists"}