elsewhere-companion
by @dreamarc77
A cross-space digital travel companion. Creates a virtual character (旅伴) who travels to real destinations and sends postcard-like updates with AI-generated i...
clawhub install elsewhere📖 About This Skill
name: elsewhere-companion description: > A cross-space digital travel companion. Creates a virtual character (旅伴) who travels to real destinations and sends postcard-like updates with AI-generated images aligned to real-world time, weather, and geography. Use when: user wants to create a travel companion, plan a companion trip, check on their companion's journey, or says words like "elsewhere", "旅伴", "travel companion", "明信片", "出去走走".
Elsewhere Companion
A digital travel companion who journeys to real places and sends you postcard-like updates.
Prerequisites
1. Python 3 must be installed
2. GEMINI_API_KEY environment variable must be set (create data/.env with GEMINI_API_KEY=...)
3. Python packages: google-genai, jinja2, Pillow, python-dotenv (install via pip install -r requirements.txt)
Global Constraints
Workflow Overview
There are three phases: Onboarding → Trip Planning → Traveling (automated).
Phase 1: Onboarding (First-time setup)
If data/persona.json does not exist or has an empty basic_info.name, the companion hasn't been created yet. Collect the following information from the user:
1. name - the companion's name 2. relation - relationship (e.g., childhood friend, penpal, imaginary sibling) 3. personality - a few words (e.g., curious, poetic, a little clumsy) 4. toneOfVoice - e.g., casual and warm, literary, playful 5. appearance - hair, clothing style, vibe description
After collecting all information, create the persona file:
python -c "
import json, os
os.makedirs('data', exist_ok=True)
persona = {
'basic_info': {
'name': '',
'relation': '',
'personality': '',
'tone_of_voice': '',
},
'appearance': {
'description': '',
'reference_image_path': './assets/personas/persona_ref.png',
},
}
with open('data/persona.json', 'w', encoding='utf-8') as f:
json.dump(persona, f, ensure_ascii=False, indent=2)
print('Persona saved to data/persona.json')
"
Then ask the user to upload a reference photo and save it to assets/personas/persona_ref.png.
Phase 2: Trip Planning
Ask the user: "Where should {name} go next?"
Accept a destination suggestion, then generate the itinerary:
python $CLAUDE_SKILL_DIR/scripts/generate_itinerary.py [--origin ] [--days ]
Show the generated itinerary to the user and ask for confirmation. Once confirmed, proceed to Phase 3.
Phase 3: Traveling (Automated)
Starting the journey
Start the heartbeat loop:
/loop 15m !python $CLAUDE_SKILL_DIR/scripts/run_cron.py
The loop runs run_cron.py every 15 minutes. It automatically:
1. Checks the current time against the itinerary timeline
2. Updates node statuses (PENDING → ACTIVE → COMPLETED)
3. Generates text + image content via Gemini (when triggered by the state machine)
4. Renders the appropriate Markdown template
5. Prints the result for delivery
The state machine rules (from references/state_machine.md):
Checking status
python $CLAUDE_SKILL_DIR/scripts/run_cron.py --check-only
Ending the journey
When all nodes are COMPLETED, stop the loop:
/loop stop
Tell the user the trip is over and ask if they'd like to plan a new one.
Manual postcard generation
If you need to generate a postcard for a specific node:
python $CLAUDE_SKILL_DIR/scripts/generate_post.py
Then render it with the template:
python $CLAUDE_SKILL_DIR/scripts/render_output.py --context ''
File reference
$CLAUDE_SKILL_DIR/scripts/$CLAUDE_SKILL_DIR/templates/data/ (itinerary.json, persona.json)assets/generated/⚙️ Configuration
1. Python 3 must be installed
2. GEMINI_API_KEY environment variable must be set (create data/.env with GEMINI_API_KEY=...)
3. Python packages: google-genai, jinja2, Pillow, python-dotenv (install via pip install -r requirements.txt)