cloudcli moves to d12813e1, which carries the fix this workspace was missing: PluginsProvider and TasksSettingsProvider sit above ProtectedRoute and fetched exactly once, on mount, so in a browser holding no token yet the request landed on the login screen, came back 401, and nothing asked again — the whole session then ran with an empty plugin list and no Tasks section until a reload. plugin-taskwork moves to fdae5240, which keeps a task draft that loses focus. dev-host-proxy.sh gains ALLOWED_HOST. Publishing the dev host under a name rather than localhost — a port forward, a reverse proxy — otherwise ends at Vite's "Blocked request. This host is not allowed.". The value goes into the variable Vite reads for exactly this, so vite.config.js needs no local patch, and leaving ALLOWED_HOST unset passes an empty string, which Vite ignores. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
cloudcli-taskwork — workspace
Meta-repository for the Task Work plugin for CloudCLI UI (siteboon/claudecodeui).
It holds the specification, the developer scripts and two submodules. It contains
no code of its own — no package.json, no dependencies.
Specification: spec/SPEC-v3.md (current), design input:
spec/DESIGN-DOC.md.
Repository map
| Path | Repository | Role |
|---|---|---|
| (this repo) | gitea:ai-first/cloudcli-taskwork |
Workspace: spec, scripts, submodule pins |
plugin-taskwork/ |
gitea:ai-first/cloudcli-plugin-taskwork |
The product, developed here; manifest.json lives in its root |
| — | github:bvn13/cloudcli-plugin-taskwork |
Where users install the plugin from — public, anonymous HTTPS clone |
cloudcli/ |
github:bvn13/claudecodeui |
Fork of the host; source of the three upstream PRs |
| — | github:siteboon/claudecodeui |
Upstream: source of updates, target of the PRs |
| — | gitea:ai-first/cloudcli |
Pull mirror of the fork, read-only |
The plugin lives in two places on purpose: development and the submodule pin stay
on Gitea, while the host installs it over anonymous HTTPS, which a private Gitea
repository cannot serve. The GitHub copy is a push mirror — pushing to Gitea
is enough, it syncs on its own. Do not add a GitHub remote to plugin-taskwork/
and do not push there by hand.
⚠️ Never push to
gitea:ai-first/cloudcli. It is a pull mirror — anything pushed there is silently overwritten on the next sync. Thecloudcli/submodule points at the GitHub fork, and the mirror is deliberately not wired up as a remote.
Getting started
git clone --recurse-submodules ssh://git@gitea.bvn13.me:2221/ai-first/cloudcli-taskwork.git
cd cloudcli-taskwork
./scripts/bootstrap.sh
Then:
./scripts/dev-host.sh start # installs the built plugin and starts the host
It prints the URL — http://localhost:5183 by default. stop, restart,
status and logs do what they say; SERVER_PORT/VITE_PORT override the
ports.
The host runs against your real environment: the same ~/.claude projects,
the same ~/.cloudcli/auth.db, the same ~/.claude-code-ui/plugins. Nothing is
sandboxed, so you see what a user would see. Ports default to 3010/5183 rather
than 3001/5173 so an already installed CloudCLI keeps running — but note that
both instances then share one database. Set DATABASE_PATH to separate them.
After changing the plugin:
cd plugin-taskwork && npm run build
cd .. && ./scripts/link-plugin.sh # the host reads a copy, not a symlink
Client changes need only the plugin surface reopened; server changes need the host
restarted (./scripts/dev-host.sh restart), because the plugin's backend process
is spawned at host startup.
The plugin stores its data outside its own directory, in
~/.claude-code-ui/taskwork/tasks.json — the plugin directory is wiped on Update.
Access
All submodule URLs are SSH, so both submodules are writable with the same key
setup: ssh://git@gitea.bvn13.me:2221/… for the plugin (the Gitea repositories
are private) and git@github.com:bvn13/claudecodeui.git for the fork. The
upstream remote stays on HTTPS — it is fetch-only and public.
Cloning therefore needs an SSH key registered with both hosts; check with
ssh -T git@github.com and ssh -T -p 2221 git@gitea.bvn13.me.
Distribution goes through the public GitHub copy
(github:bvn13/cloudcli-plugin-taskwork), because the host clones a plugin
anonymously over HTTPS and the Gitea repository is private. The submodule keeps
pointing at Gitea: that is where the plugin is developed and pushed first.
Scripts
| Script | Purpose |
|---|---|
scripts/bootstrap.sh |
Init submodules, wire the upstream remote, install deps, build the host's native modules and the plugin |
scripts/dev-host.sh |
Run the patched host locally: start, stop, restart, status, logs |
scripts/export-patches.sh |
Regenerate plugin-taskwork/patches/*.patch from the fork's feature branches (§12.0) |
scripts/link-plugin.sh |
Symlink the local plugin into the host's plugin directory (--unlink to remove) |
scripts/check-submodule-pins.sh |
Verify every pinned submodule commit is reachable from its origin |
Branches in cloudcli/
Each feature branch is cut from the upstream tag v1.37.2, never from another
feature branch — that is what keeps the three pull requests independent.
| Branch | Base | Purpose |
|---|---|---|
main |
tracks upstream/main |
Upstream sync. Carries no commits of ours |
feat/resizable-sidebar |
v1.37.2 |
PR-1 — resizable sidebar |
feat/plugin-host-api |
v1.37.2 |
PR-2 — authenticated host API for plugins |
feat/plugin-sidebar-surface |
v1.37.2 |
PR-3 — sidebar surface for plugins |
dev/taskwork |
merge of the three | Local run and debugging; the submodule is pinned here |
dev/taskwork never takes part in a pull request and may be recreated at any time.
Working with the submodules
- Commit code inside the submodule, push it, and only then record the new pin
here with a separate commit
chore: bump <submodule> to <sha>. - Update with
git submodule update --remote --merge. - Run
./scripts/check-submodule-pins.shbefore pushing a pin bump.
Status
| Piece | State |
|---|---|
| Plugin | v1.0.0, pushed to Gitea; installs, builds and runs (npm install --ignore-scripts + npm run build in ~3 s) |
feat/resizable-sidebar |
Pushed to the fork. PR-1 not opened yet; no issue needed |
feat/plugin-host-api |
Pushed to the fork. Issue text in spec/upstream/issue-1-plugin-host-api.md, PR text in plugin-taskwork/docs/upstream-pr-2.md |
feat/plugin-sidebar-surface |
Pushed to the fork. Issue text in spec/upstream/issue-2-plugin-sidebar-surface.md, PR text in plugin-taskwork/docs/upstream-pr-3.md |
dev/taskwork |
Merge of the three plus one integration commit (host API in the sidebar surface) that never goes upstream; the cloudcli pin points here |
Remaining before upstream contact (§19 of the spec): open issue #1, then PR-2; issue #2, then PR-3; PR-1 can go on its own. Also outstanding: the manual acceptance checklist (§15.4), which needs a running host in a browser.
Release
See §13.2 of the spec. In short: export patches → bump the plugin version in
package.json and manifest.json → build, typecheck, test → commit build/,
patches/, CHANGELOG.md → tag vX.Y.Z in the plugin repo → bump the pins here.
Licence
The plugin and the fork are AGPL-3.0-or-later, following the upstream host.