diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..7826dd7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,28 @@ +--- +name: Bug report +about: Report a problem with cu +labels: bug +--- + +## Description + +A clear description of the bug. + +## Steps to Reproduce + +1. Run `cu ...` +2. ... + +## Expected Behavior + +What you expected to happen. + +## Actual Behavior + +What actually happened (include error output if any; redact tokens). + +## Environment + +- `cu version` output: +- OS and version: +- Install method (Homebrew / go install / release binary): diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..aa4984d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,17 @@ +--- +name: Feature request +about: Suggest an idea for cu +labels: enhancement +--- + +## Problem + +What problem would this feature solve? What are you trying to do? + +## Proposed Solution + +What you'd like to happen (example commands/flags welcome). + +## Alternatives + +Any workarounds or alternative approaches you've considered. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..b53bb20 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,10 @@ +## Summary + +What does this PR change and why? + +## Checklist + +- [ ] `./scripts/ci.sh` passes locally (or `go test -race ./...` at minimum) +- [ ] Commit messages use conventional prefixes (`feat:`, `fix:`, `docs:`, `chore:`, `ci:`, `test:`) +- [ ] CLI docs regenerated if command help text changed (`cu docs markdown --dir docs/site/commands`) +- [ ] Docs updated if user-facing behavior changed diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 46f1170..5dcf282 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -36,7 +36,7 @@ jobs: pip install mkdocs-material - name: Build documentation - run: mkdocs build --site-dir _site + run: mkdocs build --strict --site-dir _site - name: Upload artifact uses: actions/upload-pages-artifact@v3 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..6816c06 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,76 @@ +# Contributing to cu + +Thanks for your interest in contributing! `cu` is an unofficial, community-maintained ClickUp CLI, and contributions of all kinds are welcome. + +## Development Setup + +Prerequisites: + +- Go 1.24 or later +- `make` (optional but convenient) + +Clone and build: + +```bash +git clone https://github.com/timimsms/cu.git +cd cu +make build # builds the ./cu binary +``` + +Common tasks: + +```bash +make build # build the binary +make test # run tests +make lint # run golangci-lint (brew install golangci-lint) +make fmt # gofmt + go mod tidy +``` + +Before pushing, run the full local CI suite (mirrors GitHub Actions — vet, staticcheck, gosec, errcheck, tests with race detector, build, tidy check, formatting): + +```bash +./scripts/ci.sh # or: make ci +``` + +## Commit Messages + +This repo uses conventional-commit prefixes: + +- `feat:` — new features +- `fix:` — bug fixes +- `docs:` — documentation changes +- `chore:` — maintenance, tooling, dependencies +- `ci:` — CI workflow changes +- `test:` — adding or improving tests + +## Testing + +- All changes should pass `go test -race ./...`. +- Add tests for new behavior where practical; table-driven tests are preferred. + +## Regenerating CLI Docs + +The command reference under `docs/site/commands/` is generated from the cobra command definitions. If you change command help text, regenerate the docs: + +```bash +make build +./cu docs markdown --dir docs/site/commands +``` + +Commit the regenerated files along with your change. + +## Previewing the Documentation Site + +The docs site uses [MkDocs](https://www.mkdocs.org/) with the Material theme: + +```bash +pip install mkdocs-material +mkdocs serve # local preview at http://127.0.0.1:8000 +``` + +`mkdocs build --strict` must pass — CI treats warnings as errors. + +## Pull Requests + +- Branch from `main` and keep PRs focused on a single change. +- Fill out the PR template and make sure CI is green. diff --git a/README.md b/README.md index b74768a..d5e0908 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,8 @@ [![CI](https://github.com/timimsms/cu/actions/workflows/ci.yml/badge.svg)](https://github.com/timimsms/cu/actions/workflows/ci.yml) [![Documentation](https://img.shields.io/badge/docs-timimsms.github.io%2Fcu-blue)](https://timimsms.github.io/cu/) +> **Note**: `cu` is an unofficial, community-maintained project and is not affiliated with or endorsed by ClickUp. + A GitHub CLI-inspired command-line interface for ClickUp. ## Overview @@ -24,18 +26,21 @@ A GitHub CLI-inspired command-line interface for ClickUp. ## Installation -### Homebrew (macOS/Linux) +### Homebrew (macOS) ```bash -# Coming soon -brew install clickup-cli +brew install timimsms/cu/cu ``` -### npm +Installs from the [timimsms/homebrew-cu](https://github.com/timimsms/homebrew-cu) tap. Available with the first tagged release. + +### Go ```bash -# Coming soon -npm install -g @clickup/cli +go install github.com/timimsms/cu/cmd/cu@latest ``` +### npm +Planned as `@timimsms/cu` (not yet published). + ### Direct Download Download the latest release from the [releases page](https://github.com/timimsms/cu/releases). diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..7ac9050 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,24 @@ +# Security Policy + +`cu` is an unofficial, community-maintained project and is not affiliated with or endorsed by ClickUp. + +## Token Storage + +`cu` stores your ClickUp personal API token in the operating system's native credential store via [zalando/go-keyring](https://github.com/zalando/go-keyring), under the service name `cu-cli`: + +- **macOS**: Keychain +- **Windows**: Credential Manager +- **Linux**: Secret Service (e.g. GNOME Keyring, KWallet) + +There is no plaintext fallback — tokens are never written to disk in plaintext by `cu`. On headless Linux systems, a Secret Service implementation must be available or authentication will fail. + +## Revoking Access + +If a token is compromised or no longer needed: + +1. Revoke it in ClickUp: **Settings → Apps**, then delete the token. +2. Remove the stored copy locally: `cu auth logout` + +## Reporting a Vulnerability + +Please report security vulnerabilities privately by emailing tim@mims.ms rather than opening a public issue. Include a description of the issue, steps to reproduce, and any relevant details. You should receive a response within a few days. diff --git a/docs/site/authentication.md b/docs/site/authentication.md new file mode 100644 index 0000000..feea070 --- /dev/null +++ b/docs/site/authentication.md @@ -0,0 +1,54 @@ +# Authentication & Security + +`cu` authenticates with ClickUp using a personal API token. + +## Creating a ClickUp Personal API Token + +1. Log in to ClickUp and open **Settings → Apps** (https://app.clickup.com/settings/apps). +2. Under **API Token**, click **Generate** (or **Regenerate**). +3. Copy the token — it starts with `pk_`. + +Then authenticate: + +```bash +cu auth login +``` + +Paste the token when prompted, or pass it directly: + +```bash +cu auth login --token pk_xxxxxxxx +``` + +Check your status at any time with `cu auth status`. + +## Where Your Token Is Stored + +`cu` stores the token in your operating system's native credential store via the [zalando/go-keyring](https://github.com/zalando/go-keyring) library, under the service name `cu-cli`: + +| OS | Credential store | +| --- | --- | +| macOS | Keychain | +| Windows | Credential Manager | +| Linux | Secret Service (GNOME Keyring, KWallet, etc.) | + +Tokens are never written to disk in plaintext by `cu` — there is no plaintext fallback. + +## Headless Linux Caveat + +On headless Linux (servers, containers, CI), `cu` requires a running Secret Service implementation to store and read the token. There is currently no environment-variable fallback, so authentication will fail without one. A common workaround is to run a keyring daemon such as `gnome-keyring-daemon` with a D-Bus session. + +## Revoking Access + +If a token is compromised or no longer needed: + +1. Revoke it in ClickUp under **Settings → Apps** so it can no longer be used anywhere. +2. Remove the locally stored copy: + +```bash +cu auth logout +``` + +## Reporting Security Issues + +See the project's [security policy](https://github.com/timimsms/cu/blob/main/SECURITY.md) for how to report vulnerabilities. diff --git a/docs/site/commands/cu_auth.md b/docs/site/commands/cu_auth.md index 5d69e83..823dfbf 100644 --- a/docs/site/commands/cu_auth.md +++ b/docs/site/commands/cu_auth.md @@ -4,7 +4,7 @@ Manage authentication with ClickUp ### Synopsis -Authenticate cu with ClickUp API using personal tokens or OAuth. +Authenticate cu with the ClickUp API using a personal API token. ### Options @@ -27,4 +27,4 @@ Authenticate cu with ClickUp API using personal tokens or OAuth. * [cu auth logout](cu_auth_logout.md) - Log out from ClickUp * [cu auth status](cu_auth_status.md) - Show authentication status -###### Auto generated by spf13/cobra on 29-Jun-2025 +###### Auto generated by spf13/cobra on 14-Jul-2026 diff --git a/docs/site/commands/cu_auth_login.md b/docs/site/commands/cu_auth_login.md index 3ba1ea9..f36b074 100644 --- a/docs/site/commands/cu_auth_login.md +++ b/docs/site/commands/cu_auth_login.md @@ -4,7 +4,7 @@ Authenticate with ClickUp ### Synopsis -Authenticate with ClickUp using a personal API token or OAuth device flow. +Authenticate with ClickUp using a personal API token. The token is stored securely in your operating system's credential store. ``` cu auth login [flags] @@ -30,4 +30,4 @@ cu auth login [flags] * [cu auth](cu_auth.md) - Manage authentication with ClickUp -###### Auto generated by spf13/cobra on 29-Jun-2025 +###### Auto generated by spf13/cobra on 14-Jul-2026 diff --git a/docs/site/index.md b/docs/site/index.md index 1bc03e6..0d125f4 100644 --- a/docs/site/index.md +++ b/docs/site/index.md @@ -1,5 +1,7 @@ # cu - ClickUp CLI +> **Note**: `cu` is an unofficial, community-maintained project and is not affiliated with or endorsed by ClickUp. + A GitHub CLI-inspired command-line interface for ClickUp. ## Overview @@ -19,27 +21,48 @@ A GitHub CLI-inspired command-line interface for ClickUp. - **Shell Completions**: Full support for bash, zsh, fish, and PowerShell - **Cross-Platform**: Works on macOS, Linux, and Windows +## Installation + +### Homebrew (macOS) + +```bash +brew install timimsms/cu/cu +``` + +Installs from the [timimsms/homebrew-cu](https://github.com/timimsms/homebrew-cu) tap. Available with the first tagged release. + +### Go + +```bash +go install github.com/timimsms/cu/cmd/cu@latest +``` + +### npm + +Planned as `@timimsms/cu` (not yet published). + +### Direct Download + +Download the latest release from the [releases page](https://github.com/timimsms/cu/releases). + ## Quick Start Get started with `cu` in just a few steps: ```bash -# 1. Install cu (see Installation guide) -brew install clickup-cli # Coming soon - -# 2. Authenticate with ClickUp +# 1. Authenticate with ClickUp cu auth login -# 3. List your tasks +# 2. List your tasks cu task list -# 4. Create a new task +# 3. Create a new task cu task create ``` ## Next Steps +- [Authentication & Security](authentication.md) - Create a token and connect `cu` to ClickUp - [Command Reference](commands/cu.md) - Explore all available commands - [Task Management](commands/cu_task.md) - Learn how to manage tasks -- [Configuration](commands/cu_config.md) - Customize `cu` to your workflow -- [Authentication](commands/cu_auth.md) - Connect `cu` to your ClickUp account \ No newline at end of file +- [Configuration](commands/cu_config.md) - Customize `cu` to your workflow \ No newline at end of file diff --git a/internal/cmd/auth.go b/internal/cmd/auth.go index c9541e9..ec6e61f 100644 --- a/internal/cmd/auth.go +++ b/internal/cmd/auth.go @@ -14,13 +14,13 @@ import ( var authCmd = &cobra.Command{ Use: "auth", Short: "Manage authentication with ClickUp", - Long: `Authenticate cu with ClickUp API using personal tokens or OAuth.`, + Long: `Authenticate cu with the ClickUp API using a personal API token.`, } var authLoginCmd = &cobra.Command{ Use: "login", Short: "Authenticate with ClickUp", - Long: `Authenticate with ClickUp using a personal API token or OAuth device flow.`, + Long: `Authenticate with ClickUp using a personal API token. The token is stored securely in your operating system's credential store.`, Run: func(cmd *cobra.Command, args []string) { token, _ := cmd.Flags().GetString("token") workspace, _ := cmd.Flags().GetString("workspace") diff --git a/mkdocs.yml b/mkdocs.yml index 48a7d36..b3cf496 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -2,7 +2,7 @@ site_name: cu - ClickUp CLI site_url: https://timimsms.github.io/cu repo_url: https://github.com/timimsms/cu repo_name: timimsms/cu -edit_uri: edit/main/docs/ +edit_uri: edit/main/docs/site/ theme: name: material @@ -31,6 +31,7 @@ theme: nav: - Home: index.md + - Authentication & Security: authentication.md - Commands: - cu: commands/cu.md - Authentication: