# Beta channel

> Parallel /last30days-beta install from the private repo, promotion workflow, and where client-specific customizations belong.

- Repository: mvanhorn/last30days-skill
- GitHub: https://github.com/mvanhorn/last30days-skill
- Human docs: https://grok-wiki.com/public/docs/mvanhorn-last30days-skill-50b5421a8cca
- Complete Markdown: https://grok-wiki.com/public/docs/mvanhorn-last30days-skill-50b5421a8cca/llms-full.txt

## Source Files

- `CONCEPTS.md`
- `CONFIGURATION.md`
- `AGENTS.md`
- `CHANGELOG.md`
- `docs/releases/v3.0.9.md`

---

---
title: "Beta channel"
description: "Parallel /last30days-beta install from the private repo, promotion workflow, and where client-specific customizations belong."
---

The beta channel is a second Agent Skills install sourced from the private companion repository `mvanhorn/last30days-skill-private`, exposed to harnesses as `/last30days-beta` alongside the public `/last30days` skill from `mvanhorn/last30days-skill`. Experimental SKILL.md and engine changes land in the private repo first; promotion to the public marketplace requires an explicit review pull request against the public repository—beta-only changes never ship on the public channel without that step.

## Public vs beta

| Dimension | Public channel | Beta channel |
|---|---|---|
| Repository | `mvanhorn/last30days-skill` (this repo) | `mvanhorn/last30days-skill-private` |
| Slash command | `/last30days` | `/last30days-beta` |
| Distribution | Claude Code marketplace, `npx skills add`, per-harness skill dirs | Private-repo install (see `BETA.md` in the private repo) |
| Badge line (first output line) | `🌐 last30days v{VERSION} · synced {YYYY-MM-DD}` | `🧪 last30days-beta · branch <name> · synced {YYYY-MM-DD}` |
| Promotion path | Default release target | Review PR → merge into public `main` |

Both channels share the same architectural split documented in [Skill, engine, and harness](/skill-engine-harness): `SKILL.md` is the runtime contract; `scripts/last30days.py` is the engine. The beta install is a parallel copy of that package with its own harness registration, not a flag on the public skill.

```mermaid
flowchart LR
  subgraph public["mvanhorn/last30days-skill"]
    P_SKILL["skills/last30days/SKILL.md"]
    P_ENGINE["scripts/last30days.py"]
  end
  subgraph private["mvanhorn/last30days-skill-private"]
    B_SKILL["SKILL.md + scripts/"]
    B_BETA["BETA.md workflow"]
  end
  subgraph harness["Harness runtime"]
    CMD_P["/last30days"]
    CMD_B["/last30days-beta"]
  end
  P_SKILL --> CMD_P
  P_ENGINE --> CMD_P
  B_SKILL --> CMD_B
  B_BETA -.->|promotion via review PR| public
```

<Note>
Detailed install, sync, and day-to-day beta operations live in `BETA.md` inside the private repository. That file is not vendored into the public tree; treat it as the operator runbook for beta maintainers.
</Note>

## Why the beta channel exists

Real-user validation on experimental SKILL.md and engine changes must not block the stable public marketplace. The beta channel lets maintainers iterate on contract changes (LAWs, badge enforcement, pre-flight flags) and client-specific data (category peers, subreddit lists, competitors-plan templates) before those changes appear in `mvanhorn/last30days-skill`.

The public `SKILL.md` documents why that separation matters in practice: on 2026-04-18 the same model achieved **10/10** compliance on the beta channel and **0/8** on public v3.0.6 with similar SKILL.md content—the delta was structural anchors (mandatory badge, `SKILL_DIR` substitution, preface ordering), not model capability. Beta is the environment where those anchors are proven before promotion.

## What belongs in beta vs public

Use the beta channel for customizations you do **not** intend to upstream—client-vertical category rows in `scripts/lib/categories.py`, internal subreddit lists, recurring `--competitors-plan` JSON skeletons, and other fork-specific SKILL.md tweaks.

Use the public repo’s [per-client setup](/per-client-setup) patterns when the customization is portable or may eventually ship to all users:

| Pattern | Public repo support | Typical beta use |
|---|---|---|
| Project-scoped `.claude/last30days.env` | Yes — [Configure sources](/configure-sources) | Rarely; env files work on either install |
| `--save-suffix` / `LAST30DAYS_MEMORY_DIR` wrappers | Yes | Beta runs often use `-raw-beta` suffix (see A/B testing) |
| Custom `categories.py` rows | Yes (upstreamable) | Vertical-specific peers you will not PR publicly |
| Pre-built `--competitors-plan` JSON | Yes (upstreamable) | Client-industry templates kept private |

<Warning>
Never publish beta-only changes to the public Claude Code marketplace or `main` without a review PR against `mvanhorn/last30days-skill`. The public marketplace plugin (`last30days` in `.claude-plugin/marketplace.json`) tracks only the public repository.
</Warning>

## Promotion workflow

Promotion is a deliberate merge from private experimentation into the public release line—not a separate release channel inside one repo.

<Steps>
<Step title="Develop and validate on beta">
Install or sync from `mvanhorn/last30days-skill-private` so `/last30days-beta` loads the private `SKILL.md` and engine. Run representative topics; confirm the beta badge line appears and output passes the LAWs contract.
</Step>
<Step title="Open a review PR on the public repo">
Cherry-pick or re-implement the validated changes on a branch of `mvanhorn/last30days-skill`. Scope the PR to what should ship to all users; leave client-only forks in the private repo.
</Step>
<Step title="Merge and release publicly">
After review, merge to public `main`, bump plugin version metadata, and let users pick up the release via marketplace update or `npx skills add` re-sync. Beta-only artifacts stay in the private repo.
</Step>
</Steps>

```mermaid
stateDiagram-v2
  [*] --> BetaDev: change in last30days-skill-private
  BetaDev --> BetaTest: /last30days-beta validation
  BetaTest --> BetaDev: fix failures
  BetaTest --> ReviewPR: open PR on last30days-skill
  ReviewPR --> PublicMain: merge after review
  PublicMain --> [*]: /last30days marketplace release
  BetaDev --> BetaOnly: client fork stays private
  BetaOnly --> [*]
```

The setup plan referenced in contributor docs (`docs/plans/2026-04-17-005-feat-beta-skill-from-private-repo-plan.md`) established this two-repo layout; that plan file is not present in the public tree—use `BETA.md` in the private repo for operational detail.

## A/B testing public vs beta

`skills/last30days/scripts/compare.sh` is a maintainer-side runner that invokes both slash commands sequentially (30s gap for rate limits) and prints saved raw file paths for manual diff review.

<CodeGroup>
```bash title="compare.sh invocation"
bash skills/last30days/scripts/compare.sh "Kevin Rose"
```

```text title="Expected output files"
$LAST30DAYS_MEMORY_DIR/<slug>-raw.md        # public /last30days
$LAST30DAYS_MEMORY_DIR/<slug>-raw-beta.md   # private /last30days-beta
```
</CodeGroup>

The script drives Claude Code headlessly:

```bash
claude -p --dangerously-skip-permissions "/last30days $TOPIC"
claude -p --dangerously-skip-permissions "/last30days-beta $TOPIC"
```

Verification signals after a run:

| Check | Public | Beta |
|---|---|---|
| First-line badge | `🌐 last30days v…` | `🧪 last30days-beta · branch …` |
| Raw filename suffix | `-raw.md` | `-raw-beta.md` |
| Regression signal | Missing public badge → stale install | Missing beta badge → beta badge regression |

If the beta badge is absent, treat it as a contract regression in the private `SKILL.md` synthesis section (the public repo’s `compare.sh` footer points maintainers at the beta setup plan naming pattern).

## Install and sync boundaries

**Public install (end users):** Claude Code marketplace (`/plugin install last30days@last30days-skill`), `npx skills add mvanhorn/last30days-skill -g -y`, or harness-specific paths documented in [Installation](/installation) and [Model clients](/model-clients).

**Beta install (maintainers / private forks):** Follow `BETA.md` in `mvanhorn/last30days-skill-private`. The public repo does not ship beta marketplace metadata.

Historical note: an older maintainer `sync.sh` script once pinned Claude plugin-cache paths; [#402](https://github.com/mvanhorn/last30days-skill/pull/402) fixed it pointing at the public cache instead of the private repo, and [#405](https://github.com/mvanhorn/last30days-skill/pull/405) removed `sync.sh` entirely in favor of `npx skills add . -g -y` (live symlink) for public dev deploys. Beta deploy semantics remain private-repo concerns.

<Info>
Public `SKILL.md` STEP 0 guards against a different stale-install bug: Claude Code’s `~/.claude/plugins/marketplaces/last30days-skill/` git clone lagging the versioned cache. That check applies to `/last30days`, not the beta install path.
</Info>

## Contributor rules (public repo)

From `AGENTS.md` and `CONFIGURATION.md`:

- Mirror new **public** configuration knobs in `CONFIGURATION.md` when they land in `SKILL.md` or the engine.
- Keep beta-only experiments out of public `main` until the review PR lands.
- When a config concept is beta-only today but becomes universal, promote code **and** docs in the same public PR.

## Related pages

<CardGroup>
<Card title="Per-client setup" href="/per-client-setup">
Project-scoped `.claude/last30days.env`, save-dir isolation, and portable wrapper patterns on the public skill.
</Card>
<Card title="Installation" href="/installation">
Marketplace and `npx skills add` flows for the public `/last30days` channel.
</Card>
<Card title="Skill contract" href="/skill-contract">
SKILL.md runtime authority, STEP 0 stale-clone guard, and engine invocation rules shared by both channels.
</Card>
<Card title="Develop and test" href="/develop-and-test">
`uv run pytest`, contributor constraints, and validation before promotion.
</Card>
</CardGroup>
