# gitea plugin — roadmap > **Status:** scaffold. Phase 1 = accounts CRUD + connection test only. > The `gitea-issue-client/` Python tool in the project root is the > reference for the full feature surface that needs to be ported. ## Phase 1 — done ✅ - [x] `GiteaClient.php` cURL wrapper with `testConnection()`, `searchIssues()`, `listRepoIssues()`, `getIssue()`, `listIssueComments()` - [x] `gitea_accounts` table with encrypted token (vault key, same as email) - [x] Routes: `GET/POST/PATCH/DELETE /api/gitea/accounts` + `POST .../test` - [x] Settings tab via `hyprcrd.settings.registerTab` - [x] Header button "gitea" - [x] Welcome view + accounts management form - [x] Connection test against `/api/v1/user` ## Phase 2 — issue reader ✅ - [x] **Issue list view** in the overlay: - Search box (`q` parameter, debounced 350ms) - State filter (open/closed/all) - Pagination (prev/next, hasMore heuristic since Gitea doesn't always return total) - Each row: title, repo path, state badge, labels, author, age - [x] **Issue detail view** (right pane): - Subject + state badge + labels + #number + repo - Body (markdown rendered via `hyprcrd.markdown.render` — exposed by core) - Comments list (each with author + relative timestamp + rendered markdown) - "Open on Gitea" link button - [x] **Extract → card**: - Card title = `[repo#number] title` - Card body = metadata header + body + comments + `#gitea #issue` tags - Color: green (#22c55e) - [ ] **Issue → card backlink** in a `gitea_issue_links` table — needed for Phase 5 bidirectional sync ## Phase 3 — write operations - [x] **Add comment** — composer textarea always visible at the bottom of the detail pane. Ctrl/Cmd+Enter posts. New comment is appended to local state and re-rendered immediately. - [x] **Close / reopen** — single button in the action bar that toggles state. Updates the badge, button label, and the row in the list. - [x] **Edit title** — pencil icon next to the title swaps to an inline input. Enter saves, Escape cancels. PATCH `/issues/{index}`. - [x] **Edit body** — pencil icon next to the body swaps to a textarea. Ctrl/Cmd+Enter saves, Escape cancels. - [x] **Set labels** — tag icon opens an inline editor that fetches the repo's label list (`GET /api/gitea/repo/.../labels`) and shows checkboxes with original colors. Save uses `PUT /issues/{index}/labels`. - [ ] **Set assignees** — needs a collaborator typeahead (next round, see TODO Phase 3.5) - [ ] **Set milestone** — needs milestone fetch + dropdown (next round) - [ ] **Set due date** — date picker (next round) ## Phase 3.5 — remaining metadata - [ ] `GET /api/gitea/repo/{accId}/{owner}/{repo}/milestones` - [ ] `GET /api/gitea/repo/{accId}/{owner}/{repo}/collaborators` - [ ] Milestone dropdown in detail view - [ ] Assignee multi-select with typeahead - [ ] Due date input + clear button ## Phase 4 — create issues - [x] **"new issue" button** in the list toolbar - [x] **Repo picker** loaded from `/user/repos` (cached per account, filtered to non-archived repos with push permission) - [x] **Title + body + labels** form - [x] **Submit** creates via POST `/repo/{accId}/{owner}/{repo}/issues`, refreshes list, auto-opens the new issue in the detail view - [ ] **Create from card**: a card → push as new gitea issue, store the backref so future edits can sync both ways (Phase 5) - [ ] **Pre-fill template** from a repo's `.gitea/ISSUE_TEMPLATE.md` if available (next round) ## Phase 5 — bidirectional sync (the killer feature) - [ ] When a card has a gitea backref, an "issue" badge appears - [ ] Edit the card body in hyprcrd → "push to gitea" button - [ ] "pull from gitea" button refreshes the card from the live issue - [ ] Conflict detection via `updated_at` timestamps - [ ] This replaces the Python tool's `gir push` workflow ## Phase 6 — multi-instance + ergonomics - [ ] Account selector remembers last-used account in localStorage - [ ] Per-account default filters (e.g. always show `assigned=true`) - [ ] Org/repo browsing tree on the left - [ ] Label browser per repo - [ ] Milestone view - [ ] Search across multiple accounts ## Hardening - [ ] Rate limiting on test endpoint - [ ] Better error messages (currently raw HTTP body leaks through) - [ ] Cert pinning option for self-hosted gitea instances - [ ] Connection caching (currently every request opens a new cURL handle) - [ ] Map common errors (401 → "token expired", 403 → "no access", etc.) ## Mapping from the Python tool | Python feature | hyprcrd plan | |----------------------------------------|-------------------------------------------| | `gi search` | overlay issue list with `q` filter | | `gi list --owner --repo` | overlay with owner/repo filter | | `gi get` | overlay detail pane | | `gi create` | Phase 4 "new issue" button | | `gi edit` | Phase 3 detail-pane edit buttons | | `gi comment` | Phase 3 comment box in detail pane | | `gi comments` | Phase 2 comments rendering | | `gir fetch` → markdown files | Phase 2 extract-as-card (no files needed) | | `gir push` → sync local edits | Phase 5 bidirectional sync | | `gir new --push` | Phase 4 create-from-card | | `gir clean` | not needed (cards are managed via the UI) | | `_valid-metadata.md` per repo | label/milestone dropdowns at edit time | | `templates/gir-new-issue.md` | configurable issue template per account | Once Phase 2–4 are done, the entire `gitea-issue-client/` Python tool can be removed from the project root.