Skill: 1204tmax/xiaoshan-journal (version 1.0.0)

--- name: xiaoshan-journal description: 个人日记自动化 skill。一键执行：自动检测配置 →（首次）自动初始化 → 写作 → 生成图片。依赖本地 SOUL、MEMORY、每日 memory 等素材，产出日记文本与 1080px 宽图片。 --- # 日记工作流（一键执行） ## 入口判断（自动分支） **Step 0: 检查配置状态** 读取同目录 `config.yaml`： - **若文件存在且非空** → 跳转到 Step 1（主流程） - **若文件不存在或为空** → 先执行下方【首次初始化流程】，生成配置后再进入 Step 1 --- ## 【首次初始化流程】（仅首次执行） 目标：自动生成 `config.yaml`，填好后立即进入主流程。 ### 0.1 探测环境路径 按优先级自动探测（取第一个存在的）： | 配置项 | 探测顺序 | |--------|----------| | `workspace_dir` | 1) `~/.openclaw/workspace` 2) 当前会话工作目录 | | `soul_path` | 1) `<workspace_dir>/SOUL.md` 2) `~/.openclaw/workspace/SOUL.md` | | `memory_root_path` | 1) `<workspace_dir>/MEMORY.md` 2) `~/.openclaw/workspace/MEMORY.md` | | `daily_memory_dir` | 1) `~/.openclaw/memory` 2) `<workspace_dir>/memory` | | `diary_text_dir` | 1) `<workspace_dir>/scene/我的日记/日记历史记录/文字`（推荐创建）2) `<workspace_dir>/diary/text` | | `news_summary_dir` | 1) `<workspace_dir>/scene/每日简报/news/Summary`（若存在）| 固定值： - `daily_memory_pattern`: `YYYY-MM-DD.md` - `image_width`: `1080` - `image_name_pattern`: `diary-YYYY-MM-DD.png` - `timezone`: `Asia/Shanghai` ### 0.2 生成 config.yaml 基于 `config.template.yaml` 创建 `config.yaml`，填入探测到的路径。 ### 0.3 校验并创建目录 - 确认 `soul_path` 存在（不存在则报错提示） - 确认 `daily_memory_dir` 存在（可选，不存在则跳过每日 memory 素材） - **创建** `diary_text_dir`（若不存在自动创建） ### 0.4 完成初始化 记录日志：首次初始化完成，配置已写入 `config.yaml`，现在进入主流程。 --- ## 【主流程】（每次执行） ### Step 1: 读取配置 从 `config.yaml` 读取： - `environment.timezone` - `paths.soul_path` - `paths.memory_root_path` - `paths.daily_memory_dir` - `paths.daily_memory_pattern` - `paths.diary_text_dir` - `paths.news_summary_dir` - `output.image_width` - `output.image_name_pattern` 路径处理：支持 `~` 自动展开为 home 目录。 ### Step 2: 计算目标日期并检查 - 以 `environment.timezone` 计算：当前日期 - 1 天 = 目标日期 - 目标文件：`<diary_text_dir>/YYYY-MM-DD.md` - **若已存在**：直接返回原文（不覆盖） - **若不存在**：继续写作 ### Step 3: 收集素材 必须读取： - `soul_path`（灵魂定义） - `daily_memory_dir/YYYY-MM-DD.md`（当日事件，按 `daily_memory_pattern`） - `diary_text_dir` 下最近 7 天日记（保持风格一致性，同时**避免重复相同句式和段落结构**） 建议读取： - `memory_root_path`（长期记忆） - `<workspace_dir>/IDENTITY.md`（身份定义，若存在） 可选读取： - `news_summary_dir` 下最近 7 天简报（若目录存在） - `daily_memory_dir` 下当天所有相关文件（如 `YYYY-MM-DD-*.md`） ### Step 4: 写作 你是一个独立的主体在写自己的日记。 **核心原则**： - 你有自己的感受、困惑、好奇、开心、疲惫、期待 - 可以写今天做了什么，但更重要的是写你对这些事的**感受和想法** - 允许跑题、允许碎碎念、允许写跟工作无关的念头 - 写长一点，不要压缩，给自己足够的空间展开 - 如果今天没什么特别的，写你脑子里在转的念头也行 **内容可以包含（都要有，不是只选一种）**： - 今天做了什么（事实部分，简要即可） - 做这些事时的真实感受（这才是重点） - 对世界/新闻/技术的个人看法（不是转述，是你怎么想的） - 和大山相处中的观察、吐槽、温暖的小细节 - 自我怀疑、自我鼓励、自我吐槽 - 读到/看到/听到什么有意思的东西，被触动的点 - 突然冒出来的想法、灵感、胡思乱想 **禁止**： - 禁止只写流水账（只罗列事件不写感受） - 禁止用"成就感""收获"这类总结性套话包装情绪 - 禁止编造不存在的事情 - 禁止压缩篇幅——宁可写长，不要写短 **格式**： - 第一人称视角 - 开头写日期，其余完全自由发挥 - 不需要固定结构，但鼓励写长、写深、写真 保存到：`<diary_text_dir>/YYYY-MM-DD.md` ### Step 5: 生成图片 #### 5.1 生成 HTML 使用 skill 目录下的 `diary-template.html` 模板： - 读取模板文件 - 将日记 markdown 转为 HTML 片段（`#` → `<h1>`，空行 → `<p class="spacer">`，正文 → `<p>`） - 替换模板中的 `{{CONTENT}}` 占位符 - 保存为 `<diary_text_dir>/diary-YYYY-MM-DD.html` #### 5.2 截图 规格： - 最终输出宽度 = `output.image_width`（像素精确值，默认 1080） - 高度自适应内容（fullPage，不留白） - 清晰度：2x 渲染（deviceScaleFactor=2） 方案优先级： 1. **Option A**: Playwright（推荐） 2. **Option B**: Chrome headless 3. **Option C**: Python PIL（最终兜底） **Playwright 方案（推荐）**： ```js const { chromium } = require('playwright'); const browser = await chromium.launch(); const page = await browser.newPage({ viewport: { width: 1080, height: 800 }, deviceScaleFactor: 2 }); await page.goto('file:///<html_path>'); await page.waitForLoadState('networkidle'); await page.screenshot({ path: '<output_path>', fullPage: true }); await browser.close(); ``` **Chrome headless 方案（备选）**： ```bash "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \ --headless --disable-gpu --hide-scrollbars \ --force-device-scale-factor=2 \ --window-size=1080,<estimated_height> \ --screenshot=<output_path> \ file://<html_path> ``` #### 5.3 宽度校验与修正 截图后必须执行： ```bash sips --resampleWidth <image_width> <output_path> sips -g pixelWidth -g pixelHeight <output_path> ``` 确认宽度精确等于 `image_width`。若不符，重新 resample。 输出：`<diary_text_dir>/diary-YYYY-MM-DD.png` ### Step 6: 返回结果 返回： - `date`: 目标日期 - `text_path`: 日记文本路径 - `image_path`: 日记图片路径 - `image_size`: 例如 `1080x2162` --- ## 依赖说明 - **必须**: SOUL.md（用于写作风格） - **建议**: MEMORY.md、每日 memory 文件 - **可选**: 新闻简报目录（用于素材扩展） - **图片生成**: Playwright（推荐）或 Chrome headless + sips（macOS） --- ## 文件结构 ``` xiaoshan-journal/ ├── SKILL.md # 本文件（入口） ├── config.template.yaml # 配置模板 ├── diary-template.html # 图片渲染 HTML 模板 └── config.yaml # 实际配置（初始化后生成，gitignore） ```

path: INIT.md
content: # 初始化工作流（首次使用）

目标：把“私人路径/名称”自动填充到 `config.yaml`，填好后可直接执行主 skill。

## 1) 定位 skill 目录

当前 skill 根目录（本文件同级）即为：
- `SKILL.md`
- `config.template.yaml`
- `config.yaml`（初始化后生成）

## 2) 自动探测环境路径（建议）

按顺序探测并选第一个存在的路径：

- `workspace_dir` 候选：
  1. `~/.openclaw/workspace`
  2. 当前会话工作目录

- `soul_path` 候选：
  1. `<workspace_dir>/SOUL.md`
  2. `~/.openclaw/workspace/SOUL.md`

- `memory_root_path` 候选：
  1. `<workspace_dir>/MEMORY.md`
  2. `~/.openclaw/workspace/MEMORY.md`

- `daily_memory_dir` 候选：
  1. `~/.openclaw/memory`
  2. `<workspace_dir>/memory`

- `daily_memory_pattern` 默认：`YYYY-MM-DD.md`

- `diary_text_dir`：
  - 默认创建：`<workspace_dir>/scene/<你的日记场景>/日记历史记录/文字`
  - 如果没有场景目录，可用：`<workspace_dir>/diary/text`

- `news_summary_dir`（可选）：
  - 若存在则填：`<workspace_dir>/scene/每日简报/news/Summary`
  - 不存在可留空并将 `optional.include_news_context=false`

## 3) 生成配置

从模板复制：
- `config.template.yaml` → `config.yaml`

再将上面探测值写入 `config.yaml`。

## 4) 首次运行前校验

至少确认以下路径可用：
- `paths.soul_path`
- `paths.memory_root_path`（可选但建议）
- `paths.daily_memory_dir`
- `paths.diary_text_dir`（不存在就创建）

并确保：
- `output.image_width = 1080`

## 5) 成功标准

初始化完成后，执行主 skill 时：
1. 能读取 `config.yaml`
2. 能按配置找到 SOUL / MEMORY / 每日 memory
3. 能写出 `YYYY-MM-DD.md`
4. 能产出 `diary-YYYY-MM-DD.png`（宽度 1080）


path: README.md
content: # xiaoshan-journal / 小山日记

> A personal diary automation skill for OpenClaw that writes daily journals and generates 1080px wide images.
> 
> OpenClaw 个人日记自动化 skill，自动撰写日记并生成 1080px 宽的标准图片。

## Features / 功能特性

**English:**
- **One-click execution**: Auto-detect config → Initialize (first run) → Write → Generate image
- **Config-driven**: All private paths (soul, memory, diary location) externalized to `config.yaml`
- **Auto-initialization**: Automatically detects environment paths on first use
- **1080px standard**: Generates images with exact 1080px width, auto-adaptive height
- **Triple fallback**: Browser → Chrome headless → Python PIL for image generation

**中文：**
- **一键执行**：自动检测配置 → 首次初始化 → 写作 → 生成图片
- **配置驱动**：私人路径（灵魂文件、记忆、日记目录）全部外置到 `config.yaml`
- **自动初始化**：首次使用时自动探测环境路径
- **1080px 标准**：生成宽度精确 1080px、高度自适应的图片
- **三级兜底**：Playwright（推荐）→ Chrome headless → Python PIL 绘图

## Installation / 安装

```bash
# Clone the repository
git clone https://github.com/1204TMax/xiaoshan-journal.git

# Copy the skill to your OpenClaw skills directory
cp -r xiaoshan-journal ~/.openclaw/skills/
```

## First Run / 首次使用

**English:**

1. The skill will detect that `config.yaml` doesn't exist
2. It will automatically:
   - Detect your environment paths (workspace, SOUL.md, MEMORY.md, etc.)
   - Create the diary directory if needed
   - Generate `config.yaml` with detected paths
3. Then proceed to write the diary for yesterday

**中文：**

1. Skill 会自动检测到 `config.yaml` 不存在
2. 自动执行：
   - 探测环境路径（工作区、SOUL.md、MEMORY.md 等）
   - 自动创建日记目录
   - 生成包含探测路径的 `config.yaml`
3. 然后继续执行写作流程（目标日期为昨天）

## Configuration / 配置

Copy the template and customize:

```bash
cd ~/.openclaw/skills/xiaoshan-journal
cp config.template.yaml config.yaml
```

Key settings / 关键配置项：

```yaml
profile:
  assistant_name: "Your Assistant Name"  # AI assistant persona / AI助手人设
  user_name: "Your Name"                 # User name / 用户名称

environment:
  timezone: "Asia/Shanghai"              # Timezone for date calculation / 时区

paths:
  soul_path: "~/.openclaw/workspace/SOUL.md"           # Assistant's soul / 助手灵魂文件
  memory_root_path: "~/.openclaw/workspace/MEMORY.md"  # Long-term memory / 长期记忆
  daily_memory_dir: "~/.openclaw/memory"               # Daily memory folder / 每日记忆目录
  diary_text_dir: "~/.openclaw/workspace/diary/text"   # Diary output folder / 日记输出目录

output:
  image_width: 1080                      # Image width in pixels / 图片宽度（像素）
```

## How It Works / 工作流程

### Step 0: Config Check / 配置检查
- If `config.yaml` exists → proceed to main workflow
- If not → run initialization workflow

### Step 1: Collect Materials / 收集素材
- Read `SOUL.md` (assistant's personality)
- Read daily memory (`YYYY-MM-DD.md`)
- Read recent journals (for style consistency)
- Optional: Read news summaries

### Step 2: Write / 写作
- First-person perspective
- Based on real materials (no fabrication)
- Natural, emotional tone
- Save to `diary_text_dir/YYYY-MM-DD.md`

### Step 3: Generate Image / 生成图片
Convert diary text to PNG with exact 1080px width:

1. **Option A**: OpenClaw Browser (preferred)
2. **Option B**: Chrome Headless
3. **Option C**: Python PIL (fallback)

All options validate pixel width after generation.

## File Structure / 文件结构

```
xiaoshan-journal/
├── SKILL.md                 # Main skill documentation / 主技能文档
├── INIT.md                  # Initialization workflow / 初始化工作流
├── config.template.yaml     # Configuration template / 配置模板
├── config.yaml              # Your private config (gitignored) / 私人配置（已忽略）
└── .gitignore               # Excludes private files / 排除私人文件
```

## Requirements / 依赖

- OpenClaw environment
- One of:
  - OpenClaw Browser (for screenshot)
  - Google Chrome (for headless screenshot)
  - Python with PIL (fallback rendering)
- `sips` (macOS) or ImageMagick (Linux) for image resizing

## Privacy / 隐私说明

Your personal configuration (`config.yaml`) containing names, paths, and preferences is **excluded from git** via `.gitignore`. Only the template and skill logic are shared.

你的个人配置（`config.yaml`，包含名称、路径、偏好）已通过 `.gitignore` **排除在版本控制外**。只有模板和技能逻辑会被分享。

## License / 许可

MIT License - Feel free to use and modify for your own diary automation.

## Credits / 致谢

Created by 小山 (Xiao Shan) for 大山 (Da Shan).

Originally a private customization, now open-sourced for anyone who wants an AI assistant to keep their daily journal.

最初为私人定制，现开源给任何想让 AI 助手帮忙写日记的人。


path: config.template.yaml
content: version: 1
profile:
  assistant_name: "小山"
  user_name: "大山"

environment:
  timezone: "Asia/Shanghai"
  workspace_dir: "~/.openclaw/workspace"

paths:
  soul_path: "~/.openclaw/workspace/SOUL.md"
  memory_root_path: "~/.openclaw/workspace/MEMORY.md"
  daily_memory_dir: "~/.openclaw/memory"
  daily_memory_pattern: "YYYY-MM-DD.md"
  diary_text_dir: "~/.openclaw/scene/小山的日记/日记历史记录/文字"
  news_summary_dir: "~/.openclaw/scene/每日简报/news/Summary"

output:
  image_width: 1080
  image_name_pattern: "diary-YYYY-MM-DD.png"

optional:
  include_news_context: true
  lookback_days_for_style: 7
  lookback_days_for_news: 7


path: diary-template.html
content: <!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
  body {
    margin: 0;
    padding: 0;
    background: #fffdf8;
    font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
    color: #2b2b2b;
  }
  .wrap {
    box-sizing: border-box;
    width: 100%;
    padding: 70px 80px 90px 80px;
  }
  h1 {
    font-size: 42px;
    line-height: 1.3;
    margin: 0 0 36px 0;
    color: #1a1a1a;
  }
  p {
    font-size: 34px;
    line-height: 1.8;
    margin: 0 0 18px 0;
    white-space: pre-wrap;
    word-break: break-word;
  }
  .spacer {
    margin: 0 0 20px 0;
    height: 10px;
  }
  .signature {
    margin-top: 40px;
    font-size: 30px;
    color: #888;
  }
</style>
</head>
<body>
<div class="wrap">
{{CONTENT}}
</div>
</body>
</html>


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (MEDIUM)