endurance-coach 1.0.2 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +2 -1
- package/README.md +49 -4
- package/dist/cli.js +11 -14
- package/dist/expander/expander.js +15 -2
- package/dist/templates/template.schema.d.ts +6 -0
- package/dist/templates/template.schema.js +3 -0
- package/dist/templates/template.types.d.ts +1 -1
- package/package.json +3 -3
- package/templates/plan-viewer.html +21 -21
- package/templates/strength/eccentric.yaml +77 -0
- package/templates/strength/light.yaml +60 -0
- package/templates/strength/power.yaml +81 -0
- package/templates/strength/runner.yaml +76 -0
- package/templates/strength/trail.yaml +83 -0
- package/templates/strength/triathlon.yaml +83 -0
- package/templates/swim/endurance.yaml +57 -0
- package/templates/swim/speed.yaml +74 -0
- package/templates/bike/CLAUDE.md +0 -7
- package/templates/brick/CLAUDE.md +0 -7
- package/templates/run/CLAUDE.md +0 -7
- package/templates/strength/CLAUDE.md +0 -7
- package/templates/swim/CLAUDE.md +0 -7
package/LICENSE.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2025 Felix Rieseberg
|
|
3
|
+
Original work Copyright (c) 2025 Felix Rieseberg
|
|
4
|
+
Modifications and independent development Copyright (c) 2025-2026 Shiva Prasad
|
|
4
5
|
|
|
5
6
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
7
|
of this software and associated documentation files (the "Software"), to deal
|
package/README.md
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
# Endurance Coach
|
|
2
2
|
|
|
3
|
-
Originally forked from Claude Coach.
|
|
4
|
-
This project is now independently maintained and has evolved with a different architecture and goals, focusing on agent-first, schema-driven endurance planning.
|
|
5
|
-
|
|
6
3
|
Endurance Coach allows you to use Claude (or any AI assistant) to create custom-tailored training programs for triathlons, marathons, and other endurance activities. Using a data-driven approach and principles from top training plans, the AI will create a training plan that's uniquely fit for you, your personal fitness, and the constraints you have in the next couple of weeks. Maybe you're recovering from an injury, maybe you're traveling and don't have access to a pool or track in a certain week - tell the AI about it and it'll create a plan that works for you.
|
|
7
4
|
|
|
8
5
|
The output is a beautiful training plan app that allows you to add, edit, or move workouts, mark them as complete, and update key training data like heart rate zones, LTHR, threshold paces, FTP, and others. Your data is kept locally in your browser.
|
|
@@ -92,6 +89,54 @@ In the next step, the AI will ask you about yourself, the event you're training
|
|
|
92
89
|
|
|
93
90
|
The AI will use this information to create a plan tailored to your current fitness level. The more detail you provide, the better your plan will be.
|
|
94
91
|
|
|
92
|
+
## Contributing
|
|
93
|
+
|
|
94
|
+
We welcome contributions from the community! Whether you want to add workout templates, improve the UI, fix bugs, or enhance documentation, your help is appreciated.
|
|
95
|
+
|
|
96
|
+
Please see our [CONTRIBUTING.md](CONTRIBUTING.md) for:
|
|
97
|
+
|
|
98
|
+
- Development setup instructions
|
|
99
|
+
- Coding standards and guidelines
|
|
100
|
+
- How to submit pull requests
|
|
101
|
+
- Areas where we need help
|
|
102
|
+
|
|
95
103
|
# About
|
|
96
104
|
|
|
97
|
-
|
|
105
|
+
## Lineage & Architectural Evolution
|
|
106
|
+
|
|
107
|
+
This project originated as a fork of [Claude Coach](https://github.com/felixrieseberg/claude-coach) by [Felix Rieseberg](https://felixrieseberg.com), but it is no longer a fork in any meaningful architectural or behavioral sense.
|
|
108
|
+
|
|
109
|
+
The original project relied on large language models generating full, deeply nested workout plans as verbose JSON based solely on plain-text instructions. This approach had no formal schema contract, no validation loop, and no way for an AI agent to detect or correct structural errors before downstream rendering. Failures were late, brittle, and required human intervention.
|
|
110
|
+
|
|
111
|
+
This project deliberately replaces that architecture.
|
|
112
|
+
|
|
113
|
+
### Key changes that make this an independent system:
|
|
114
|
+
|
|
115
|
+
**Contract-first design**
|
|
116
|
+
The system now exposes explicit machine-consumable schemas (via validation tooling) rather than relying on prose instructions. AI agents can validate outputs and receive structured error feedback before proceeding.
|
|
117
|
+
|
|
118
|
+
**Representation shift**
|
|
119
|
+
Workout plans are no longer generated as large raw JSON objects. Instead, the system defines a constrained domain-specific language composed of reusable workout templates. Plans are authored as concise YAML compositions of these templates, drastically reducing output size, entropy, and failure modes.
|
|
120
|
+
|
|
121
|
+
**Template-based composition**
|
|
122
|
+
The AI agent does not invent workout structure freely. It selects from a predefined, inspectable set of workout building blocks supplied by the tool, turning generation into constrained composition rather than unconstrained construction.
|
|
123
|
+
|
|
124
|
+
**Agent-first execution model**
|
|
125
|
+
The primary consumer is an AI agent, not a human. All commands are deterministic, side-effect explicit, and validation-first. Outputs are designed to support self-correction loops by the agent.
|
|
126
|
+
|
|
127
|
+
**Independent surface and identity**
|
|
128
|
+
The project has a new name, a new installation path, and a different public contract. It is no longer Claude-specific and is designed to be consumed by any AI agent or orchestration framework.
|
|
129
|
+
|
|
130
|
+
Because the core abstraction, data representation, validation model, target consumer, and public interface have all changed, this project should be treated as an independently evolved system that acknowledges its lineage but does not share the original architecture or assumptions.
|
|
131
|
+
|
|
132
|
+
## Disclaimer
|
|
133
|
+
|
|
134
|
+
Endurance Coach is an independent, open-source project. It is not made by, endorsed by, or affiliated with Anthropic, PBC. "Claude" is a trademark of Anthropic. This skill works with Claude and other AI assistants but is developed and maintained independently.
|
|
135
|
+
|
|
136
|
+
## Maintainer
|
|
137
|
+
|
|
138
|
+
Maintained by [Shiva Prasad](https://shiv19.com) · [@multishiv19](https://twitter.com/multishiv19)
|
|
139
|
+
|
|
140
|
+
## License
|
|
141
|
+
|
|
142
|
+
MIT License. Original work Copyright © 2025 Felix Rieseberg. Modifications and independent development Copyright © 2025-2026 Shiva Prasad.
|
package/dist/cli.js
CHANGED
|
@@ -218,8 +218,8 @@ Commands:
|
|
|
218
218
|
sync Sync activities from Strava
|
|
219
219
|
auth Get Strava authorization URL or exchange code for tokens
|
|
220
220
|
schema Print the YAML v2.0 plan format reference
|
|
221
|
-
validate <file> Validate a training plan
|
|
222
|
-
expand <file> Expand a compact YAML plan to full
|
|
221
|
+
validate <file> Validate a training plan (YAML recommended)
|
|
222
|
+
expand <file> Expand a compact YAML plan to full format
|
|
223
223
|
render <file> Render a training plan to HTML
|
|
224
224
|
templates List available workout templates
|
|
225
225
|
query <sql> Run a SQL query against the database
|
|
@@ -241,9 +241,6 @@ Sync Options:
|
|
|
241
241
|
--client-secret=SEC Strava API client secret (for OAuth flow)
|
|
242
242
|
--days=N Days of history to sync (default: 730)
|
|
243
243
|
|
|
244
|
-
Validate Options:
|
|
245
|
-
--compact Force compact plan validation (auto-detected for .yaml files)
|
|
246
|
-
|
|
247
244
|
Expand Options:
|
|
248
245
|
--output, -o FILE Output file (default: stdout)
|
|
249
246
|
--format json|yaml Output format (default: json)
|
|
@@ -261,7 +258,7 @@ Query Options:
|
|
|
261
258
|
|
|
262
259
|
Modify Options:
|
|
263
260
|
--backup, -b FILE Backup JSON file (exported from Settings)
|
|
264
|
-
--plan, -p FILE
|
|
261
|
+
--plan, -p FILE Expanded plan JSON file to modify
|
|
265
262
|
--output, -o FILE Output file (default: overwrites plan file)
|
|
266
263
|
|
|
267
264
|
Examples:
|
|
@@ -277,20 +274,20 @@ Examples:
|
|
|
277
274
|
# Get the YAML v2.0 format reference
|
|
278
275
|
npx endurance-coach schema
|
|
279
276
|
|
|
280
|
-
# Validate a
|
|
281
|
-
npx endurance-coach validate plan.
|
|
277
|
+
# Validate a compact YAML plan
|
|
278
|
+
npx endurance-coach validate plan.yaml
|
|
282
279
|
|
|
283
|
-
# Render a training plan to HTML
|
|
284
|
-
npx endurance-coach render plan.
|
|
280
|
+
# Render a training plan to HTML
|
|
281
|
+
npx endurance-coach render plan.yaml --output my-plan.html
|
|
285
282
|
|
|
286
283
|
# Query the database
|
|
287
284
|
npx endurance-coach query "SELECT * FROM weekly_volume LIMIT 5"
|
|
288
|
-
|
|
289
|
-
# Apply backup changes to
|
|
290
|
-
npx endurance-coach modify --backup backup.json --plan
|
|
285
|
+
|
|
286
|
+
# Apply backup changes to an expanded plan
|
|
287
|
+
npx endurance-coach modify --backup backup.json --plan expanded.json
|
|
291
288
|
|
|
292
289
|
# Save modified plan to a new file
|
|
293
|
-
npx endurance-coach modify -b backup.json -p
|
|
290
|
+
npx endurance-coach modify -b backup.json -p expanded.json -o modified.json
|
|
294
291
|
`);
|
|
295
292
|
}
|
|
296
293
|
// ============================================================================
|
|
@@ -9,6 +9,16 @@ import { calculateAthleteZones } from "./zones.js";
|
|
|
9
9
|
// ============================================================================
|
|
10
10
|
// Date Utilities
|
|
11
11
|
// ============================================================================
|
|
12
|
+
/**
|
|
13
|
+
* Parse an ISO date string (YYYY-MM-DD) as a local date, avoiding timezone issues.
|
|
14
|
+
* When you use `new Date("2025-02-16")`, it creates a UTC date which can shift
|
|
15
|
+
* to the previous day in timezones behind UTC. This function creates a date in
|
|
16
|
+
* local timezone.
|
|
17
|
+
*/
|
|
18
|
+
function parseLocalDate(dateStr) {
|
|
19
|
+
const [year, month, day] = dateStr.split("-").map(Number);
|
|
20
|
+
return new Date(year, month - 1, day);
|
|
21
|
+
}
|
|
12
22
|
/**
|
|
13
23
|
* Get the day of week name from a Date.
|
|
14
24
|
*/
|
|
@@ -20,7 +30,10 @@ function getDayOfWeekName(date) {
|
|
|
20
30
|
* Format a Date as ISO date string (YYYY-MM-DD).
|
|
21
31
|
*/
|
|
22
32
|
function formatDate(date) {
|
|
23
|
-
|
|
33
|
+
const year = date.getFullYear();
|
|
34
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
35
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
36
|
+
return `${year}-${month}-${day}`;
|
|
24
37
|
}
|
|
25
38
|
/**
|
|
26
39
|
* Add days to a date.
|
|
@@ -34,7 +47,7 @@ function addDays(date, days) {
|
|
|
34
47
|
* Calculate the start date of the plan from the event date and total weeks.
|
|
35
48
|
*/
|
|
36
49
|
function calculateStartDate(eventDate, totalWeeks, firstDayOfWeek) {
|
|
37
|
-
const event =
|
|
50
|
+
const event = parseLocalDate(eventDate);
|
|
38
51
|
// Go back totalWeeks * 7 days from event date
|
|
39
52
|
const start = addDays(event, -(totalWeeks * 7));
|
|
40
53
|
// Adjust to the first day of the week
|
|
@@ -33,12 +33,15 @@ export declare const WorkoutCategorySchema: z.ZodEnum<{
|
|
|
33
33
|
rest: "rest";
|
|
34
34
|
recovery: "recovery";
|
|
35
35
|
threshold: "threshold";
|
|
36
|
+
power: "power";
|
|
36
37
|
endurance: "endurance";
|
|
37
38
|
tempo: "tempo";
|
|
38
39
|
intervals: "intervals";
|
|
39
40
|
technique: "technique";
|
|
40
41
|
hills: "hills";
|
|
42
|
+
aerobic: "aerobic";
|
|
41
43
|
speed: "speed";
|
|
44
|
+
maintenance: "maintenance";
|
|
42
45
|
}>;
|
|
43
46
|
export declare const TemplateParamSchema: z.ZodObject<{
|
|
44
47
|
type: z.ZodEnum<{
|
|
@@ -264,12 +267,15 @@ export declare const WorkoutTemplateSchema: z.ZodObject<{
|
|
|
264
267
|
rest: "rest";
|
|
265
268
|
recovery: "recovery";
|
|
266
269
|
threshold: "threshold";
|
|
270
|
+
power: "power";
|
|
267
271
|
endurance: "endurance";
|
|
268
272
|
tempo: "tempo";
|
|
269
273
|
intervals: "intervals";
|
|
270
274
|
technique: "technique";
|
|
271
275
|
hills: "hills";
|
|
276
|
+
aerobic: "aerobic";
|
|
272
277
|
speed: "speed";
|
|
278
|
+
maintenance: "maintenance";
|
|
273
279
|
}>;
|
|
274
280
|
params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
275
281
|
type: z.ZodEnum<{
|
|
@@ -14,6 +14,7 @@ export const WorkoutCategorySchema = z.enum([
|
|
|
14
14
|
"rest",
|
|
15
15
|
"recovery",
|
|
16
16
|
"endurance",
|
|
17
|
+
"aerobic",
|
|
17
18
|
"tempo",
|
|
18
19
|
"threshold",
|
|
19
20
|
"intervals",
|
|
@@ -21,6 +22,8 @@ export const WorkoutCategorySchema = z.enum([
|
|
|
21
22
|
"hills",
|
|
22
23
|
"race",
|
|
23
24
|
"strength",
|
|
25
|
+
"power",
|
|
26
|
+
"maintenance",
|
|
24
27
|
"technique",
|
|
25
28
|
]);
|
|
26
29
|
// ============================================================================
|
|
@@ -67,7 +67,7 @@ export interface TemplateStructure {
|
|
|
67
67
|
/**
|
|
68
68
|
* Workout category for organization.
|
|
69
69
|
*/
|
|
70
|
-
export type WorkoutCategory = "rest" | "recovery" | "endurance" | "tempo" | "threshold" | "intervals" | "speed" | "hills" | "race" | "strength" | "technique";
|
|
70
|
+
export type WorkoutCategory = "rest" | "recovery" | "endurance" | "aerobic" | "tempo" | "threshold" | "intervals" | "speed" | "hills" | "race" | "strength" | "power" | "maintenance" | "technique";
|
|
71
71
|
/**
|
|
72
72
|
* A complete workout template.
|
|
73
73
|
*/
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "endurance-coach",
|
|
3
|
-
"version": "1.0
|
|
4
|
-
"author": "
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"author": "Shiva Prasad <sp@shiv19.com> (https://shiv19.com)",
|
|
5
5
|
"contributors": [
|
|
6
|
-
"
|
|
6
|
+
"Felix Rieseberg (https://felixrieseberg.com)"
|
|
7
7
|
],
|
|
8
8
|
"license": "MIT",
|
|
9
9
|
"type": "module",
|