glebis/sorted
Automate getSorted.de (Sorted) for freelancer invoicing, expense tracking, and German tax submissions (VAT, ZM, annual returns). Uses real-browser automation via Chrome Beta + agent-browser. Triggers on "create invoice", "sorted invoice", "download invoice", "submit VAT", "tax report", "sorted expenses", "/sorted", or any getSorted.de interaction.
npx skills add https://github.com/glebis/claude-skills --skill sorted
Automates getSorted.de via real Chrome Beta browser for invoicing, expense tracking, and German tax report submissions.
--remote-debugging-port=9222 (use /real-browser launch sequence)~/.chrome-beta-profileagent-browser CLI installedinvoice createCreate a new invoice on Sorted.
Required params: client name, amount
Optional: hours, rate, description, due date, service date, client type (business/person)
invoice download <invoice-number>Download a properly formatted PDF from Sorted (not browser print).
invoice send <invoice-number> --email <email>Send invoice via email directly from Sorted (paid plan only). On free plan, downloads PDF and sends via Telegram instead.
invoice listList all invoices with status (paid/unpaid).
expense addAdd an expense entry.
tax statusShow current tax obligations, deadlines, and overdue reports.
tax preview <report-type> <period>Preview a tax report before submission.
tax submit <report-type> <period>Submit a tax report to Finanzamt via ELSTER (requires paid plan).
App URL: https://app.getsorted.de/
| Section | Sidebar link | Purpose |
|---------|-------------|---------|
| Dashboard | Sorted (logo) | Overview: taxes owed, income, expenses |
| Taxes | Taxes | Tax reports, deadlines, submissions |
| Income | Income | Invoice list, create/edit invoices |
| Expenses | Expenses | Expense tracking, receipts |
| Tax consultant | Tax consultant | Advisor connection |
| Personal details | Profile → Personal details | Freelancer info, Steuernummer |
| Bank accounts | Profile → Bank accounts (Beta) | Connected banks |
| Subscription | Profile → Subscription | Plan management |
| Import | Profile → Import your data | Bulk data import |
| Settings | Profile → Settings | App preferences |
| Report | German name | Frequency | Description |
|--------|------------|-----------|-------------|
| Advance VAT | Umsatzsteuer-Voranmeldung (UStVA) | Quarterly | VAT collected on invoices |
| EU Summary | Zusammenfassende Meldung (ZM) | Quarterly | Revenue from EU customers |
| Annual Returns | EÜR + Einkommensteuererklärung | Yearly | Profit/loss + income tax |
Income → click Add → Create invoiceClient details area on invoice previewAdd new clientBusiness or Private personSave in dialogclickable and is positioned at ~x:734 y:413 on the invoice previewAdd a lineSave button. Title changes from "Add invoice" to "Edit invoice" on successCRITICAL: Do NOT use Chrome CDP Page.printToPDF — it captures the entire page including sidebar and settings panel. Always use Sorted's native PDF.
Save and send button (top right, teal button)ALL3 DOO BELGRADE-2025-03-21-20260506.pdf)generic element with cursor:pointer and onclick{CLIENT_NAME}-{INVOICE_NUMBER}-{DATE}.pdf~/Downloads/Close or ×)On paid plans, the "Email invoice" dialog is fully functional:
To field with client email (@e49)Subject if needed (auto-filled as "Gleb Kalinin sent you an invoice (#INVOICE-NUMBER)")Message in the textareaEmail invoice button (@e15) to sendOn the free plan, the dialog shows "Sending invoices by email is not available in your plan" with a "Change my plan" link. The PDF download still works regardless.
When email sending is unavailable, download the PDF and send via Telethon (see "Sending Invoice After Download" section below).
{CLIENT_NAME}-{INVOICE_NUMBER}-{YYYYMMDD}.pdf
Example: ALL3 DOO BELGRADE-2025-03-21-20260506.pdf
Existing clients are stored and reusable. When creating an invoice:
After downloading the PDF, send via Telegram using Telethon:
from telethon.sync import TelegramClient
import json
from pathlib import Path
config = json.loads((Path.home() / '.telegram_dl' / 'config.json').read_text())
session = str(Path.home() / '.telegram_dl' / 'user')
with TelegramClient(session, config['api_id'], config['api_hash']) as client:
client.send_file("username", "/path/to/invoice.pdf", caption="message")
Always use the /real-browser skill's launch sequence. Session name should be unique per run:
SESSION=$(LC_ALL=C tr -dc 'a-z0-9' < /dev/urandom | head -c 6)
agent-browser --cdp 9222 --session "$SESSION" open "https://app.getsorted.de/"
Google login is persisted — no need to re-authenticate each time.
Take glebis/sorted from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.