> ## Content Index
> Fetch the complete content index at: https://contextfirst.blog/llms.txt
> Use this file to discover other available public pages before exploring further.

# Your Slack Script Just Shipped
- URL: https://contextfirst.blog/script-to-cli-spreadsheet-product/
- Published: 2026-08-30T13:00:00.000Z
- Updated: 2026-08-30T13:00:00.000Z
- Description: The second team is the product threshold
- Author: Iheatu Chris Wogu
- Tags: Field Notes, Engineering Management, Agentic Delivery, Learning Journey 2026

Three weeks after the [857-line honesty machine](./03-pr-timeline-script.md), managers were running reports weekly. Slack carried forked copies with incompatible flags. Excel exports became the source of truth in staff meetings - and **breakage was visible**.

On **2026-06-01 at 09:32**, commit `9d47215` refactored github-analysis into a **uv-managed CLI** with `analyze`, `export`, and `run` commands. This note is about recognizing when a personal script becomes **team infrastructure**.

**Here's what this piece covers:** the product threshold, what changed in the refactor, version as contract, and three lead actions.

Part of [Field Notes: agentic delivery](https://contextfirst.blog/field-notes-agentic-delivery/).

---

## 1\. The leadership problem

Ad-hoc scripts spread via Slack. Everyone runs different flags. When the spreadsheet breaks mid-staff-meeting, you learn you never had an owner.

**Wrong:** "We refactored for cleanliness."  
**Right:** "Jun 1 `9d47215`: monolith to `github-analysis` CLI because three managers were running incompatible exports."

The anti-pattern is the **eternal personal script** \- no owner, no contract, no `--help`.

---

## 2\. What the git history shows

| Date             | Commit  | State                                            |
| ---------------- | ------- | ------------------------------------------------ |
| 2026-04-10       | d52975b | 857-line single file + README                    |
| 2026-06-01 09:32 | 9d47215 | Modular package, pyproject + uv, CLI entry point |

`9d47215` \- *Refactor into modular CLI with uv, team summaries, and Excel export* \- touched the whole repo layout:

```text
github_analysis/cli/commands/analyze.py
github_analysis/cli/commands/export.py
github_analysis/cli/commands/run.py
github_analysis/analysis/   github_analysis/export/
github_analysis/pipeline/
```

flowchart LR subgraph before\["Apr 10 - probe"\] M\[857-line monolith\] end subgraph after\["Jun 1 - product"\] CLI\[github-analysis CLI\] CLI --> A\[analyze\] CLI --> E\[export\] CLI --> R\[run\] end M --> CLI

---

## 3\. What changed in the refactor

**Package layout** \- commands, analysis, export, pipeline separated. Tests could target modules instead of a god file.

**Commands:**

| Command | When to use                               | Output                            |
| ------- | ----------------------------------------- | --------------------------------- |
| analyze | PR timeline / person rollups for a window | TSV under analysis-results/       |
| export  | Regenerate Excel from cached run          | .xlsx via openpyxl optional group |
| run     | Full pipeline - fetch, analyze, export    | Run logs + artifacts              |

Entry point as contract:

```python
import click

@click.group()
@click.version_option("2.0.0")
def cli():
    """Engineering metrics - analyze, export, run."""

@cli.command()
@click.option("--since", required=True, help="Half-open window start (ISO).")
@click.option("--until", required=True, help="Half-open window end (ISO).")
def analyze(since: str, until: str):
    """PR timeline + person rollups for [since, until)."""
    ...
```

**Version pin (`2.0.0`)** \- signals contract to consumers. **Legacy wrapper** kept `github_pr_timeline_report.py` forwarding to `analyze` for one release cycle.

**README as contract** \- foreshadow [article 10](./10-readme-as-contract.md). `--help` before new metrics.

The named pattern:

> **Script → product threshold** \- modular CLI, version pin, `--help` before new metrics when a second team depends on you.

---

## 4\. What broke / lessons

Refactor day is expensive - batch breaking changes when dependents are few. I waited until three managers depended on the script; I should have named an owner at two.

The afternoon of **2026-06-01** also shipped wrong person-summary metrics - three correction commits by 10:52 (article 09). Productizing without definitional discipline just scales bad numbers faster.

---

## 5\. What I'd do as a lead

1. **Name an owner when the second team asks for the report.** Not when the fifth team complains.
2. **Invest in `--help` and README before new metrics.** Columns need definitions before staff meeting.
3. **Keep a legacy entry point for one release cycle.** Forks die slower than you hope.

---

### Further reading

- [An 857-line honesty machine](./03-pr-timeline-script.md) \- `d52975b` · 2026-04-10
- [Three wrong metrics same morning](./09-three-wrong-metrics.md) \- later in series
- github-analysis: commit `9d47215` · 2026-06-01 · `docs/architecture.md`

---

![Iheatu Chris Wogu](https://avatars.githubusercontent.com/u/3457705?s=176&v=4)

## About the author

**Iheatu Chris Wogu** is an engineering manager focused on launch programs, honest engineering metrics, and **engineering-led, agent-accelerated** delivery - researching where work queues up when agents widen dev output, then building proof, gates, and measurement that scale.

Field notes live on [First Context](https://contextfirst.blog/). Values treatise: [engineering manager values](https://contextfirst.blog/engineering-manager-values/).

**LinkedIn:** [linkedin.com/in/iheatu-chris-wogu](https://www.linkedin.com/in/iheatu-chris-wogu/?ref=contextfirst.blog)