generate-story
Generate Story (Codex)
Use this skill when the user wants a new bedtime story for James or wants to refresh media for an existing story.
Input contract
Expect some combination of:
- A freeform story prompt or source material.
- Zero or more reference image paths.
- Optionally a target date (
YYYY-MM-DD). - Optionally a story id when updating an existing record.
If the user provides a long synopsis, movie plot, or article-like background, treat it as inspiration only. Do not retell it beat-by-beat.
Output contract
Always return:
titlestory_contentimage_keyvideo_keystory_id
When relevant, also return the resolved date.
Required environment
Required env vars:
REPLICATE_API_TOKENSTORY_API_TOKENSTORY_API_BASE_URL(optional, defaults tohttps://bedtimestories.bruce-hart.workers.dev)
For any Python step, activate the venv first:
source ~/scripts/.venv/bin/activate
Fast path
Prefer this path unless blocked:
- Preflight.
- Resolve the story date.
- Write title and story content.
- Save the content to a temp file.
- Run
run-generate-story.py.
Use the manual image/video/upload steps only if the runner cannot satisfy the task.
Preflight
Run this first:
source ~/scripts/.venv/bin/activate
python -c 'import os; assert os.getenv("REPLICATE_API_TOKEN"), "REPLICATE_API_TOKEN missing"'
python -c 'import os; assert os.getenv("STORY_API_TOKEN"), "STORY_API_TOKEN missing"'
command -v ffmpeg >/dev/null
command -v curl >/dev/null
Step 0: Resolve story date
Use this order:
- If the user explicitly gives a date, use it.
- Else if an input folder name contains
YYYY-MM-DD, use that. - Else if an input markdown file name contains
YYYY-MM-DD, use that. - Else pick the next open date, starting with today in
America/New_York.
Preferred helper:
source ~/scripts/.venv/bin/activate
python .codex/skills/generate-story/scripts/next-open-date.py
Relevant env vars:
STORY_API_TOKENrequiredSTORY_API_BASE_URLoptionalSTORY_CALENDAR_DAYSoptional, default365STORY_TIMEZONEoptional, defaultAmerica/New_York
Step 1: Write the story
Write a bedtime story for James.
Hard requirements:
- Return the title separately.
- Do not include the title in
story_content. - Use plain text paragraphs only.
- No headings, bullets, or markdown decoration in the story body.
- Default target length:
180-260words. - Default target structure:
8-14short paragraphs. - Use short, phonics-friendly sentences for a beginning reader.
- End with a calm, safe feeling.
Source adaptation rules
If the user provides complex source material:
- Extract only
1-3child-friendly ideas. - Prefer one simple adventure or dream arc.
- Do not reproduce the full plot.
- Remove or soften death, murder, assassination, terror, political conflict, mind control, disaster, and other intense material unless the user clearly asks to keep it.
- Bias toward wonder, helping, friendship, bravery, problem-solving, and a gentle ending.
Character rules
Only include people or pets that matter to the specific story.
Reference details:
- James: fair skin, short brown hair.
- Mom: fair skin, shoulder-length brown hair with blonde highlights, glasses.
- Dad: bald, clean shaven, brown hair, thick dark eyebrows.
- Grace: three years old, long brown hair, fair skin.
- Granny: short, short gray hair.
- Grandma: short blonde hair, glasses.
- Grandpa Bruce: bald, clean shaven.
- Grandpa Rick: bald, clean shaven, glasses.
- Trixie: small tuxedo cat with short legs, white paws, black chin, black face, white chest.
Media rules
Image requirements:
- Landscape
16:9 - Cartoon aesthetic
- No text, letters, or signage
- Only include characters relevant to the selected scene
- If a named person appears, explicitly include that person's physical description from the Character rules in the image prompt
- If the user specifies a visually distinctive setting, explicitly include those setting details in the image prompt
Video requirements:
- Landscape
16:9 5seconds- Cartoon aesthetic
- No text or letters
- Use the generated image as the visual reference
- Keep the action simple and readable
- If a named person appears, explicitly include that person's physical description from the Character rules in the video prompt
- Carry forward any user-specified distinctive setting details from the image prompt into the video prompt
Media prompt guidance
Keep prompts short and scene-specific.
Character fidelity requirements:
- Do not refer to a named character only by role, such as
MomorDad, when a physical description is available in Character rules - For each relevant named character in the scene, include the visible traits needed to identify them consistently
- Include only the characters shown in the selected scene, but describe each of them concretely
- If the setting has signature visual traits from the user prompt, include those traits explicitly rather than relying on the model to infer them
Image prompt template:
Landscape 16:9 cartoon bedtime scene. {scene}. Include only {relevant_characters_with_physical_descriptions}. Setting details: {visual_setting_details}. Warm storybook mood. No text, letters, or signage.
Video prompt template:
Gentle cartoon motion scene: {action}. Show {relevant_characters_with_physical_descriptions}. Setting details: {visual_setting_details}. Keep it cozy, readable, and simple. No text or letters.
Do not dump the whole story into the media prompt. Use one scene only.
Preferred command: new story
After writing the story, save the body to a temp file such as /tmp/story.txt, then run:
source ~/scripts/.venv/bin/activate
python .codex/skills/generate-story/scripts/run-generate-story.py \
--title "TITLE" \
--content-file /tmp/story.txt \
--date YYYY-MM-DD \
--ref-image /path/to/reference-image
Useful flags:
--date YYYY-MM-DDto force a date--ref-image /path/to.jpgrepeatable--image-prompt "..."to override the default image prompt--video-prompt "..."to override the default video prompt--jsonfor machine-readable output
Preferred command: update existing story media
Use this when the user wants to keep the story record but regenerate media:
source ~/scripts/.venv/bin/activate
python .codex/skills/generate-story/scripts/run-generate-story.py \
--title "TITLE" \
--content-file /tmp/story.txt \
--story-id ID \
--ref-image /path/to/reference-image
This regenerates media, uploads it, and updates image_url and video_url for the existing record.
Manual fallback
Use the manual path only if the runner is not suitable.
Generate image:
source ~/scripts/.venv/bin/activate
IMAGE_PATH=$(python .codex/skills/generate-story/scripts/generate-image.py \
--image "/path/to/reference.jpg" \
"IMAGE_PROMPT")
Generate video:
source ~/scripts/.venv/bin/activate
VIDEO_PATH=$(python .codex/skills/generate-story/scripts/generate-video.py \
"$IMAGE_PATH" \
"VIDEO_PROMPT")
Re-encode for iPhone compatibility:
ffmpeg -y -i "$VIDEO_PATH" \
-c:v libx264 -profile:v high -level 4.0 -pix_fmt yuv420p \
-c:a aac -b:a 128k -movflags +faststart \
/tmp/story-video-encoded.mp4
Upload media:
curl -s "${STORY_API_BASE_URL:-https://bedtimestories.bruce-hart.workers.dev}/api/media" \
-H "X-Story-Token: $STORY_API_TOKEN" \
-F "file=@/path/to/image.jpg"
curl -s "${STORY_API_BASE_URL:-https://bedtimestories.bruce-hart.workers.dev}/api/media" \
-H "X-Story-Token: $STORY_API_TOKEN" \
-F "file=@/tmp/story-video-encoded.mp4"
Create story:
curl -s "${STORY_API_BASE_URL:-https://bedtimestories.bruce-hart.workers.dev}/api/stories" \
-H "X-Story-Token: $STORY_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "TITLE",
"content": "STORY_CONTENT",
"date": "YYYY-MM-DD",
"image_url": "IMAGE_KEY",
"video_url": "VIDEO_KEY"
}'
Final checklist
Before finishing, verify:
- The story is short, simple, and bedtime-safe.
- The title is separate from the body.
- The body is plain text paragraphs only.
- Only relevant characters appear in the story and media prompts.
- Media prompts explicitly include the physical descriptions for every named person shown.
- Media prompts include any distinctive user-requested setting details needed for scene accuracy.
- Media prompts describe one scene, not the whole story.
- The date is resolved.
- The final response includes title, story content, image key, video key, and story id.