{"id":25891388,"url":"https://github.com/nonrational/short-sheet","last_synced_at":"2025-07-21T22:36:14.453Z","repository":{"id":145223413,"uuid":"610443318","full_name":"nonrational/short-sheet","owner":"nonrational","description":"Synchronize Shortcut ←→ Google Sheets","archived":false,"fork":false,"pushed_at":"2025-02-27T05:06:08.000Z","size":221,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-02-27T06:20:17.400Z","etag":null,"topics":["google-sheets","productivity","project-management","repl","ruby","shortcut"],"latest_commit_sha":null,"homepage":"","language":"Ruby","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/nonrational.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}},"created_at":"2023-03-06T19:34:27.000Z","updated_at":"2025-02-27T05:06:11.000Z","dependencies_parsed_at":null,"dependency_job_id":"66a54f40-71f0-4b05-8a8e-eb1ad039c8c2","html_url":"https://github.com/nonrational/short-sheet","commit_stats":null,"previous_names":["nonrational/short-sheet"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nonrational%2Fshort-sheet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nonrational%2Fshort-sheet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nonrational%2Fshort-sheet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nonrational%2Fshort-sheet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nonrational","download_url":"https://codeload.github.com/nonrational/short-sheet/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241564547,"owners_count":19982960,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["google-sheets","productivity","project-management","repl","ruby","shortcut"],"created_at":"2025-03-02T20:17:02.792Z","updated_at":"2025-07-21T22:36:14.442Z","avatar_url":"https://github.com/nonrational.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ShortSheet\n\nA REPL environment and Rake tasks to synchronize [Shortcut](https://shortcut.com/) and [Google Sheets](https://workspace.google.com/) to enhance Shortcut's capabilities and facilitate low-friction planning.\n\n## Feature Overview\n\n- REPL with ActiveRecord-esque models for interacting with Shortcut \u0026 Sheets\n- Bi-directional sync between Shortcut Epics and Google Sheets\n- Automatic creation of canonically named Bi-Monthly Iterations\n- [Prioritization of iteration \"Ready\" stories](https://github.com/nonrational/short-sheet/blob/main/lib/tasks/iteration_ready_sort.rb#L34-L41) based on epic sort order, priority, product area, blocked status, due date, etc.\n- Template-based Shortcut Epic creation for things like Monthly Chores\n- Local Sinatra-based OAuth2 authorize endpoints to create Google OAuth Access Tokens 🐐\n- Bulk creation of stories from CSV\n- Migrate deprecated \"Project\" field values to Custom Field values\n- ~~Automatically move all incomplete stories from the previous iteration to the current iteration~~ 🎉 Now supported natively in Shortcut\n\n## Why Google Sheets?\n\nThis project provides customization and automation that sits on top of Shortcut to provide a more flexible and powerful planning experience. Google Sheets is familiar and flexible. A central \"planning sheet\" can then be a staging area to prioritize and organize initiatives before they're pushed into Shortcut.\n\n\u003cimg alt=\"A screenshot of a Google Sheet with columns A-K, including Name (with initiative names blurred out), Doc, Shortcut, Owner, Urgency, Status, Begin, Target, Start, End. The 'Begin' and 'End' columns show values like 'Nov H1 '24' and 'Feb H2 '25' (iteration names) and the resulting Start/End calendar dates are shown in columns to the right. The Target column has the funnel icon highlighted, indicated that the column is filtered.\" src='https://raw.githubusercontent.com/nonrational/short-sheet/refs/heads/main/static/annotated_google_sheet_screenshot.png' /\u003e\n\n### ① Iteration-Bound Delivery\n\nRather than needing to think in target _dates_, we've found it helpful to think in target _iterations_. Our planning sheet automatically translates canonical iteration names with start/end dates, so we can plan talking about iterations, then push the resulting dates into Shortcut epics.\n\n### ② Story to Epic Evolution\n\nWhen we consider a new initiative, it usually starts as a \"Scoping\" story in Shortcut. That story represents discovery and definition of the initiative. After scoping is complete, we'll make a go/no-go decision. If we decide not to proceed right now, having an Epic sitting in the hopper is confusing. So, the Sheet view allows us to prioritize Epics _alongside Stories_. The Sheet order can then be pushed into Shortcut.\n\n### ③ Obvious Filtering\n\nUsing Google Sheet's column filtering criteria is more intuitive for those less familiar with Shortcut.\n\n## Automation\n\n### Task Summary\n\n```\n$ rake -T\n\nrake config:check                    # Check config is valid\nrake config:export                   # Export the config.yml file as a base64 encoded string\n\nrake monthly_chores:create_current   # Create the next monthly chores epic\nrake monthly_chores:create_next      # Create the next monthly chores epic\n\nrake planning:prioritize_shortcut    # Sort epics by sheet order and ready stories by priority\nrake planning:review                 # Interactively review any out-of-sync initiatives and choose whether to update shortcut or the sheet\nrake planning:update_sheet           # Fetch information from shortcut and update the sheet with it\n\nrake shortcut:iteration:create_next  # Create the next iteration\nrake shortcut:project_sync:run       # Ensure that all stories with a project have the correct product area set\n```\n\n### Scheduling\n\nOnce you've got everything configured in `config.yml`, run `rake config:export` to produce a base64'd version suitable to drop into ENV to trigger actions via GitHub Actions or another crotab-like provider.\n\n## Development\n\n```shell\nasdf plugin add ruby\nasdf install\ngem install bundler\nbundle\n```\n\n## Configuration\n\nSee `config.yml.example`\n\n### Shortcut Credentials\n\nSet `shortcut-api-token` in `config.yml` or `SHORTCUT_API_TOKEN` in `.env`.\n\n### Google Workspace Credentials\n\n1. Generate an OAuth2 Client at https://console.cloud.google.com/apis/credentials with the required scopes and permissions to access the Drive and Sheets APIs.\n1. Download its JSON config to `client_secrets.json`.\n1. Run `make serve` and visit http://localhost:4567 to fetch access and refresh tokens, saving them to `google_credentials.json`.\n1. The refresh token will then automatically be used to refresh your credentials as necessary.\n\n## Rake Completion via Homebrew\n\nTab completion for `rake` is really handy.\n\n```sh\nbrew install bash bash-completion\ncurl -o \"$(brew --prefix)/etc/bash_completion.d/rake\" \\\n    \"https://raw.githubusercontent.com/ai/rake-completion/e46866ebf5d2e0d5b8cb3f03bae6ff98f22a2899/rake\"\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnonrational%2Fshort-sheet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnonrational%2Fshort-sheet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnonrational%2Fshort-sheet/lists"}