{"id":"1faa8425-3cad-47b1-a4c1-7da913e94925","shortId":"Dy3aB7","kind":"skill","title":"chat-logger","tagline":"Log all chat messages to a SQLite database for searchable history and audit. Use when: (1) Building chat history, (2) Auditing conversations, (3) Searching past messages, or (4) User asks to log chats.","description":"# Chat Logger\n\nLog all incoming and outgoing chat messages to a SQLite database for searchable history, analytics, and auditing. Works with any chat system or agent framework.\n\n## When to use\n\n- Building a searchable chat history system\n- Auditing and reviewing past conversations\n- Creating analytics on chat interactions\n- Debugging chat flows and responses\n- User asks to track or search conversation history\n\n## Required tools / APIs\n\n- Python standard library (sqlite3, datetime, json)\n- Any programming language with SQLite support\n\nNo external APIs or services required.\n\n## Database Schema\n\n```sql\nCREATE TABLE IF NOT EXISTS messages (\n  id INTEGER PRIMARY KEY AUTOINCREMENT,\n  timestamp TEXT NOT NULL,\n  session_id TEXT,\n  sender TEXT NOT NULL,           -- 'user', 'assistant', or identifier\n  content TEXT,\n  metadata TEXT,                  -- JSON: channel, tools_used, etc.\n  created_at DATETIME DEFAULT CURRENT_TIMESTAMP\n);\n\nCREATE INDEX idx_timestamp ON messages(timestamp);\nCREATE INDEX idx_session ON messages(session_id);\nCREATE INDEX idx_sender ON messages(sender);\n\n-- Automatic purge: delete records older than 1 year\nDELETE FROM messages WHERE created_at < datetime('now', '-1 year');\n```\n\n**Fields:**\n- `id` - Auto-incrementing primary key\n- `timestamp` - ISO 8601 timestamp of the message\n- `session_id` - Optional session/conversation identifier\n- `sender` - Message sender ('user', 'assistant', or custom ID)\n- `content` - Message text content\n- `metadata` - JSON field for additional data (channel, tools, context)\n- `created_at` - Database insertion timestamp\n\n## Basic Implementation\n\n### Python\n\n**Initialize database:**\n\n```python\nimport sqlite3\nfrom datetime import datetime\nfrom pathlib import Path\nimport json\n\n# Configure database path\nDB_PATH = Path.home() / \".chat_logs\" / \"messages.db\"\n\ndef init_db():\n    \"\"\"Initialize database and create tables.\"\"\"\n    DB_PATH.parent.mkdir(parents=True, exist_ok=True)\n    conn = sqlite3.connect(str(DB_PATH))\n    conn.execute(\"\"\"\n        CREATE TABLE IF NOT EXISTS messages (\n            id INTEGER PRIMARY KEY AUTOINCREMENT,\n            timestamp TEXT NOT NULL,\n            session_id TEXT,\n            sender TEXT NOT NULL,\n            content TEXT,\n            metadata TEXT,\n            created_at DATETIME DEFAULT CURRENT_TIMESTAMP\n        )\n    \"\"\")\n    conn.execute(\"CREATE INDEX IF NOT EXISTS idx_timestamp ON messages(timestamp)\")\n    conn.execute(\"CREATE INDEX IF NOT EXISTS idx_session ON messages(session_id)\")\n    conn.execute(\"CREATE INDEX IF NOT EXISTS idx_sender ON messages(sender)\")\n    conn.commit()\n    conn.close()\n\ndef purge_old_messages():\n    \"\"\"Delete messages older than 1 year to keep the database size sane.\"\"\"\n    conn = sqlite3.connect(str(DB_PATH))\n    conn.execute(\"DELETE FROM messages WHERE created_at < datetime('now', '-1 year')\")\n    conn.commit()\n    conn.close()\n\n# Initialize on import and purge old records\ninit_db()\npurge_old_messages()\n```\n\n**Log messages:**\n\n```python\ndef log_message(sender: str, content: str, session_id: str = None, metadata: dict = None):\n    \"\"\"Log a chat message to the database.\"\"\"\n    conn = sqlite3.connect(str(DB_PATH))\n    try:\n        conn.execute(\n            \"\"\"INSERT INTO messages (timestamp, session_id, sender, content, metadata)\n               VALUES (?, ?, ?, ?, ?)\"\"\",\n            (\n                datetime.utcnow().isoformat(),\n                session_id,\n                sender,\n                content[:10000] if content else None,  # Truncate long messages\n                json.dumps(metadata) if metadata else None\n            )\n        )\n        conn.commit()\n    finally:\n        conn.close()\n\n# Usage examples\nlog_message(\"user\", \"Hello, how are you?\", session_id=\"session_123\")\nlog_message(\"assistant\", \"I'm doing well, thank you!\", session_id=\"session_123\")\nlog_message(\"user\", \"Help me deploy a website\", session_id=\"session_456\",\n            metadata={\"channel\": \"web\", \"ip\": \"192.168.1.1\"})\n```\n\n**Query messages:**\n\n```python\ndef get_recent_messages(limit: int = 50):\n    \"\"\"Get recent messages.\"\"\"\n    conn = sqlite3.connect(str(DB_PATH))\n    conn.row_factory = sqlite3.Row\n    cursor = conn.execute(\n        \"SELECT * FROM messages ORDER BY timestamp DESC LIMIT ?\",\n        (limit,)\n    )\n    results = cursor.fetchall()\n    conn.close()\n    return results\n\ndef get_session_history(session_id: str):\n    \"\"\"Get all messages from a specific session.\"\"\"\n    conn = sqlite3.connect(str(DB_PATH))\n    conn.row_factory = sqlite3.Row\n    cursor = conn.execute(\n        \"SELECT * FROM messages WHERE session_id = ? ORDER BY timestamp ASC\",\n        (session_id,)\n    )\n    results = cursor.fetchall()\n    conn.close()\n    return results\n\ndef search_messages(query: str, limit: int = 20):\n    \"\"\"Search message content.\"\"\"\n    conn = sqlite3.connect(str(DB_PATH))\n    conn.row_factory = sqlite3.Row\n    cursor = conn.execute(\n        \"SELECT * FROM messages WHERE content LIKE ? ORDER BY timestamp DESC LIMIT ?\",\n        (f\"%{query}%\", limit)\n    )\n    results = cursor.fetchall()\n    conn.close()\n    return results\n\n# Usage\nmessages = get_recent_messages(10)\nfor msg in messages:\n    print(f\"[{msg['timestamp']}] {msg['sender']}: {msg['content'][:100]}\")\n\n# Search\nresults = search_messages(\"deploy website\")\nprint(f\"Found {len(results)} messages about deploying websites\")\n```\n\n### Node.js\n\n```javascript\nimport sqlite3 from \"sqlite3\";\nimport { promisify } from \"util\";\nimport path from \"path\";\nimport os from \"os\";\n\nconst DB_PATH = path.join(os.homedir(), \".chat_logs\", \"messages.db\");\n\n// Initialize database\nconst db = new sqlite3.Database(DB_PATH);\nconst run = promisify(db.run.bind(db));\nconst all = promisify(db.all.bind(db));\n\nawait run(`\n  CREATE TABLE IF NOT EXISTS messages (\n    id INTEGER PRIMARY KEY AUTOINCREMENT,\n    timestamp TEXT NOT NULL,\n    session_id TEXT,\n    sender TEXT NOT NULL,\n    content TEXT,\n    metadata TEXT,\n    created_at DATETIME DEFAULT CURRENT_TIMESTAMP\n  )\n`);\n\n// Log message\nasync function logMessage(sender, content, sessionId = null, metadata = null) {\n  await run(\n    `INSERT INTO messages (timestamp, session_id, sender, content, metadata)\n     VALUES (?, ?, ?, ?, ?)`,\n    [\n      new Date().toISOString(),\n      sessionId,\n      sender,\n      content,\n      metadata ? JSON.stringify(metadata) : null,\n    ]\n  );\n}\n\n// Query messages\nasync function getRecentMessages(limit = 50) {\n  return await all(\n    `SELECT * FROM messages ORDER BY timestamp DESC LIMIT ?`,\n    [limit]\n  );\n}\n\n// Usage\nawait logMessage(\"user\", \"Hello!\", \"session_123\");\nawait logMessage(\"assistant\", \"Hi there!\", \"session_123\");\n\nconst messages = await getRecentMessages(10);\nconsole.log(messages);\n```\n\n## Bash Quick Queries\n\n```bash\n# View recent messages\nsqlite3 ~/.chat_logs/messages.db \"SELECT timestamp, sender, substr(content, 1, 80) FROM messages ORDER BY timestamp DESC LIMIT 20\"\n\n# Search for specific content\nsqlite3 ~/.chat_logs/messages.db \"SELECT * FROM messages WHERE content LIKE '%docker%' ORDER BY timestamp DESC\"\n\n# Count messages by sender\nsqlite3 ~/.chat_logs/messages.db \"SELECT sender, COUNT(*) as count FROM messages GROUP BY sender\"\n\n# Export session to JSON\nsqlite3 -json ~/.chat_logs/messages.db \"SELECT * FROM messages WHERE session_id='session_123' ORDER BY timestamp ASC\" > conversation.json\n```\n\n## Integration Examples\n\n### Generic Chat Application\n\n```python\nclass ChatLogger:\n    \"\"\"Simple chat logger that can wrap any chat system.\"\"\"\n\n    def __init__(self, db_path: str = None):\n        self.db_path = db_path or str(Path.home() / \".chat_logs\" / \"messages.db\")\n        self._init_db()\n\n    def _init_db(self):\n        # Same as init_db() above\n        pass\n\n    def log_user_message(self, content: str, session_id: str = None, **metadata):\n        return log_message(\"user\", content, session_id, metadata)\n\n    def log_assistant_message(self, content: str, session_id: str = None, **metadata):\n        return log_message(\"assistant\", content, session_id, metadata)\n\n    def get_conversation(self, session_id: str):\n        return get_session_history(session_id)\n\n# Usage in any chat system\nlogger = ChatLogger()\n\n# In your chat handler\ndef handle_message(user_input, session_id):\n    logger.log_user_message(user_input, session_id=session_id)\n\n    # Process message...\n    response = generate_response(user_input)\n\n    logger.log_assistant_message(response, session_id=session_id)\n    return response\n```\n\n### Decorator Pattern\n\n```python\ndef with_logging(session_id: str = None):\n    \"\"\"Decorator to automatically log chat interactions.\"\"\"\n    def decorator(func):\n        def wrapper(user_message, *args, **kwargs):\n            # Log user message\n            log_message(\"user\", user_message, session_id=session_id)\n\n            # Call original function\n            response = func(user_message, *args, **kwargs)\n\n            # Log assistant response\n            log_message(\"assistant\", response, session_id=session_id)\n\n            return response\n        return wrapper\n    return decorator\n\n# Usage\n@with_logging(session_id=\"session_123\")\ndef chat_handler(message):\n    return f\"You said: {message}\"\n```\n\n## Agent Prompt\n\n```text\nYou have chat logging capability. All conversations are logged to a SQLite database.\n\nWhen user asks to:\n- Search past conversations\n- Find specific messages\n- Review conversation history\n- Export chat logs\n\nUse the SQLite database at ~/.chat_logs/messages.db with this schema:\n- messages table (id, timestamp, session_id, sender, content, metadata)\n\nQuery examples:\n1. Recent history: SELECT * FROM messages ORDER BY timestamp DESC LIMIT 50\n2. Search content: SELECT * FROM messages WHERE content LIKE '%keyword%'\n3. Session history: SELECT * FROM messages WHERE session_id = ? ORDER BY timestamp ASC\n\nAlways use SQL queries to retrieve information and present results clearly to the user.\n```\n\n## Best Practices\n\n1. **Truncate long messages** to avoid database bloat (e.g., 10,000 chars)\n2. **Use indexes** on timestamp, session_id, and sender for fast queries\n3. **Store metadata as JSON** for flexibility\n4. **Use ISO 8601 timestamps** for consistency\n5. **Session IDs** help organize conversations\n6. **Privacy considerations**: be mindful of storing sensitive data\n7. **Regular backups**: SQLite files are easy to backup/restore\n\n## Troubleshooting\n\n**Database locked error:**\n- Close all connections properly with `conn.close()`\n- Use connection pooling for high traffic\n\n**Large database file:**\n- Run `VACUUM` to compact: `sqlite3 messages.db \"VACUUM\"`\n- Archive old messages periodically\n\n**Query performance:**\n- Ensure indexes are created (timestamp, session_id, sender)\n- Use LIMIT on queries\n- Consider pagination for large result sets\n\n## See also\n\n- [../file-tracker/SKILL.md](../file-tracker/SKILL.md) — Track file modifications\n- [../web-search-api/SKILL.md](../web-search-api/SKILL.md) — Search external content","tags":["chat","logger","open","skills","besoeasy","agent-skills","ai-agents","claude-code","clawdbot","clawdbot-skill","llm-tools","mcp-server"],"capabilities":["skill","source-besoeasy","skill-chat-logger","topic-agent-skills","topic-ai-agents","topic-claude-code","topic-clawdbot","topic-clawdbot-skill","topic-llm-tools","topic-mcp-server","topic-openai","topic-openclaw","topic-vibe-coding","topic-vibecoding"],"categories":["open-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/besoeasy/open-skills/chat-logger","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add besoeasy/open-skills","source_repo":"https://github.com/besoeasy/open-skills","install_from":"skills.sh"}},"qualityScore":"0.505","qualityRationale":"deterministic score 0.51 from registry signals: · indexed on github topic:agent-skills · 111 github stars · SKILL.md body (10,891 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-02T12:55:02.795Z","embedding":null,"createdAt":"2026-04-18T22:10:35.015Z","updatedAt":"2026-05-02T12:55:02.795Z","lastSeenAt":"2026-05-02T12:55:02.795Z","tsv":"'-1':199,391 '/.chat_logs/messages.db':825,846,863,880,1152 '/file-tracker/skill.md':1332,1333 '/web-search-api/skill.md':1337,1338 '000':1228 '1':19,189,369,831,1167,1218 '10':637,814,1227 '100':650 '10000':454 '123':483,496,802,809,888,1105 '192.168.1.1':513 '2':23,1179,1230 '20':599,840 '3':26,1189,1242 '4':31,1249 '456':508 '5':1256 '50':523,783,1178 '6':1262 '7':1271 '80':832 '8601':210,1252 'addit':236 'agent':62,1115 'also':1331 'alway':1202 'analyt':53,79 'api':98,113 'applic':898 'archiv':1306 'arg':1059,1080 'asc':584,892,1201 'ask':33,89,1133 'assist':143,224,486,805,961,974,1027,1083,1087 'async':746,779 'audit':16,24,55,73 'auto':204 'auto-incr':203 'autoincr':130,303,722 'automat':183,1048 'avoid':1223 'await':710,755,785,797,803,812 'backup':1273 'backup/restore':1279 'bash':817,820 'basic':246 'best':1216 'bloat':1225 'build':20,67 'call':1073 'capabl':1122 'channel':151,238,510 'char':1229 'chat':2,6,21,36,37,44,59,70,81,84,270,426,689,897,903,909,925,995,1001,1050,1107,1120,1145 'chat-logg':1 'chatlogg':901,998 'class':900 'clear':1212 'close':1284 'compact':1302 'configur':264 'conn':287,377,431,527,565,603 'conn.close':360,394,470,548,589,629,1289 'conn.commit':359,393,468 'conn.execute':292,325,336,348,382,437,536,574,612 'conn.row':532,570,608 'connect':1286,1291 'consid':1324 'consider':1264 'consist':1255 'console.log':815 'const':684,694,700,705,810 'content':146,228,231,315,415,445,453,456,602,617,649,734,750,764,772,830,844,851,944,955,964,975,1163,1181,1186,1341 'context':240 'convers':25,77,94,981,1124,1137,1142,1261 'conversation.json':893 'count':858,866,868 'creat':78,120,155,161,168,176,195,241,279,293,319,326,337,349,387,712,738,1315 'current':159,323,742 'cursor':535,573,611 'cursor.fetchall':547,588,628 'custom':226 'data':237,1270 'databas':11,49,117,243,250,265,277,374,430,693,1130,1150,1224,1281,1297 'date':768 'datetim':103,157,197,255,257,321,389,740 'datetime.utcnow':448 'db':267,275,290,380,403,434,530,568,606,685,695,698,704,709,914,920,931,936 'db.all.bind':708 'db.run.bind':703 'db_path.parent.mkdir':281 'debug':83 'decor':1036,1046,1053,1098 'def':273,361,410,517,551,592,911,929,939,959,979,1003,1039,1052,1055,1106 'default':158,322,741 'delet':185,191,365,383 'deploy':502,655,664 'desc':543,622,793,838,857,1176 'dict':422 'docker':853 'e.g':1226 'easi':1277 'els':457,466 'ensur':1312 'error':1283 'etc':154 'exampl':472,895,1166 'exist':124,284,297,330,341,353,716 'export':874,1144 'extern':112,1340 'f':624,643,658,1111 'factori':533,571,609 'fast':1240 'field':201,234 'file':1275,1298,1335 'final':469 'find':1138 'flexibl':1248 'flow':85 'found':659 'framework':63 'func':1054,1077 'function':747,780,1075 'generat':1022 'generic':896 'get':518,524,552,558,634,980,987 'getrecentmessag':781,813 'group':871 'handl':1004 'handler':1002,1108 'hello':476,800 'help':500,1259 'hi':806 'high':1294 'histori':14,22,52,71,95,554,989,1143,1169,1191 'id':126,136,175,202,216,227,299,309,347,418,443,451,481,494,506,556,580,586,718,728,762,886,947,957,967,977,984,991,1009,1016,1018,1031,1033,1043,1070,1072,1090,1092,1103,1158,1161,1197,1236,1258,1318 'identifi':145,219 'idx':163,170,178,331,342,354 'implement':247 'import':252,256,260,262,397,668,672,676,680 'incom':41 'increment':205 'index':162,169,177,327,338,350,1232,1313 'inform':1208 'init':274,402,912,930,935 'initi':249,276,395,692 'input':1007,1014,1025 'insert':244,438,757 'int':522,598 'integ':127,300,719 'integr':894 'interact':82,1051 'ip':512 'iso':209,1251 'isoformat':449 'javascript':667 'json':104,150,233,263,877,879,1246 'json.dumps':462 'json.stringify':774 'keep':372 'key':129,207,302,721 'keyword':1188 'kwarg':1060,1081 'languag':107 'larg':1296,1327 'len':660 'librari':101 'like':618,852,1187 'limit':521,544,545,597,623,626,782,794,795,839,1177,1321 'lock':1282 'log':4,35,39,271,407,411,424,473,484,497,690,744,926,940,952,960,972,1041,1049,1061,1064,1082,1085,1101,1121,1126,1146 'logger':3,38,904,997 'logger.log':1010,1026 'logmessag':748,798,804 'long':460,1220 'm':488 'messag':7,29,45,125,166,173,181,193,214,221,229,298,334,345,357,364,366,385,406,408,412,427,440,461,474,485,498,515,520,526,539,560,577,594,601,615,633,636,641,654,662,717,745,759,778,789,811,816,823,834,849,859,870,883,942,953,962,973,1005,1012,1020,1028,1058,1063,1065,1068,1079,1086,1109,1114,1140,1156,1172,1184,1194,1221,1308 'messages.db':272,691,927,1304 'metadata':148,232,317,421,446,463,465,509,736,753,765,773,775,950,958,970,978,1164,1244 'mind':1266 'modif':1336 'msg':639,644,646,648 'new':696,767 'node.js':666 'none':420,423,458,467,917,949,969,1045 'null':134,141,307,314,726,733,752,754,776 'ok':285 'old':363,400,405,1307 'older':187,367 'option':217 'order':540,581,619,790,835,854,889,1173,1198 'organ':1260 'origin':1074 'os':681,683 'os.homedir':688 'outgo':43 'pagin':1325 'parent':282 'pass':938 'past':28,76,1136 'path':261,266,268,291,381,435,531,569,607,677,679,686,699,915,919,921 'path.home':269,924 'path.join':687 'pathlib':259 'pattern':1037 'perform':1311 'period':1309 'pool':1292 'practic':1217 'present':1210 'primari':128,206,301,720 'print':642,657 'privaci':1263 'process':1019 'program':106 'promisifi':673,702,707 'prompt':1116 'proper':1287 'purg':184,362,399,404 'python':99,248,251,409,516,899,1038 'queri':514,595,625,777,819,1165,1205,1241,1310,1323 'quick':818 'recent':519,525,635,822,1168 'record':186,401 'regular':1272 'requir':96,116 'respons':87,1021,1023,1029,1035,1076,1084,1088,1094 'result':546,550,587,591,627,631,652,661,1211,1328 'retriev':1207 'return':549,590,630,784,951,971,986,1034,1093,1095,1097,1110 'review':75,1141 'run':701,711,756,1299 'said':1113 'sane':376 'schema':118,1155 'search':27,93,593,600,651,653,841,1135,1180,1339 'searchabl':13,51,69 'see':1330 'select':537,575,613,787,826,847,864,881,1170,1182,1192 'self':913,932,943,963,982 'self._init_db':928 'self.db':918 'sender':138,179,182,220,222,311,355,358,413,444,452,647,730,749,763,771,828,861,865,873,1162,1238,1319 'sensit':1269 'servic':115 'session':135,171,174,215,308,343,346,417,442,450,480,482,493,495,505,507,553,555,564,579,585,727,761,801,808,875,885,887,946,956,966,976,983,988,990,1008,1015,1017,1030,1032,1042,1069,1071,1089,1091,1102,1104,1160,1190,1196,1235,1257,1317 'session/conversation':218 'sessionid':751,770 'set':1329 'simpl':902 'size':375 'skill' 'skill-chat-logger' 'source-besoeasy' 'specif':563,843,1139 'sql':119,1204 'sqlite':10,48,109,1129,1149,1274 'sqlite3':102,253,669,671,824,845,862,878,1303 'sqlite3.connect':288,378,432,528,566,604 'sqlite3.database':697 'sqlite3.row':534,572,610 'standard':100 'store':1243,1268 'str':289,379,414,416,419,433,529,557,567,596,605,916,923,945,948,965,968,985,1044 'substr':829 'support':110 'system':60,72,910,996 'tabl':121,280,294,713,1157 'text':132,137,139,147,149,230,305,310,312,316,318,724,729,731,735,737,1117 'thank':491 'timestamp':131,160,164,167,208,211,245,304,324,332,335,441,542,583,621,645,723,743,760,792,827,837,856,891,1159,1175,1200,1234,1253,1316 'toisostr':769 'tool':97,152,239 'topic-agent-skills' 'topic-ai-agents' 'topic-claude-code' 'topic-clawdbot' 'topic-clawdbot-skill' 'topic-llm-tools' 'topic-mcp-server' 'topic-openai' 'topic-openclaw' 'topic-vibe-coding' 'topic-vibecoding' 'track':91,1334 'traffic':1295 'tri':436 'troubleshoot':1280 'true':283,286 'truncat':459,1219 'usag':471,632,796,992,1099 'use':17,66,153,1147,1203,1231,1250,1290,1320 'user':32,88,142,223,475,499,799,941,954,1006,1011,1013,1024,1057,1062,1066,1067,1078,1132,1215 'util':675 'vacuum':1300,1305 'valu':447,766 'view':821 'web':511 'websit':504,656,665 'well':490 'work':56 'wrap':907 'wrapper':1056,1096 'year':190,200,370,392","prices":[{"id":"86566629-b5cf-47de-80e2-ac66d5a8ba6d","listingId":"1faa8425-3cad-47b1-a4c1-7da913e94925","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"besoeasy","category":"open-skills","install_from":"skills.sh"},"createdAt":"2026-04-18T22:10:35.015Z"}],"sources":[{"listingId":"1faa8425-3cad-47b1-a4c1-7da913e94925","source":"github","sourceId":"besoeasy/open-skills/chat-logger","sourceUrl":"https://github.com/besoeasy/open-skills/tree/main/skills/chat-logger","isPrimary":false,"firstSeenAt":"2026-04-18T22:10:35.015Z","lastSeenAt":"2026-05-02T12:55:02.795Z"}],"details":{"listingId":"1faa8425-3cad-47b1-a4c1-7da913e94925","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"besoeasy","slug":"chat-logger","github":{"repo":"besoeasy/open-skills","stars":111,"topics":["agent-skills","ai","ai-agents","claude-code","clawdbot","clawdbot-skill","llm-tools","mcp-server","openai","openclaw","vibe-coding","vibecoding"],"license":null,"html_url":"https://github.com/besoeasy/open-skills","pushed_at":"2026-03-31T13:05:30Z","description":"Battle-tested skill library for AI agents. Save 98% of API costs with ready-to-use code for crypto, PDFs, search, web scraping & more. No trial-and-error, no expensive APIs.","skill_md_sha":"5b8866a94dea08071518f9d63fcee9c84f4f302f","skill_md_path":"skills/chat-logger/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/besoeasy/open-skills/tree/main/skills/chat-logger"},"layout":"multi","source":"github","category":"open-skills","frontmatter":{"name":"chat-logger","description":"Log all chat messages to a SQLite database for searchable history and audit. Use when: (1) Building chat history, (2) Auditing conversations, (3) Searching past messages, or (4) User asks to log chats."},"skills_sh_url":"https://skills.sh/besoeasy/open-skills/chat-logger"},"updatedAt":"2026-05-02T12:55:02.795Z"}}