开发者可上传 Agent 会话记录到 DEV 并嵌入文章,便于知识分享和学习交流。
作者现在可以将 AI 智能体会话记录上传到他们的 DEV 账户。这些记录可以被整理、切分、公开分享,以及嵌入到文章中。这是一项测试功能,我们正在积极寻求反馈!
每天,越来越多的人第一次开始创建软件。有些人有长期的开发者经历,有些人从未看过一行代码。在大多数情况下,他们使用相同的工具——AI 编程智能体。然而,随着这些工具变得无处不在,除了截图之外,以标准化方式分享工作流程和成果的方法却出人意料地少。每个工具都有自己的分享链接生成器,每个工具以不同的格式输出日志。虽然有一些新兴项目可以提供帮助,但它们通常作为独立工具存在,或不能以在 DEV 上有效运作的方式明确解决分享问题。
我们决定通过让你能够将记录上传到 DEV、自动将其解析为标准格式,并以自然融入技术写作的方式将完整或部分会话嵌入到文章中来解决这个问题。
目前,我们的解析器支持 Gemini CLI、Codex、Claude Code、Pi 和 GitHub Copilot CLI。如果你使用其他工具,我们鼓励你在 Forem 上开启 PR 或 Issue 来自己添加新的解析器,或者请求我们这样做。例如,你可以查看我们的 Gemini CLI 解析器如何工作的示例,在我们的 GitHub 提交中:https://github.com/forem/forem/commit/0230aa56c1b4e59480c1de95822824f62f95aaa4#diff-a096c013f50a6f14bf8c09ab7c693348b9b704adeb99517f6089a511d025daa0
这是我使用 Gemini CLI 为我的宠物豚鼠 Pearl 构建的一个示例应用的会话(在评论中有必要的照片)。
build me a simple web app to let my guinea pig tell me what food it wants
Clarifying Application Needs / Defining Food Selection UI / Mapping Out The App's Flow
我将构建一个充满活力、触摸友好的网络应用,名叫"Pui Pui Picker",专为豚鼠(及其主人)设计。
架构:使用 Vite 创建 React + TypeScript 项目。
设计:具有高对比度颜色和弹性动画的"大按钮"界面,使其引人入胜。
功能:食物网格:为 Hay、Carrots、Romaine 和 Bell Peppers 提供大卡片。Pui Pui 反馈:选择项目时的视觉和文本"wheeking"反馈。历史:一个小"Last Requested"日志,用于追踪豚鼠"选择"了什么。
食物网格:为 Hay、Carrots、Romaine 和 Bell Peppers 提供大卡片。
Pui Pui 反馈:选择项目时的视觉和文本"wheeking"反馈。
历史:一个小"Last Requested"日志,用于追踪豚鼠"选择"了什么。
样式:使用自定义 Vanilla CSS 实现精致、现代的外观,无需外部依赖。
这听起来像是一个很好的开始,适合你的豚鼠吗?或者我应该添加它们喜欢的具体零食?
我将从架构项目开始。
{
"command": "npm create vite@latest . -- --template react-ts && npm install",
"description": "Scaffolding the React TypeScript project using Vite and installing dependencies."
}
让我们比 Vite 和 React 更简单
Seeking Simplification for App / Constructing the index.html
我将创建一个单文件、充满活力和触摸友好的 HTML 应用,名叫"The Wheeky Menu"。它将使用大的彩色按钮和弹性动画——非常适合豚鼠的"输入"(或人类的手指)。
单文件:index.html 中的所有内容(HTML、CSS、JS)可以立即加载。
以豚鼠为中心的用户界面:大交互区域:易于点击的 Hay、Carrots、Peppers 和 Lettuce 卡片。视觉反馈:点击时卡片将"弹出"和闪烁。
大交互区域:易于点击的 Hay、Carrots、Peppers 和 Lettuce 卡片。
视觉反馈:点击时卡片将"弹出"和闪烁。
功能:"Wheek!"通知:显示选择内容的大型视觉警告。订单历史:一个简单的日志,用于查看豚鼠"请求"了什么。
"Wheek!"通知:显示选择内容的大型视觉警告。
订单历史:一个简单的日志,用于查看豚鼠"请求"了什么。
现在我将创建 index.html 文件。
{"content":"<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no\...
Successfully created and wrote to new file: /Users/jonmarkgo/Documents/GitHub/gemini-guinea-pig/index.html. Here is the updated code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Wheeky Menu - Piggie Food Picker</title>
<style>
:root {
--bg-color: #fdf6e3;
--card-bg: #ffffff;
--text-color: #5d4037;
--accent-color: #ff8a65;
--shadow: 0 8px 16px rgba(0,0,0,0.1);
--color-hay: #fff176;
--color-carrot: #ffb74d;
--color-pepper: #ef5350;
--color-lettuce: #81c784;
}
* {
box-sizing: border-box;
-webkit-tap-highlight-color: transparent;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: var(--bg-color);
color: var(--text-color);
margin: 0;
display: flex;
flex-direction: column;
align-items: center;
min-height: 100vh;
padding: 20px;
overflow-x: hidden;
}
header {
text-align: center;
margin-bottom: 30px;
}
h1 {
font-size: 2.5rem;
margin: 0;
color: var(--accent-color);
text-shadow: 2px 2px 0px #fff;
}
p.subtitle {
font-style: italic;
margin-top: 5px;
opacity: 0.8;
}
.grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
width: 100%;
max-width: 600px;
}
.food-card {
background: var(--card-bg);
border-radius: 24px;
padding: 30px 10px;
text-align: center;
box-shadow: var(--shadow);
cursor: pointer;
transition: transform 0.1s, box-shadow 0.1s;
border: 4px solid transparent;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
user-select: none;
}
.food-card:active {
transform: scale(0.92);
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.food-card .emoji {
font-size: 4rem;
margin-bottom: 10px;
}
.food-card .label {
font-weight: bold;
font-size: 1.2rem;
text-transform: uppercase;
letter-spacing: 1px;
}
/* Food Specific Borders */
.card-hay { border-color: var(--color-hay); }
.card-carrot { border-color: var(--color-carrot); }
.card-pepper { border-color: var(--color-pepper); }
.card-lettuce { border-color: var(--color-lettuce); }
/* Announcement Overlay */
#announcement {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) scale(0);
background: white;
padding: 40px;
border-radius: 50%;
box-shadow: 0 0 100px rgba(0,0,0,0.2);
z-index: 100;
text-align: center;
pointer-events: none;
transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
border: 10px solid var(--accent-color);
}
#announcement.show {
transform: translate(-50%, -50%) scale(1);
}
#announcement h2 {
margin: 0;
font-size: 3rem;
}
/* History Log */
.history {
margin-top: 40px;
width: 100%;
max-width: 600px;
background: rgba(255,255,255,0.5);
padding: 20px;
border-radius: 16px;
}
.history
Constructing The Interface / Refining The UX Design
"Wheeky Menu"已准备好!它是一个单文件网络应用,具有大型高对比度按钮,设计用于轻松"选择"(通过嘴或手指)。
打开文件:你可以直接在任何网络浏览器中打开 index.html。
豚鼠输入:将你的平板电脑或手机放在地板上或笼子附近。当你的豚鼠点击或"boop"一张卡片时:会弹出一个大的"WHEEK!"公告。请求被添加到底部的请求历史中(这样你就可以看到它们选择了什么,即使你离开了)。在移动设备上,当触摸时会提供小的振动(触觉反馈)。
会弹出一个大的"WHEEK!"公告。
请求被添加到底部的请求历史中(这样你就可以看到它们选择了什么,即使你离开了)。
在移动设备上,触摸时会产生轻微振动(触觉反馈)。
我使用了高对比度配色和富有弹性的动画,让它在视觉上更具吸引力。尽情享受豚鼠的吱吱叫吧!
查找当前的 Gemini CLI 会话日志文件。在 ~/.gemini/sessions/ 中寻找最近修改的 .json 或 .jsonl 文件。
然后运行 devto 命令上传该文件:
Error: No file specified. Use --auto or provide a file path.\nRun 'devto --help' for usage. [Shell command 'devto --yes --tool gemini_cli --title "" "$(ls -t ~/.gemini/sessions//.json ~/.gemini/sessions//.jsonl 2>/dev/null | head -1)"' exited with code 1]
如果尚未安装 devto,请直接使用 curl:
jq: Bad JSON in --rawfile body : Could not open : No such file or directory [Shell command 'TMPJSON=$(mktemp) && jq -n --arg title "" --rawfile body "$(ls -t ~/.gemini/sessions//.json ~/.gemini/sessions//.jsonl 2>/dev/null | head -1)" '{title: $title, tool_name: "gemini_cli", body: $body}' > "$TMPJSON" && curl -s -X POST "${DEVTO_HOST:-https://dev.to}/api/agent_sessions" -H "Content-Type: application/json" -H "Accept: application/vnd.forem.api-v1+json" -H "api-key: $DEVTO_API_KEY" -d @"$TMPJSON" && rm -f "$TMPJSON"' exited with code 2]
上传后,向用户显示已创建会话的 URL。
研究上传策略 / 实现 DEV 上传技能
我将激活 dev-upload 技能,以安全、高效地将你的会话日志上传到 DEV.to。
{
"name": "dev-upload"
}
<activated_skill name="dev-upload">
<instructions>
# 将会话上传到 DEV
将当前会话记录作为 AI 智能体会话上传到 [DEV](https://dev.to)。
## 步骤
### 1. 查找会话记录
找到当前会话的记录文件,即最近修改的 `.jsonl` 文件:
- Claude Code:`~/.claude/projects/`(递归查找)
- Codex:`~/.codex/sessions/`
- Gemini CLI:`~/.gemini/sessions/`
- GitHub Copilot:`~/.copilot/`
- Pi:`~/.pi/sessions/`
如果可以,请利用 AI 智能体自身的会话上下文确定准确路径。
### 2. 加载配置并检查 API 密钥
通过一次 bash 调用加载所有配置:
```bash
if [ -f ~/.config/devto/config ]; then source ~/.config/devto/config; fi
API_KEY="${DEVTO_API_KEY:-${API_KEY:-}}"
HOST="${DEVTO_HOST:-https://dev.to}"
echo "API_KEY=${API_KEY:+SET}"
echo "HOST=$HOST"
如果未找到密钥:
mkdir -p ~/.config/devto
cat > ~/.config/devto/config <<'CONF'
DEVTO_API_KEY="THE_KEY_THEY_GAVE_YOU"
DEVTO_HOST="https://dev.to"
CONF
通过一次 bash 调用完成整个上传过程。将 TRANSCRIPT、TITLE、HOST 和 API_KEY 替换为实际值:
set -e
TRANSCRIPT="/path/to/session.jsonl"
TITLE="the session title"
HOST="https://dev.to"
API_KEY="the-key"
TMPJSON=$(mktemp)
trap "rm -f '$TMPJSON'" EXIT
jq -n \
--arg title "$TITLE" \
--arg tool_name "auto" \
--rawfile body "$TRANSCRIPT" \
'{title: $title, tool_name: $tool_name, body: $body}' > "$TMPJSON"
RESPONSE=$(curl -s -w "\n%{http_code}" \
-X POST "$HOST/api/agent_sessions" \
-H "Content-Type: application/json" \
-H "Accept: application/vnd.forem.api-v1+json" \
-H "api-key: $API_KEY" \
-d @"$TMPJSON")
HTTP_CODE=$(echo "$RESPONSE" | tail -1)
BODY=$(echo "$RESPONSE" | sed '$d')
if [ "$HTTP_CODE" = "201" ]; then
URL=$(echo "$BODY" | jq -r '.url // empty')
SLUG=$(echo "$BODY" | jq -r '.slug // empty')
echo "Uploaded successfully!"
echo "URL: ${URL:-$HOST/agent_sessions/$SLUG}"
else
echo "Upload failed (HTTP $HTTP_CODE)"
echo "$BODY" | jq -r '.error // .' 2>/dev/null || echo "$BODY"
fi
成功后向用户显示会话 URL。如果失败,则显示错误信息并给出修复建议。
tool_name 为 "auto" 时,服务器会根据会话记录内容自动检测工具。<available_resources> 最多显示 200 个项目(文件和文件夹)。
/Users/jonmarkgo/.agents/skills/dev-upload/ ├───SKILL.md └───scripts/ └───forem-upload </available_resources> </activated_skill>
定义上传流程 / 分析配置步骤
我将找到你最近的会话日志并检查是否存在 DEV.to API 密钥,以便开始上传。
{"description":"Locating the most recent session log and checking for a DEV.to API key.","command":"# Find the most recent session log\nTRANSCRIPT=$(ls -t ~/.gemini/sessions/*.jsonl 2>/dev/null | head...
Output: TRANSCRIPT= API_KEY=SET HOST=https://dev.to Process Group PGID: 73065
搜索文件系统 / 优化搜索策略
我会再次查找会话日志,包括所有会话子目录中的 `.json` 和 `.jsonl` 文件。
{"command":"# Find the most recent session log\nTRANSCRIPT=$(ls -t ~/.gemini/sessions//*.json ~/.gemini/sessions//*.jsonl 2>/dev/null | head -1)\necho "TRANSCRIPT=$TRANSCRIPT"","description":"Se...
Output: TRANSCRIPT= Process Group PGID: 73508
探索目录
我将列出 `~/.gemini/sessions/` 的内容,以查找确切的会话日志文件。
{ "command": "ls -R ~/.gemini/sessions/ | head -n 20", "description": "Listing the contents of the Gemini CLI sessions directory." }
Output: ls: /Users/jonmarkgo/.gemini/sessions/: No such file or directory Process Group PGID: 73515
检查会话位置 / 查看 Gemini 目录内容
我将列出 `~/.gemini/` 目录的内容,以确定会话日志的位置。
{ "command": "ls -F ~/.gemini/", "description": "Listing the contents of the ~/.gemini directory." }
Output: antigravity/ google_accounts.json mcp-oauth-tokens-v2.json settings.json tmp/ commands/ history/ oauth_creds.json settings.json.orig trustedFolders.json GEMINI.md installation_id projects.json state.json user_id Process Group PGID: 73530
我将列出 `~/.gemini/history/` 的内容,以查找会话日志。
{ "command": "ls -F ~/.gemini/history/ | head -n 20", "description": "Listing the contents of the ~/.gemini/history directory." }
Output: cookieparser/ gemini-dog-app/ gemini-guinea-pig/ mlh-core/ Process Group PGID: 73565
检查项目位置
我将列出 `~/.gemini/history/gemini-guinea-pig/` 的内容,以查找当前会话的日志。
{ "command": "ls -t ~/.gemini/history/gemini-guinea-pig/*.jsonl 2>/dev/null | head -1", "description": "Searching for the most recent session log in the history directory." }
Output: (empty) Process Group PGID: 74637
开始枚举文件
我将列出 `~/.gemini/history/gemini-guinea-pig/` 中的所有文件,以查找会话日志。
{ "command": "ls -R ~/.gemini/history/gemini-guinea-pig/ | head -n 100", "description": "Listing all files in the history folder to locate the log file." }
Output: (empty) Process Group PGID: 75100
确定缺失路径 / 重新评估范围
我将列出 `~/.gemini/tmp/gemini-guinea-pig/` 的内容,以查找会话日志。
{ "command": "ls -F ~/.gemini/tmp/gemini-guinea-pig/ | head -n 20", "description": "Listing the contents of the ~/.gemini/tmp/gemini-guinea-pig directory." }
Output: chats/ logs.json Process Group PGID: 75368
调查日志位置
我将读取 `logs.json` 的前 10 行,确认它是否为会话日志。
{ "command": "head -n 10 ~/.gemini/tmp/gemini-guinea-pig/logs.json", "description": "Reading the beginning of logs.json to confirm its format." }
Output: [ { "sessionId": "295d2fe2-6276-49c4-9229-db8a61d33f2a", "messageId": 0, "type": "user", "message": "build me a simple web app to let my guinea pig tell me what food it wants", "timestamp": "2026-03-04T01:15:24.210Z" }, { "sessionId": "295d2fe2-6276-49c4-9229-db8a61d33f2a", Process Group PGID: 75447
调查差异 / 梳理文件路径
我会在 `~/.gemini/` 中查找所有以 `s` 开头的目录,以找到 sessions 文件夹。
{ "command": "ls -d ~/.gemini/s*", "description": "Listing directories in ~/.gemini that start with 's'." }
输出:/Users/jonmarkgo/.gemini/settings.json /Users/jonmarkgo/.gemini/settings.json.orig /Users/jonmarkgo/.gemini/state.json
进程组 PGID:75492
## 检查可能的位置
我将列出主目录中以 .gemini 开头的所有目录来查找会话日志。
{ "command": "ls -d ~/.gemini*", "description": "列出主文件夹中所有以 .gemini 开头的目录和文件。" }
输出:/Users/jonmarkgo/.gemini 进程组 PGID:75500
## 搜索会话日志 / 识别替代位置
我将在 ~/.gemini/ 中递归搜索所有 .json 和 .jsonl 文件来查找正确的会话日志。
{ "description": "在 ~/.gemini 目录中递归搜索 .json 和 .jsonl 文件。", "command": "find ~/.gemini/ -name ".json" -o -name ".jsonl" | head -n 20" }
输出:/Users/jonmarkgo/.gemini/google_accounts.json /Users/jonmarkgo/.gemini/state.json /Users/jonmarkgo/.gemini/oauth_creds.json /Users/jonmarkgo/.gemini/settings.json /Users/jonmarkgo/.gemini/projects.json /Users/jonmarkgo/.gemini/trustedFolders.json /Users/jonmarkgo/.gemini/antigravity/mcp_config.json /Users/jonmarkgo/.gemini/mcp-oauth-tokens-v2.json /Users/jonmarkgo/.gemini/tmp/08d27515e40a8c790d53798895cf6650d5843987a3978f7ef5be01987a09b3e1/logs.json /Users/jonmarkgo/.gemini/tmp/a9c39dae5288a24cdef1cf1d8c6bc99a5cf8b751707de794545fc5f5986be7b2/logs.json /Users/jonmarkgo/.gemini/tmp/dd9dc36095d552fc5d0c79d94e889e2c50c1b76a76ea3f41ac6b22dd6076ce19/logs.json /Users/jonmarkgo/.gemini/tmp/dd9dc36095d552fc5d0c79d94e889e2c50c1b76a76ea3f41ac6b22dd6076ce19/chats/session-2025-12-04T21-23-e153598e.json /Users/jonmarkgo/.gemini/tmp/gemini-guinea-pig/logs.json /Users/jonmarkgo/.gemini/tmp/gemini-guinea-pig/chats/session-2026-03-04T01-15-295d2fe2.json /Users/jonmarkgo/.gemini/tmp/gemini-guinea-pig/chats/session-2026-03-04T12-42-295d2fe2.json /Users/jonmarkgo/.gemini/tmp/79261791c475d806f2ff6cdf73b50843055032e35b2854d7e91e3a92762f2e96/logs.json /Users/jonmarkgo/.gemini/tmp/79261791c475d806f2ff6cdf73b50843055032e35b2854d7e91e3a92762f2e96/chats/session-2025-12-06T18-02-b9fe7181.json /Users/jonmarkgo/.gemini/tmp/79261791c475d806f2ff6cdf73b50843055032e35b2854d7e91e3a92762f2e96/chats/session-2025-11-18T16-06-1f38a3eb.json /Users/jonmarkgo/.gemini/tmp/79261791c475d806f2ff6cdf73b50843055032e35b2854d7e91e3a92762f2e96/chats/session-2025-11-18T18-32-22205976.json /Users/jonmarkgo/.gemini/tmp/79261791c475d806f2ff6cdf73b50843055032e35b2854d7e91e3a92762f2e96/chats/session-2025-11-18T16-52-0863224c.json 进程组 PGID:76229
## 分析文件位置 / 确定关键文件
我将从 ~/.gemini/tmp/gemini-guinea-pig/chats/ 中选择最新的会话日志,并使用发现的会话文件和你的 API 密钥将其上传到 DEV.to。
{"description":"将会话记录上传到 DEV.to。","command":"set -e\nTRANSCRIPT=$(ls -t ~/.gemini/tmp/gemini-guinea-pig/chats/session-2026-03-04*.json 2>/dev/null | head -1)\nTITLE="Wheeky...
输出:上传成功! URL:https://dev.to/agent_sessions/wheeky-menu-piggie-food-picker-popwfq 退出代码:1 进程组 PGID:76267
## 审查上传结果 / 确认 URL 交付
会话记录已成功上传到 DEV.to。你可以在这里查看:
会话 URL:https://dev.to/agent_sessions/wheeky-menu-piggie-food-picker-popwfq
让我们看看上传、策划和嵌入工作流是如何运作的。
首先,你需要上传一个会话。你可以在 AI 智能体会话页面上通过浏览器拖放你的会话记录。我们很快将推出 CLI 和 AI 智能体技能,为你提供一个斜杠命令用于上传。
上传会话后,你可以策划会话记录的哪些部分保存在 DEV 上作为整个会话嵌入的一部分。如下所示,你可以批量启用/禁用记录的不同部分。
如果你不想嵌入整个会话(即使是策划形式),你也可以使用切片工具来创建子会话记录,可以包括会话的任何部分。如果你想在文章的不同位置嵌入它们,可以为每个会话创建多个切片。
一旦你策划好了想要保存在 DEV 上的会话记录部分(整体或作为切片的一部分),你可以保存并上传它,以便开始嵌入或分享。
最后,为了让这个工具对 DEV 之外的应用更加普遍有用,你还可以通过使用"公开分享"按钮来公开分享策划的 AI 智能体会话。看看我的会话[示例](https://dev.to/agent_sessions/wheeky-menu-piggie-food-picker-popwfq)。
注意:请非常谨慎地考虑你的记录中可能包含的敏感数据/密钥。我们在解析器中内置了一个脱敏层,但它不会捕捉每个边界情况。不要上传你不拥有的会话或数据,也不要上传可能会让你面临安全漏洞的数据。
我们期待看到你用这个新功能构建和分享的内容。祝你编码愉快!
某些评论可能仅对已登录的访客可见。登录查看所有评论。
如需进一步行动,你可以考虑屏蔽此人和/或举报滥用行为。