AGENTS.md
Agent Instructions
This repository is exclusively the standalone KDE Plasma widget for CodexBar.
In this repository, plugin, widget, plasmoid, and applet all mean the KDE Plasma frontend. The official macOS CodexBar product is a separate app and is never the implementation target of work in this repo.
Project Boundaries
- Work only on the Plasma applet in this repository unless the user explicitly requests a separate upstream CLI change. A request for macOS parity authorizes comparison and Plasma implementation only; it does not authorize editing the macOS app, the upstream CLI, or a sibling/fork workspace.
- Treat the official macOS app as a read-only product, behavior, terminology, and UX reference. Recreate only useful Plasma-native equivalents backed by an official CLI contract; do not translate Swift/AppKit/WidgetKit code into QML.
- Keep this repo small. It should contain only the Plasma applet, packaging helpers, tests, and docs.
- Do not copy the macOS app, Swift sources, Xcode projects, or full upstream CodexBar tree into this repo.
- Provider logic, authentication, config parsing, quota fetching, and JSON contracts belong in the upstream
codexbarCLI. - If a local upstream/fork workspace exists, keep it read-only unless the user explicitly asks for an upstream change in the current task. Use it only for comparison, syncing provider maps, or drafting CLI contract proposals.
- If the Plasma frontend needs new provider data, prefer extending the CLI JSON contract upstream. Do not hand-edit CodexBar config JSON from QML except through supported CLI commands.
- If the official Linux CLI does not expose the required data or action, record the gap as an upstream contract requirement and stop at the frontend boundary. Do not fill the gap with provider scraping, authentication, or config parsing in QML.
Sources of Truth and Parity
Use this order when sources disagree:
- The current Plasma implementation, config schema, tests, and documented repository decisions define what this repo currently supports.
- The released official
codexbarLinux CLI and its documented JSON contracts define what the frontend may consume. - The official macOS app defines product inspiration and parity candidates, not frontend architecture or data contracts.
- Local forks and experimental branches are comparison material only unless the user explicitly selects them as a target.
- Pin comparisons to an exact CLI/app version, tag, or commit. Do not mix an
installed CLI, upstream
main, and a local fork and report the result as one coherent release. - Classify every macOS parity gap as one of: Plasma-native and implementable now, blocked on an official CLI contract, or macOS-only/non-goal.
- Confirm a field or action exists in official Linux CLI output before designing UI around it. Swift view models, screenshots, and filenames are not contracts.
- Prefer generic CLI-described fields, actions, detail rows, and charts over provider-specific QML branches. Unknown providers and unknown optional fields should degrade gracefully rather than break the whole popup.
- Keep static provider metadata as fallback presentation data only. When the CLI exposes canonical metadata, consume it and retain cheap drift tests for any remaining fallback map.
Working Method
- Before editing, identify the requested Plasma surface, its owning QML file, the config entry if any, the CLI payload involved, and the nearest regression check. If the requested behavior belongs upstream, report that boundary before writing frontend code.
- Make the smallest coherent change that satisfies the request. Avoid unrelated refactors, formatting churn, generated artifacts, and changes in sibling repos.
- Preserve user changes in a dirty worktree. Review
git diffandgit statusbefore handing off, and call out unrelated pre-existing changes rather than incorporating them silently. - Add tests at the cheapest useful layer: normalization/contract assertions for data changes, static QML assertions for durable UI rules, and runtime checks only when static checks cannot establish the behavior.
- Run the narrowest relevant check while iterating, then the repository-required checks before completion. Never claim packaging or runtime verification unless it was actually performed; state clearly what was not available.
- When a parity decision changes, update
TODO.mdand the mirror below in the same change so future agents do not revive a rejected port or obsolete gap.
CLI and Data Safety
- Treat CLI stdout, stderr, descriptors, cached payloads, labels, URLs, and provider-controlled status text as untrusted input. Validate shapes, types, bounds, command allowlists, and URL schemes before use.
- Never log, display, persist, or pass through raw API keys, cookies, bearer tokens, auth headers, or unredacted diagnostics. Secret entry must use supported CLI stdin flows and redacted result contracts.
- Keep command nonce, timeout, disconnect, retry, and stale-result handling close to each external process lifecycle. A late process result must not overwrite a newer refresh or account selection.
- Preserve partial healthy data when one provider or optional enrichment fails; surface the scoped error without clearing unrelated provider snapshots.
Layout
metadata.json: Plasma applet metadata.contents/ui/main.qml: panel, popup, provider details, status badges, bars, account selection.contents/ui/components/: presentation-only QML components used by the panel, popup, and config pages.contents/ui/configGeneral.qml: general widget settings.contents/ui/configProviders.qml: provider enablement and provider actions.contents/config/main.xml: persisted Plasma configuration schema.contents/icons/: applet and provider icons.scripts/: static regression checks.
Agent-Readable Code Rules
- Before changing behavior, read the nearest existing implementation, config schema, and static test that cover that behavior. Do not infer contracts from filenames alone.
- Make names carry the contract: include provider/source/account/window/unit
where ambiguity is likely, and use boolean names that read clearly in
ifstatements. - Keep helper names honest.
build*,format*,provider*Url,*Rows, and*Texthelpers should stay side-effect free.refresh*,load*,parse*,select*,set*, andprocess*helpers may mutate state. - Keep parsing, normalization, presentation rows, and UI rendering separated. For new provider data, add/adjust a normalization helper before wiring QML controls directly to raw JSON.
- Treat CLI JSON as a contract. When adding a field, update the normalizer, the UI surface, the relevant static check, and docs/TODO if behavior changes.
- Prefer small named helpers over repeated inline JavaScript in delegates, timers, and DataSource callbacks.
- Prefer small presentation-only QML components for repeated or bulky UI blocks.
Pass normalized data and an explicit parent API object such as
appletorconfigPage; keep CLI commands, parsing, nonce/process lifecycle, and config writes in the owning page unless there is a focused plan and test coverage. - Put non-obvious lifecycle state in names:
connected*,pending*,*Memo,*Revision,*Initialized. Update that state close to the side effect it represents. - Comments should explain why a workaround, contract, or lifecycle rule exists. Do not comment obvious assignments or restate the QML type.
- Provider identity data is easy to drift. When adding a provider, check
provider keys, CLI aliases, title, color, docs/dashboard/login URLs, icon
asset, and
scripts/test_provider_icons.sh. - Every new UI rule that agents might accidentally break should get a cheap
static assertion in
scripts/before relying on manual review. - Keep
AGENTS.mdshort and practical. Add rules only after repeated friction or a real bug, and prefer pointing to canonical local examples over copying a full style guide.
Current TODO Mirror
Keep this in sync with TODO.md when feature parity decisions change:
- Provider-specific editing should come from a stable CLI descriptor, not
duplicated provider-specific config logic in QML. The Providers page consumes
descriptor fields/actions from
docs/cli-provider-settings-descriptor.mdfor generic source mode, API key, cookie source/manual cookie, enterprise/base URL, workspace/project ID, region, AWS profile/auth mode, and boolean extras. Missing controls include token-account add/edit/remove, provider-specific auth mode nuances, organization/team, metric, and quota threshold editors. - Provider onboarding improvements should stay CLI-backed: dashboard actions can come from the descriptor and login/account links are fine as fallbacks, but browser-cookie import, local-file, OAuth/device-flow, CLI-auth setup, and token-account workflows need JSON-described CLI actions before QML grows real controls.
- Generic CodexBar 0.48.1
usage.detailsrows and bounded bar/line charts are surfaced, with legacy dashboard KPI/summary payloads retained as a compatibility fallback. Richer provider-specific layouts, billing summaries, usage breakdowns, credits history, and model/request/token sections should wait for stable CLI presentation fields. - Interactive history charts can build on the current cost history bars, but hover/selection, credits history, and plan utilization history should wait for stable history payloads and avoid heavy delegate work. Compact burn-down/history views may be useful Plasma equivalents to macOS widgets.
- Gettext template extraction exists. Real
.pocatalogs, compiled catalog packaging, and translator contribution docs should come with localization work. - Notification refinements should stay quiet, configurable, and tied to clear state transitions.
- The fallback catalog covers the 67 provider IDs released in CodexBar v0.48.1
and retains fork-only compatibility assets. Future drift syncs should cover
provider keys, CLI aliases, titles, colors, docs/dashboard/login URLs, icon
assets, and
scripts/test_provider_icons.sh. - The GitHub Release updater is current. If a KDE Store channel is added, prefer KDE Store/KNewStuff/Discover for that channel.
- Do not port macOS-only surfaces directly, including WidgetKit, Sparkle, and Keychain/Full Disk Access UI. Add only useful Plasma/Linux equivalents and keep provider/auth logic in the CLI.
Agent instruction references:
- OpenAI Codex AGENTS.md guide: https://developers.openai.com/codex/guides/agents-md
- OpenAI Codex best practices: https://developers.openai.com/codex/learn/best-practices
- Claude Code memory/instructions: https://docs.anthropic.com/en/docs/claude-code/memory
- GitHub Copilot repository instructions: https://docs.github.com/en/copilot/how-tos/copilot-on-github/customize-copilot/add-custom-instructions/add-repository-instructions
- Cursor agent rules best practices: https://cursor.com/blog/agent-best-practices
Plasma/QML Guidelines
- Keep the Plasma 6 root object as
PlasmoidItem. UseContainmentItemonly for containment/panel/desktop code. - Preserve the standard package shape:
metadata.json,contents/ui,contents/config/main.xml, andcontents/config/config.qmlwhen config tabs are needed. - Persistent settings belong in
contents/config/main.xml; config pages bind them throughcfg_*properties, and runtime code reads them throughPlasmoid.configuration. - Prefer Plasma-styled controls for widget UI:
PlasmaComponentsfor the panel/popup surface and Kirigami/Qt Quick Controls in config pages. - Use the right control for the setting:
CheckBoxfor booleans,SpinBoxorSliderfor numbers,TextFieldfor short strings, andComboBoxwhen there are more than three choices. - Items default to 0x0. Always give visual children a real size through layouts, anchors, implicit sizes, or explicit compact dimensions.
- Use
Layout.minimum*,Layout.preferred*,implicitWidth,implicitHeight, andKirigami.Unitsinstead of panel-size magic numbers. - Prefer declarative bindings over imperative assignments. Keep bindings simple; move repeated or expensive calculations into small helper functions or cached properties.
- Avoid heavy JavaScript in delegates, compact panel rendering, timer paths, and data-source callbacks. Profile before doing performance refactors.
- Use anchors or layouts for relative positioning instead of binding
x,y,width, orheightto sibling geometry. - Keep delegates small and stable. Do not add clipping, shaders, or nested layout work in repeaters unless there is a visible need.
- External
Repeater/view delegate components must declarerequired property var modelDatainside the component. Do not rely on the parent assigningmodelDatathrough an alias property;qmllintmay miss the runtime scoping error. - When adding or moving QML files, update every local QML source list:
MakefileQML_FILES,scripts/test_qml_hardening.sh,scripts/update_translations.sh, and any static assertion inscripts/that was tied to the old file. - All user-facing text must go through
i18nori18np. - Test with
make checkfirst. Useplasmawindowedorplasmoidviewerfor quick widget checks when available; after extracting delegates/components, install or upgrade the local plasmoid and check recent Plasma logs forReferenceError,TypeError, andSyntaxError. - Restarting or replacing
plasmashellis a final runtime check, not the normal edit loop.
Primary references:
- KDE Plasma widget setup: https://develop.kde.org/docs/plasma/widget/setup/
- KDE Plasma widget properties: https://develop.kde.org/docs/plasma/widget/properties/
- KDE Plasma widget configuration: https://develop.kde.org/docs/plasma/widget/configuration/
- KDE Plasma widget testing: https://develop.kde.org/docs/plasma/widget/testing/
- KDE Plasma KF6 porting: https://develop.kde.org/docs/plasma/widget/porting_kf6/
- KDE Plasma QML API: https://develop.kde.org/docs/plasma/widget/plasma-qml-api/
- Qt QML best practices: https://doc.qt.io/qt-6/qtquick-bestpractices.html
- Qt Quick performance: https://doc.qt.io/qt-6/qtquick-performance.html
Verification
Run this before committing QML, config, packaging, or README changes:
| 1 | make check |
For packaging changes, also run:
| 1 | make package |
For runtime verification on the local KDE session:
| 1 | ./install.sh |
| 2 | journalctl --user -u plasma-plasmashell.service --since '2 minutes ago' --no-pager \ |
| 3 | | rg -n 'app\.codexbar|CodexBar|ReferenceError|TypeError|SyntaxError|file://.*/app.codexbar' |
Ignore unrelated Plasma logs from other widgets unless they mention app.codexbar.
CLI Assumptions
The widget expects a working codexbar binary. Useful probes:
| 1 | codexbar usage --format json --json-only |
| 2 | codexbar usage --provider codex --status --format json --json-only |
| 3 | codexbar usage --provider codex --all-accounts --format json --json-only |
| 4 | codexbar cost --format json --json-only |
| 5 | codexbar config providers --format json --json-only |
On the owner machine, the AUR package normally installs the CLI at /usr/bin/codexbar.
Release Flow
- Keep
maingreen withmake check. - Generate the distributable with
make package. - Publish
dist/codexbar-plasma.plasmoidin a GitHub Release. - Use the full fork workspace only for upstream sync work; this standalone repo is the public user-facing project.