Tchousec Nl2sql Analysis
ASecurityTCHouse-C(ClickHouse)自然语言 SQL 生成 Skill。用户通过自然语言描述分析需求,AI 自动理解意图、生成对应 SQL 语句,并给出图表可视化建议与中文业务解读思路。 ⚠️ 当前版本仅生成 SQL 与分析建议,不直接执行 SQL;用户需自行将生成的 SQL 复制到 TCHouse-C 控制台的 SQL 工作区(DMS)或其他客户端执行。 触发词:数据分析、统计、报表、趋势图、柱状图、饼图、折线图、数据查询、NL2SQL、自然语言查询、帮我写SQL、帮我生成SQL、帮我查一下、帮我统计、帮我分析、按天统计、按月统计、分组统计、TOP排名、占比分析、同比、环比、趋势分析、ClickHouse查询、TCHouse-C查询、cdwch、SQL生成、GMV、DAU、转化率、支付金额、订单量。 本 Skill 包含 3 个子能力:①自然语言转 SQL(NL2SQL)②智能图表可视化推荐 ③中文业务结论摘要撰写建议。 何时不触发:慢 SQL 诊断与自动调优(已有 SQL 的性能分析)、集群健康诊断与故障排查(监控指标/告警/节点故障)、集群选型与架构推荐、智能建表与数...
- 417 stars
- 0 votes
- 0 copies
- 2 views
- Added November 8, 2026
Works with
Security analysis
100/100Pro scans all 5 files and shows the line behind each finding
npx -y skills add infometa/workbuddyskills --skill tchousec-nl2sql-analysis --agent claude-codeAre you the author of Tchousec Nl2sql Analysis?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/infometa-tchousec-nl2sql-analysis)---
name: 腾讯云TCHouse-C 自然语言 SQL 生成
description: >
TCHouse-C(ClickHouse)自然语言 SQL 生成 Skill。用户通过自然语言描述分析需求,AI 自动理解意图、生成对应 SQL 语句,并给出图表可视化建议与中文业务解读思路。
⚠️ 当前版本仅生成 SQL 与分析建议,不直接执行 SQL;用户需自行将生成的 SQL 复制到 TCHouse-C 控制台的 SQL 工作区(DMS)或其他客户端执行。
触发词:数据分析、统计、报表、趋势图、柱状图、饼图、折线图、数据查询、NL2SQL、自然语言查询、帮我写SQL、帮我生成SQL、帮我查一下、帮我统计、帮我分析、按天统计、按月统计、分组统计、TOP排名、占比分析、同比、环比、趋势分析、ClickHouse查询、TCHouse-C查询、cdwch、SQL生成、GMV、DAU、转化率、支付金额、订单量。
本 Skill 包含 3 个子能力:①自然语言转 SQL(NL2SQL)②智能图表可视化推荐 ③中文业务结论摘要撰写建议。
何时不触发:慢 SQL 诊断与自动调优(已有 SQL 的性能分析)、集群健康诊断与故障排查(监控指标/告警/节点故障)、集群选型与架构推荐、智能建表与数据建模、集群扩缩容操作、权限管理、数据导入导出等非 SQL 生成相关问题不走本 Skill。
allowed-tools:
- TCHouseCDescribeInstance
- TCHouseCDescribeInstanceNodes
- TCHouseCDescribeTableSchema
- ask_user # WorkBuddy 中为 AskUserQuestion
- show_widget
---
# 自然语言 SQL 生成(NL2SQL)
> ⚠️ **能力范围说明**:本 Skill 当前**仅负责 SQL 生成与分析建议**,不直接连接集群执行 SQL。生成的 SQL 语句需由用户自行复制到 TCHouse-C 控制台 SQL 工作区(DMS)或其他 ClickHouse 客户端执行。执行后如需图表可视化,用户可将结果数据回传给 Agent,Agent 会用 `show_widget` 渲染图表并给出结论摘要。
## 概述
本 Skill 提供 TCHouse-C(ClickHouse)集群的自然语言 SQL 生成能力,包含三个子能力:
1. **自然语言转 SQL(NL2SQL)**:理解用户自然语言描述的分析需求,结合表结构生成对应的 ClickHouse SQL
2. **智能图表可视化推荐**:根据用户描述的分析意图和预期结果特征,推荐合适的图表类型(用户回传数据后可直接用 `show_widget` 渲染)
3. **中文业务结论摘要撰写建议**:针对预期结果给出结论撰写模板,用户执行 SQL 后可基于模板输出面向业务人员的结论
## 依赖与运行环境
本 Skill 的所有调用通过 MCP Tool 完成(云 API 类工具由平台封装为 MCP Tool,Agent 直接调用工具名即可)。
**依赖工具清单**:
| # | Tool 名称 | 能力定位 |
| --- | ----------------------------- | ---------------------------------------------------------------------------------------- |
| 1 | TCHouseCDescribeInstance | 集群基本信息获取(用于确认集群可用性) |
| 2 | TCHouseCDescribeInstanceNodes | 获取集群数据节点 IP 列表(`TCHouseCDescribeTableSchema` 的**必要前置依赖**,见步骤 1.5) |
| 3 | TCHouseCDescribeTableSchema | 根据表名和**数据节点 IP** 获取建表 DDL(提供 SQL 生成上下文) |
| 4 | ask_user | 向用户询问确认信息(WorkBuddy 中为 AskUserQuestion) |
| 5 | show_widget | 用户回传结果数据后,渲染 Chart.js 图表 |
## 凭证 / 环境变量
- `instance_id`:集群实例 ID,需通过 `ask_user`(WorkBuddy 中为 `AskUserQuestion`)向用户询问获取
- `region_id`:地域信息,可能是 `RegionId` 数字、`Region` 字符串或中文地域名;缺失时通过 `ask_user` 询问用户获取
> ⚠️ **地域参数强制规则**:本 Skill 依赖的全部工具(`TCHouseCXxx` 系)都只接受 **`Region` 字符串**(如 `ap-guangzhou`)。**任何工具调用前**都必须先按 [地域映射表](references/region-mapping.md) 将上下文中的地域信息(无论是中文名、英文串还是 `RegionId` 数字)统一转为 `Region` 字符串后再传入,禁止凭记忆填写。详见 [工具传参形式速查](references/region-mapping.md#工具传参形式速查)。
> 💡 **多平台兼容说明**:本文档中所有提到的 `ask_user` 工具,在 WorkBuddy 平台中对应为 `AskUserQuestion`。后文不再重复标注。
## 地域映射与缓存机制
### 地域映射规则
> ⚠️ **核心原则**:本 Skill 依赖的全部工具都只接受 `Region` 字符串。无论用户提供的是中文名、英文串还是 `RegionId` 数字,都必须按 [地域映射表](references/region-mapping.md) 统一转为 `Region` 字符串后再使用。
当用户提供地域信息时,使用 [地域映射表](references/region-mapping.md) 进行统一处理:
1. **`RegionId` 数字输入**:如上下文中 `region_id` 为 `1`、`8` 等数字,直接按映射表查出对应的 `Region` 字符串(`1` → `ap-guangzhou`、8 → `ap-beijing`)
2. **`Region` 字符串输入**:如已为 `ap-guangzhou`,直接使用,无需转换
3. **精确匹配优先**:如果用户给出的地域名称能精确匹配到地域映射表中的"地域名称"列,直接使用对应的 `Region` 值
4. **常见简称映射**:支持常见地域简称(如"广州"→`ap-guangzhou`、"上海"→`ap-shanghai`、"北京"→`ap-beijing`)
5. **金融区识别**:用户提到"金融"、"金融区"时,优先匹配带 `-fsi` 后缀的地域
6. **所属地区模糊匹配**:如果用户只说了"华南地区"等大区名称,且该大区下有多个地域,需通过 `ask_user` 让用户确认具体地域
### 地域选择优化流程
**步骤 0.1:地域参数确认与映射**
**判断逻辑**:
- ✅ 参数齐全(region_id 已提供)→ 按映射表转为 `Region` 字符串后进入步骤 1
- ❌ `region_id` 缺失但用户问题中包含地域信息(中文名/英文串/数字 ID)→ 按映射表统一转为 `Region` 字符串后进入步骤 1
- ❌ `region_id` 缺失且用户问题中无地域信息 → 调用 `ask_user` 询问用户确认地域
**询问话术示例**:
"请确认您要分析的 TCHouse-C 集群所在地域(如:广州、上海、北京等)"
**缓存机制**:
- 用户确认的地域信息(`Region` 字符串)在当前会话中缓存,避免重复询问
- 如果地域调用返回 `ResourceNotFound`,提示用户确认地域是否正确,而非自动尝试其他地域
## 核心工作流
### 步骤 0:参数确认
**必需参数**:
- `instance_id`(集群 ID)
- `region_id`(地域)
**可选参数**(从用户问题中提取,缺失时使用默认值,不自行假设):
- 数据库名:从用户问题中提取,未指定 → 步骤 2 中让用户告知
- 表名:从用户问题中提取,未指定 → 步骤 2 中让用户告知
- 时间范围:从用户问题中提取(如"过去7天"、"本月"),未指定 → 询问用户
- 分析维度/指标:从用户问题中提取
**判断逻辑**:
- ✅ 参数齐全(`instance_id` 和 `region_id` 均已提供)→ **强制**按 [地域映射表](references/region-mapping.md) 将地域信息统一转为 `Region` 字符串(任何输入形式都要过这一步:中文名、英文串、数字 ID 都不例外),转换后进入步骤 1
- ❌ `instance_id` 缺失 → 调用 `ask_user` 询问集群实例 ID
- ❌ `region_id` 缺失且用户问题中无任何地域信息 → 调用 `ask_user` 询问用户地域
- ❌ 地域信息在映射表中匹配不到(或大区模糊,如"华南地区")→ 调用 `ask_user` 确认后再转换
### 步骤 1:确认集群信息
调用 `TCHouseCDescribeInstance` 获取集群基本信息,确认目标集群存在且可用。
**判断逻辑**:
- ✅ 集群状态为 `Serving` → 进入步骤 1.5
- ❌ 集群状态异常 → 告知用户集群当前不可用,但可继续基于用户提供的表结构信息生成 SQL(本 Skill 不实际执行 SQL)
- ❌ 调用失败(AuthFailure)→ 报告错误,提示检查权限
- ❌ 调用失败(ResourceNotFound)→ 检查 instance_id 格式(应为 `cdwch-` 前缀),格式错则修正重试,格式对则请用户确认
> ⚠️ **重要提醒**:`TCHouseCDescribeInstance` 返回的 `AccessInfo` 中的 IP 是 **VIP/代理地址**,**不是**数据节点 IP,**不能**用于步骤 2 的 `TCHouseCDescribeTableSchema` 调用(传入会得到 `Exists=false`)。数据节点 IP 必须通过步骤 1.5 单独获取。
### 步骤 1.5:获取数据节点 IP(步骤 2 的必要前置)
**目的**:`TCHouseCDescribeTableSchema` 的 `NodeIp` 参数要求传入**数据节点真实 IP**,必须先通过本步骤获取。
**调用方式**:
- 调用 `TCHouseCDescribeInstanceNodes`,传参 `NodeRole=DATA`(可加 `ForceAll=true` 一次性拿全)
- 从返回的 `InstancesList` 中任选一个 `Status` 正常的节点 `Ip` 作为后续 `TCHouseCDescribeTableSchema` 的 `NodeIp` 入参
- 本轮分析中该 IP 可缓存复用,避免每次表结构查询都重复调用
**判断逻辑**:
- ✅ 成功拿到至少一个可用数据节点 IP → 进入步骤 2
- ❌ 返回节点列表为空或全部异常 → 告知用户集群数据节点当前不可用,可请用户直接提供表 DDL(走步骤 2.3 兜底)
- ❌ 调用失败(AuthFailure/ResourceNotFound)→ 按错误码表处理
> ⚠️ **禁止事项**:
>
> - 禁止把 `TCHouseCDescribeInstance` 的 `AccessInfo` IP 当作 `NodeIp`(那是 VIP,`DescribeTableSchema` 会返回 `Exists=false`)
> - 禁止凭记忆或猜测填 IP
### 步骤 2:收集表结构信息
**目的**:了解用户目标表的库表结构,为 SQL 生成提供上下文。
由于本 Skill 不直接连接集群执行 `SHOW DATABASES` / `SHOW TABLES`,表结构信息通过以下方式获取(按优先级):
**2.1 快速路径:直接调用 DescribeTableSchema**
如果用户已明确 **数据库名 + 表名**:
- 调用 `TCHouseCDescribeTableSchema` 获取表的建表 DDL,其中 `NodeIp` **必须**使用步骤 1.5 获取到的数据节点 IP(禁止使用 `DescribeInstance` 返回的 VIP)
- 从 DDL 中提取列名、类型、注释、排序键、分区键等关键信息
- 如返回 `Exists=false`,优先怀疑 `NodeIp` 传错(是否误用了 VIP),核对后重试;仍为 false 再向用户确认库表名
**2.2 参数缺失时的兜底流程**
如果用户未明确数据库名或表名:
- 通过 `ask_user` 一次性询问用户 **数据库名 + 表名**(避免多轮追问)
- 询问话术示例:"请告知需要分析的数据库名和表名(例如 `db_analytics.orders`)。如果不确定具体表名,可以先在 TCHouse-C 控制台 SQL 工作区执行 `SHOW TABLES FROM 数据库名` 查看后再告诉我。"
- 用户回复后进入 2.1
> ⚠️ **禁止基于用户描述的维度/指标猜测表名**(如"渠道支付金额"→ payments/orders、"用户注册数"→ users 等猜测均不可靠)。表名必须由用户明确提供。
**2.3 用户直接提供 DDL 的情况**
用户可能会直接把建表 DDL 粘贴过来。此时:
- 直接从用户提供的 DDL 中解析列信息,跳过 `TCHouseCDescribeTableSchema` 调用
- 进入步骤 3
### 步骤 3:理解需求与生成 SQL
**3.1 需求理解**:
从用户自然语言中提取:
- **分析目标**:统计什么(如"支付金额"、"用户数")
- **时间范围**:什么时间段(如"过去7天"、"本月")
- **分组维度**:按什么维度汇总(如"按天"、"按渠道")
- **过滤条件**:有什么限制(如"只看VIP用户")
- **排序/限制**:TOP N、升序/降序
- **可视化意图**:趋势图、对比图、占比图等(用于步骤 4 图表推荐)
**3.2 SQL 生成**:
基于表结构和需求理解,生成 ClickHouse SQL。遵循 [SQL 生成规范](references/sql-generation-guide.md#生成规范)。
**关键原则**:
- 必须使用分区键过滤(避免全表扫描)
- 只 SELECT 需要的列(ClickHouse 列式存储,SELECT \* 性能差)
- 时间函数使用 ClickHouse 原生函数(toDate/toYYYYMM/toStartOfDay 等)
- 大表 JOIN 时小表放右侧
- 聚合查询必须有 GROUP BY
- 结果行数建议控制在 1000 行以内(默认加 `LIMIT 1000`,超过时告知用户)
**3.3 SQL 输出规范**:
向用户交付 SQL 时必须包含以下内容:
1. **完整 SQL 语句**:使用 Markdown 代码块(`sql ... `)包裹,方便用户复制
2. **占位符标注**:如 SQL 中包含需用户按实际情况调整的常量(如日期范围、过滤条件的具体值),使用 `-- TODO: ...` 注释明确标出
3. **执行方式提示**:在 SQL 下方附一句执行指引:
> 请将上述 SQL 复制到 TCHouse-C 控制台「SQL 工作区(DMS)」执行;执行完成后如需生成图表和结论摘要,可将结果数据(表格或 JSON 格式)回传给我。
4. **设计说明**:简述 SQL 关键设计点(分区键命中情况、聚合逻辑、性能注意事项)
### 步骤 4:图表可视化推荐
根据用户描述的分析意图和 SQL 预期返回的数据结构(列数、维度类型),推荐合适的图表类型。详见 [可视化推荐规则](references/visualization-guide.md#图表选择规则)。
**图表选择决策树**:
| 数据特征 | 分析意图 | 推荐图表 |
| ---------------------- | ---------- | -------------- |
| 时间序列 + 数值 | 趋势变化 | 📈 折线图 |
| 分类 + 数值(≤ 10 类) | 对比大小 | 📊 柱状图 |
| 分类 + 占比(≤ 8 类) | 占比分布 | 🥧 饼图/环形图 |
| 两个数值维度 | 相关性 | 散点图 |
| 时间 + 分类 + 数值 | 多系列趋势 | 📈 多折线图 |
| 分类 + 多指标 | 多维对比 | 📊 分组柱状图 |
| 单一数值 | 关键指标 | 🔢 数字卡片 |
| 排名(TOP N) | 排序对比 | 📊 横向柱状图 |
**输出方式**:
- **场景 A(用户仅要 SQL)**:在 SQL 输出下方以文字形式给出推荐图表类型及理由,例如:"建议使用**多折线图**展示各渠道的每日支付金额趋势"
- **场景 B(用户回传了 SQL 执行结果数据)**:直接调用 `show_widget` 用 Chart.js 渲染图表,并附 Markdown 结果表格
> 💡 **show_widget 图表生成要点**(仅场景 B):
>
> - 使用 Chart.js 库渲染图表
> - 根据数据特征配置合适的图表选项(标题、坐标轴标签、图例、颜色方案等)
> - 标签使用中文
### 步骤 5:业务结论摘要建议
**场景 A(用户仅要 SQL)**:给出结论撰写模板,说明用户执行完 SQL 后可按此模板整理结论。
**场景 B(用户回传了结果数据)**:直接基于数据生成中文业务结论。详见 [结论生成规范](references/visualization-guide.md#业务结论规范)。
**结论结构**:
1. **核心发现**(1-2 句话概括最重要的结论)
2. **数据支撑**(关键数字和对比)
3. **趋势判断**(上升/下降/平稳,环比/同比变化)
4. **异常提示**(如有明显异常值或突变)
5. **建议行动**(基于数据的业务建议,可选)
**输出要求**:
- 使用中文,面向非技术人员
- 数字使用千分位分隔(如 1,234,567)
- 百分比保留 2 位小数
- 金额标注单位(元/万元/亿元)
- 避免使用技术术语(如"聚合"、"JOIN")
## 频率控制
| 限制 | 阈值 | 说明 |
| -------------------------------- | ------------- | ---------------------- |
| 工具总调用频率 | ≤ 15 次/分钟 | 避免触发平台限流 |
| TCHouseCDescribeTableSchema 调用 | ≤ 5 次/轮分析 | 避免重复拉取相同表结构 |
**超限处理**:连续收到 `RequestLimitExceeded` → 等 5 秒重试,连续 3 次仍失败 → 降低调用频率,告知用户被限流。
## 错误码与处理策略
| 错误码/场景 | Agent 行为 |
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `AuthFailure.*` | 报告鉴权失败,提示用户检查集群访问权限 |
| `ResourceNotFound` | 检查 ID 格式(`cdwch-` 前缀);格式错 → 修正重试;格式对 → 请用户确认 |
| `InvalidParameter.*` | 检查参数格式,尝试修正后重试 1 次;无法修正 → 报告具体问题 |
| `UnsupportedRegion` | 该地域未开通 TCHouseC 产品。**不重试、不自动切换地域**,必须调用 `ask_user` 让用户确认地域。详见 [error-handling.md §1](references/error-handling.md#1-unsupportedregion该接口不支持此地域访问) |
| `InternalError` | 等 3 秒重试,最多 3 次;仍失败 → 报告错误码 + RequestId |
| `RequestLimitExceeded` | 等 5 秒重试;连续 3 次 → 降低频率,告知被限流 |
| 表/列不存在 | 提示用户确认表名和数据库名,重新获取表结构 |
| 网络超时 | 等 3 秒重试,最多 3 次;仍失败 → 告知用户服务暂时不可用 |
| 兜底(未列出错误码) | 报告完整错误信息 + RequestId |
## 安全规则
1. **本 Skill 仅生成 SELECT 查询**:生成的 SQL 必须是 SELECT 语句,严禁生成 INSERT/UPDATE/DELETE/DROP/ALTER/TRUNCATE 等写操作
2. **SQL 注入防护**:用户输入不直接拼接到 SQL 中,通过参数化或严格校验处理
3. **数据量控制**:SQL 中默认加 `LIMIT 1000`,避免用户执行时返回海量数据
4. **敏感数据提示**:如果 SQL 可能涉及个人隐私字段(手机号、身份证等),在输出前提醒用户注意数据安全
5. **不直接执行**:本 Skill 只生成 SQL,不连接集群执行;用户在自行执行前应确认 SQL 无误
## 检查清单(各步骤执行前自动验证)
### 步骤 0:参数确认检查清单
- [ ] 确认 `instance_id` 和 `region_id` 参数是否齐全
- [ ] 无论用户提供的是中文地域名、英文 `Region` 字符串还是 `RegionId` 数字,是否已按地域映射表统一转为 `Region` 字符串
- [ ] 是否需要通过 `ask_user` 询问缺失参数
### 步骤 1.5:数据节点 IP 检查清单
- [ ] 是否已通过 `TCHouseCDescribeInstanceNodes`(`NodeRole=DATA`)获取到至少一个可用数据节点 IP
- [ ] 是否**没有**使用 `TCHouseCDescribeInstance` 的 `AccessInfo` IP(VIP)作为 `NodeIp`
### 步骤 2:表结构收集检查清单
- [ ] 是否已明确数据库名和表名(否则需 `ask_user` 询问)
- [ ] 是否已通过 `TCHouseCDescribeTableSchema` 获取表结构,或用户已提供 DDL
- [ ] 调用 `TCHouseCDescribeTableSchema` 时 `NodeIp` 是否使用步骤 1.5 拿到的数据节点 IP
- [ ] 是否已提取列名、类型、注释、分区键、排序键等关键信息
### 步骤 3:SQL 生成检查清单
- [ ] WHERE 条件是否包含分区键过滤(避免全表扫描)
- [ ] 是否避免使用 `SELECT *`(只选需要的列)
- [ ] 时间范围是否使用动态函数(`today()`、`now()` 而非硬编码)
- [ ] 中文列名是否用反引号包裹
- [ ] 非聚合查询是否添加了 `LIMIT`
- [ ] SQL 是否用 Markdown 代码块包裹便于用户复制
- [ ] 是否附上执行方式提示(引导用户到控制台 SQL 工作区执行)
### 步骤 4:可视化检查清单
- [ ] 图表类型是否匹配数据特征和分析意图
- [ ] 用户仅要 SQL 时是否用文字形式给出推荐图表类型
- [ ] 用户回传结果数据时是否用 `show_widget` 直接渲染
- [ ] 图表标签是否使用中文
### 步骤 5:结论生成检查清单
- [ ] 结论是否使用中文面向业务人员
- [ ] 数字是否使用千分位分隔
- [ ] 是否包含核心发现、数据支撑、趋势判断
- [ ] 是否避免使用技术术语
## 高频经验提醒
| 经验 | 触发时机 | 说明 |
| ------------------------ | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| 本 Skill 不直接执行 SQL | 每次交付 SQL 时 | 必须提醒用户到 TCHouse-C 控制台 SQL 工作区(DMS)自行执行;如需生成图表可回传结果数据 |
| 时间过滤必须命中分区键 | 步骤 3 生成 SQL 时 | WHERE 条件必须包含分区键字段,优先使用 `today()` 等动态函数 |
| 中文列名需要反引号 | 步骤 3 生成 SQL 时 | ClickHouse 中文列名必须用反引号包裹,否则语法错误 |
| 表名不能猜测 | 步骤 2 收集表结构时 | 禁止基于用户描述的维度/指标猜测表名,必须由用户明确提供 |
| NodeIp 只能用数据节点 IP | 步骤 1.5 / 步骤 2 | `TCHouseCDescribeTableSchema` 的 `NodeIp` 必须传 `TCHouseCDescribeInstanceNodes` 返回的数据节点 IP;`DescribeInstance` 的 `AccessInfo` 是 VIP,传入会返回 `Exists=false` |
| 默认加 LIMIT 1000 | 步骤 3 生成 SQL 时 | 非明确要求全量的场景,SQL 默认加 `LIMIT 1000`,避免用户执行时返回海量数据 |
| 地域缺失必须询问 | 步骤 0 参数确认时 | 不要自动猜测地域;无论用户提供中文名、英文串还是 `RegionId` 数字,都必须按地域映射表统一转为 `Region` 字符串 |
Files in this skill
- SKILL.md
- references/error-handling.md
- references/region-mapping.md
- references/sql-generation-guide.md
- references/visualization-guide.md
Attribution
Related skills
View all in data →Comments
Loading comments…
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.