Triple-C marketplace: agents, skills, commands, hooks and plugins for all or individual containers #65

Merged
jknapp merged 48 commits from feat/marketplace into main 2026-09-27 23:43:27 +00:00
2 changed files with 11029 additions and 9 deletions
Showing only changes of commit 723555bf1d - Show all commits
File diff suppressed because it is too large Load Diff
@@ -46,8 +46,10 @@ publishing to a marketplace from inside Triple-C, a separate OS window for the m
Container user is addressed as `"claude"`. Constant-script + env-data rule: header of Container user is addressed as `"claude"`. Constant-script + env-data rule: header of
`commands/inspect_commands.rs`. `commands/inspect_commands.rs`.
- `container/entrypoint.sh` merges `CLAUDE_CODE_SETTINGS_JSON` into `~/.claude/settings.json` - `container/entrypoint.sh` merges `CLAUDE_CODE_SETTINGS_JSON` into `~/.claude/settings.json`
(≈:408-447), then runs `claude update` under `flock /tmp/.triple-c-claude-update.lock` (≈:408-447), runs `claude update` under `flock /tmp/.triple-c-claude-update.lock` (≈:649),
(≈:649) and prints `Triple-C container ready.` (≈:654). Nothing marks readiness on disk today. prints `Triple-C container ready.` and execs `su -s /bin/bash claude -c "exec sleep infinity"`
(≈:654-655). Nothing marks readiness on disk; that final process is the observable signal
(verified on a live container, where `jq`, `flock` and `tar` are also present).
- `commands/inspect_commands.rs` `list_container_capabilities` already inventories agents, skills, - `commands/inspect_commands.rs` `list_container_capabilities` already inventories agents, skills,
commands, hooks and plugins in a container (read-only); `CapabilityTiles.tsx` shows it. commands, hooks and plugins in a container (read-only); `CapabilityTiles.tsx` shows it.
- The container image has `gh`, `git`, `jq`. Claude Code 2.1.283 supports - The container image has `gh`, `git`, `jq`. Claude Code 2.1.283 supports
@@ -205,10 +207,13 @@ settings link for each.
The sync is idempotent; no container labels or recreation are involved. A container reset wipes The sync is idempotent; no container labels or recreation are involved. A container reset wipes
the volumes and the next start re-syncs. the volumes and the next start re-syncs.
**Readiness.** `entrypoint.sh` writes `/tmp/.triple-c-ready` just before printing **Readiness.** The entrypoint's last act is `exec su -s /bin/bash claude -c "exec sleep infinity"`,
`Triple-C container ready.`. The sync polls for it (up to 180 s) so it never races the so that process existing means the settings.json merge and `claude update` are done. The sync polls
entrypoint's settings.json merge or `claude update`. Plugin commands additionally run under `pgrep -x -f 'su -s /bin/bash claude -c exec sleep infinity'` (up to 180 s) before touching
`flock /tmp/.triple-c-claude-update.lock`. anything. No entrypoint change is needed, which matters: image and entrypoint changes reach an
existing project only through a base-image migration or a Reset (CLAUDE.md "`/home/claude` in the
image is seed-only" and the VPN notes), so a marker written by a new entrypoint would never appear
in existing projects. Plugin commands additionally run under `flock /tmp/.triple-c-claude-update.lock`.
**Payload.** The host builds one tar of the effective set, read from the cache at each pin: **Payload.** The host builds one tar of the effective set, read from the cache at each pin:
@@ -219,9 +224,12 @@ plugins/<plugin>/… # each at its own pin
manifest.json # effective set: kind, key, marketplace, commit, hook JSON manifest.json # effective set: kind, key, marketplace, commit, hook JSON
``` ```
uploaded to `~/.claude/triple-c/marketplace/incoming/` and then applied by a **constant** script uploaded to `~/.claude/triple-c/marketplace/incoming/` together with the sync script itself and
(`container/marketplace-sync.sh`, baked into the image; data only via env and files) run as applied by that **constant** script (data only via env and files) run as `claude`. The script lives
`claude`. Results come back as JSON on stdout. in the app (`app/src-tauri/src/marketplace/sync.sh`, embedded with `include_str!`) and is uploaded
on every sync rather than baked into the image, for the same reason as the readiness check: every
existing project gets it immediately and it is always the version that matches the app. Results
come back as JSON on stdout.
**Script behaviour.** State lives in `~/.claude/triple-c/marketplace/state.json` (what Triple-C **Script behaviour.** State lives in `~/.claude/triple-c/marketplace/state.json` (what Triple-C
installed last time, including the exact hook entries it inserted). installed last time, including the exact hook entries it inserted).