Skip to content

Commit f70bf89

Browse files
benvinegarclaude
andauthored
feat: improve startup header and trim dead config (#7)
- discover skills under src/ dynamically instead of hardcoding the list, so new skills appear in the startup header automatically - show analyzed episodes from dist/analysis/ in the header so returning users can see what already exists - remove the [outputs], [transcription], and [video_scan] sections from podguy.example.toml (no code reads them) and document which sections are read by code vs. consumed by the agent as prose Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 37d90a0 commit f70bf89

4 files changed

Lines changed: 46 additions & 23 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ All notable user-visible changes to this project are documented in this file.
1111

1212
### Changed
1313

14+
- Discover skills dynamically in the startup header and show analyzed episodes from `dist/analysis/`, so returning users can see what already exists.
15+
- Remove the unused `[outputs]`, `[transcription]`, and `[video_scan]` sections from `podguy.example.toml`; document which sections are read by code vs. by the agent.
16+
1417
### Fixed
1518

1619
- Standardize the chapters artifact on `dist/analysis/<slug>/chapters.md` so the chapters and YouTube publish workflows agree.

podguy.example.toml

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
# Copy this file to podguy.toml and customize it for your show.
2+
#
3+
# The top-level fields are a show profile read by pi as context (prose, not
4+
# strict config). The named sections below are read by code:
5+
# [youtube] -> scripts/youtube_publish.py
26

37
show_name = "My Podcast"
48
show_slug = "my-podcast"
@@ -9,22 +13,6 @@ audience = "listeners interested in the episode topic"
913
chapter_style = "concise, listener-friendly chapters"
1014
preferred_review = "quick_pass"
1115

12-
[outputs]
13-
chapters = true
14-
clips = true
15-
cuts = true
16-
show_notes = true
17-
quotes = true
18-
proper_nouns = true
19-
20-
[transcription]
21-
preferred_backend = "auto"
22-
preferred_model = ""
23-
24-
[video_scan]
25-
enabled = true
26-
sample_interval_seconds = 0.5
27-
2816
[youtube]
2917
# Defaults for scripts/youtube_publish.py; flags override these.
3018
default_privacy = "private"

src/podguy-post-production/SKILL.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ Use profile fields such as:
3535
- `audience`
3636
- `chapter_style`
3737
- `preferred_review`
38-
- `[outputs]` toggles
3938

4039
Do not assume a specific show, hosts, audience, tone, domain, or episode naming pattern unless the user or profile provides it.
4140

src/podguy-startup.ts

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { existsSync, readFileSync } from "node:fs";
1+
import { existsSync, readFileSync, readdirSync } from "node:fs";
22
import { homedir } from "node:os";
33
import { relative, resolve } from "node:path";
44
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
@@ -22,6 +22,35 @@ function toDisplayPath(filePath: string): string {
2222
return normalized;
2323
}
2424

25+
function discoverSkillPaths(): string[] {
26+
// The launcher loads every skill under src/; discover them the same way so
27+
// new skills show up here without editing this list.
28+
const skillsRoot = resolve(cwd, "src");
29+
if (!existsSync(skillsRoot)) return [];
30+
try {
31+
return readdirSync(skillsRoot, { withFileTypes: true })
32+
.filter((entry) => entry.isDirectory())
33+
.map((entry) => resolve(skillsRoot, entry.name, "SKILL.md"))
34+
.filter((path) => existsSync(path))
35+
.sort();
36+
} catch {
37+
return [];
38+
}
39+
}
40+
41+
function analyzedEpisodes(): string[] {
42+
const analysisRoot = resolve(cwd, "dist/analysis");
43+
if (!existsSync(analysisRoot)) return [];
44+
try {
45+
return readdirSync(analysisRoot, { withFileTypes: true })
46+
.filter((entry) => entry.isDirectory())
47+
.map((entry) => entry.name)
48+
.sort();
49+
} catch {
50+
return [];
51+
}
52+
}
53+
2554
function readProfileSummary(): string | undefined {
2655
for (const profilePath of [resolve(cwd, "podguy.toml"), resolve(cwd, "podcast.toml")]) {
2756
if (!existsSync(profilePath)) continue;
@@ -65,11 +94,7 @@ export default function podguyStartupExtension(pi: ExtensionAPI) {
6594

6695
const projectAgents = resolve(cwd, "AGENTS.md");
6796
const userAgents = resolve(home, ".pi/agent/AGENTS.md");
68-
const skillPaths = [
69-
resolve(cwd, "src/podguy-post-production/SKILL.md"),
70-
resolve(cwd, "src/podguy-clip-cutter/SKILL.md"),
71-
resolve(cwd, "src/podguy-youtube-publisher/SKILL.md"),
72-
];
97+
const skillPaths = discoverSkillPaths();
7398
const promptsPath = resolve(cwd, "prompts");
7499
const extensionPath = resolve(cwd, "src/podguy-startup.ts");
75100
const profilePath = [resolve(cwd, "podguy.toml"), resolve(cwd, "podcast.toml")].find(
@@ -103,6 +128,13 @@ export default function podguyStartupExtension(pi: ExtensionAPI) {
103128
: [];
104129

105130
const profileSummary = readProfileSummary();
131+
const episodes = analyzedEpisodes();
132+
const episodesSummary =
133+
episodes.length === 0
134+
? "no episodes analyzed yet"
135+
: episodes.length <= 6
136+
? `episodes analyzed: ${episodes.join(", ")}`
137+
: `episodes analyzed: ${episodes.slice(0, 6).join(", ")} (+${episodes.length - 6} more)`;
106138

107139
return [
108140
accent(" __ "),
@@ -113,6 +145,7 @@ export default function podguyStartupExtension(pi: ExtensionAPI) {
113145
accent("/_/ /____/ /____/"),
114146
muted(" Podcast post-production"),
115147
dim(profileSummary ? ` profile: ${profileSummary}` : " no podguy.toml profile yet"),
148+
dim(` ${episodesSummary}`),
116149
"",
117150
...formatSection(theme, "Context", contextItems),
118151
...formatSection(theme, "Profile", profileItems),

0 commit comments

Comments
 (0)