开篇:我发现自己用 AI 的方式有问题
2026 年初,我做了一个统计:在一个普通的工作日里,我打开 ChatGPT/Claude/Cursor 的次数超过 50 次。
有些使用是合理的——调试一段难缠的代码、快速生成一个正则、解释一个我不熟悉的 API。但更多的使用属于"肌肉记忆":
- 写 SQL 之前先问 AI(其实我自己想 10 秒就能写出来)
- 报错了直接复制粘贴给 AI(其实看一眼错误信息就能解决)
- 写 commit message 也让 AI 生成(这个真的不需要)
最让我警醒的是:我开始在"思考"之前先问 AI 了。不是先想清楚问题再求助 AI,而是直接把问题丢出去,让它替我想。
这个问题不是 AI 工具的错。它是我自己的使用习惯出了问题。
所以我决定做一个 Chrome 扩展——不是为了完全阻止我用 AI,而是让我在每次使用 AI 之前停一下,问自己三个问题:
- 我真的需要 AI 来完成这个任务吗?
- 如果自己先试试,我能解决吗?
- 如果求助 AI,我应该怎么描述问题才能学得最多?
这篇文章就是做这个扩展的全过程。
一、设计思路
1.1 核心原则
我设计这个扩展的原则只有三条:
- 不封堵、不禁止——AI 工具本身没错,错的是无意识使用
- 最小干预——每次使用 AI 之前弹出一个小提示,1 秒看完
- 可自定义——每个人使用 AI 的方式不同,规则应该可调
1.2 扩展的逻辑
用户打开 ChatGPT / Claude / Cursor
↓
扩展检测到 AI 工具的页面
↓
检查是否在"免打扰名单"中
├── 是 → 放行
└── 否 → 检查这个域名的使用次数
├── 今天首次 → 跳过(不打扰)
├── 第 N 次 → 弹出"意图检查"提示
└── 超过每日上限 → 弹出更强烈的提醒
二、Chrome 扩展基础结构
ai-intentional/
├── manifest.json # 扩展配置
├── background.js # 后台脚本 (Service Worker)
├── content.js # 内容脚本 (注入到 AI 页面)
├── popup.html # 弹窗 UI
├── popup.js # 弹窗逻辑
├── options.html # 设置页面
├── options.js # 设置逻辑
└── icons/
├── icon16.png
├── icon48.png
└── icon128.png
2.1 manifest.json
{
"manifest_version": 3,
"name": "Intentional AI",
"version": "1.0.0",
"description": "在每次使用 AI 工具之前,提醒你思考:我真的需要 AI 吗?",
"permissions": [
"storage",
"tabs",
"alarms"
],
"host_permissions": [
"https://chatgpt.com/*",
"https://claude.ai/*",
"https://chat.openai.com/*",
"https://cursor.sh/*",
"https://gemini.google.com/*",
"https://www.perplexity.ai/*"
],
"background": {
"service_worker": "background.js"
},
"content_scripts": [
{
"matches": [
"https://chatgpt.com/*",
"https://claude.ai/*",
"https://chat.openai.com/*",
"https://gemini.google.com/*",
"https://www.perplexity.ai/*"
],
"js": ["content.js"],
"run_at": "document_end"
}
],
"action": {
"default_popup": "popup.html",
"default_icon": {
"16": "icons/icon16.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
}
},
"options_page": "options.html"
}
三、核心实现
3.1 后台统计:追踪 AI 使用量
// background.js
//
// 追踪每日 AI 工具使用次数,用于触发意图检查
const AI_DOMAINS = {
'chatgpt.com': 'ChatGPT',
'chat.openai.com': 'ChatGPT',
'claude.ai': 'Claude',
'cursor.sh': 'Cursor',
'gemini.google.com': 'Gemini',
'perplexity.ai': 'Perplexity',
};
const STORAGE_KEY = 'ai_usage';
// 每次访问 AI 页面时,更新使用计数
chrome.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => {
if (changeInfo.status !== 'complete' || !tab.url) return;
const domain = getDomain(tab.url);
if (!domain || !AI_DOMAINS[domain]) return;
await incrementUsage(domain, AI_DOMAINS[domain]);
});
function getDomain(url) {
try {
return new URL(url).hostname.replace('www.', '');
} catch {
return null;
}
}
async function incrementUsage(domain, name) {
const today = new Date().toISOString().split('T')[0]; // YYYY-MM-DD
const storage = await chrome.storage.local.get(STORAGE_KEY);
const usage = storage[STORAGE_KEY] || {};
if (!usage[today]) {
usage[today] = {};
}
if (!usage[today][domain]) {
usage[today][domain] = { count: 0, name };
}
usage[today][domain].count += 1;
await chrome.storage.local.set({ [STORAGE_KEY]: usage });
}
// 获取今日用量
async function getTodayUsage() {
const today = new Date().toISOString().split('T')[0];
const storage = await chrome.storage.local.get(STORAGE_KEY);
const usage = storage[STORAGE_KEY] || {};
return usage[today] || {};
}
// 消息处理
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.type === 'getUsage') {
getTodayUsage().then(sendResponse);
return true; // 保持通道开放
}
if (request.type === 'checkAndNotify') {
shouldShowIntentPrompt(request.domain).then(sendResponse);
return true;
}
});
3.2 意图检查弹窗
// content.js
//
// 在 AI 页面注入意图检查弹窗
const PROMPT_MESSAGES = [
{
threshold: 5, // 今天第 5 次打开 AI
title: "🧠 慢下来",
message: "这是你今天第 {count} 次使用 AI。\n\n问自己:我试过自己解决了吗?",
dismissText: "想好了,继续"
},
{
threshold: 15,
title: "⚡ 检查你的意图",
message: "你已经使用了 {count} 次 AI。是不是有些问题可以自己先试试?",
dismissText: "继续,但这个真的需要"
},
{
threshold: 30,
title: "🔋 充电提醒",
message: "你今天已经用了 {count} 次 AI。\n\n停下来休息一下可能比继续用 AI 更有效。\n\n喝完水再回来。",
dismissText: "好的,先休息",
showAfter: 5000 // 展示 5 秒才能关闭
},
];
async function init() {
const domain = window.location.hostname;
// 检查是否应该提示
const response = await chrome.runtime.sendMessage({
type: 'checkAndNotify',
domain
});
if (!response || !response.shouldPrompt) return;
const count = response.count;
// 找到当前次数对应的提示
const promptConfig = PROMPT_MESSAGES
.filter(p => count >= p.threshold)
.pop();
if (!promptConfig) return;
showIntentPrompt(promptConfig, count);
}
function showIntentPrompt(config, count) {
// 创建遮罩层
const overlay = document.createElement('div');
overlay.style.cssText = `
position: fixed;
top: 0; left: 0; right: 0; bottom: 0;
background: rgba(0,0,0,0.5);
z-index: 2147483647;
display: flex;
align-items: center;
justify-content: center;
font-family: -apple-system, system-ui, sans-serif;
`;
// 创建弹窗卡片
const card = document.createElement('div');
card.style.cssText = `
background: white;
border-radius: 16px;
padding: 32px;
max-width: 420px;
width: 90%;
box-shadow: 0 20px 60px rgba(0,0,0,0.3);
text-align: center;
`;
const canDismiss = !config.showAfter;
card.innerHTML = `
<div style="font-size: 48px; margin-bottom: 16px;">${config.title.split(' ')[0]}</div>
<h2 style="margin: 0 0 12px; color: #1a1a1a;">${config.title}</h2>
<p style="color: #555; line-height: 1.6; margin: 0 0 24px; white-space: pre-line;">
${config.message.replace('{count}', count)}
</p>
<button id="intentional-dismiss"
style="
background: #333; color: white; border: none;
padding: 12px 24px; border-radius: 8px;
font-size: 15px; cursor: pointer;
${canDismiss ? '' : 'opacity: 0.5; pointer-events: none;'}
">
${config.dismissText}
${config.showAfter ? ` (${config.showAfter / 1000}s)` : ''}
</button>
`;
overlay.appendChild(card);
document.body.appendChild(overlay);
// 如果没有设置延迟,直接可以关闭
if (!config.showAfter) {
document.getElementById('intentional-dismiss').onclick = () => {
overlay.remove();
saveDismissed(); // 记录这次提示
};
} else {
// 延迟后可关闭
setTimeout(() => {
const btn = document.getElementById('intentional-dismiss');
if (btn) {
btn.style.opacity = '1';
btn.style.pointerEvents = 'auto';
btn.textContent = config.dismissText;
btn.onclick = () => {
overlay.remove();
saveDismissed();
};
}
}, config.showAfter);
}
}
function saveDismissed() {
// 记录提示已出示,避免过于频繁
chrome.storage.local.set({ lastPrompt: Date.now() });
}
// 页面加载后执行
init();
3.3 后台检查逻辑
// background.js — checkAndNotify handler(接之前的部分)
async function shouldShowIntentPrompt(domain) {
const usage = await getTodayUsage();
const domainUsage = usage[domain];
if (!domainUsage) return { shouldPrompt: false };
const count = domainUsage.count;
// 检查上次提示是否太近(至少间隔 3 次使用)
const storage = await chrome.storage.local.get('lastPrompt');
const lastPrompt = storage.lastPrompt || 0;
// 如果上次提示在 5 分钟内,跳过
if (Date.now() - lastPrompt < 5 * 60 * 1000) {
return { shouldPrompt: false, count };
}
// 只在特定阈值触发
const thresholds = [5, 10, 15, 20, 25, 30, 40, 50];
const shouldPrompt = thresholds.includes(count);
return { shouldPrompt, count };
}
四、设置页面
用户可以通过设置页自定义规则:
// options.js
document.addEventListener('DOMContentLoaded', loadSettings);
document.getElementById('save').addEventListener('click', saveSettings);
async function loadSettings() {
const storage = await chrome.storage.local.get('settings');
const settings = storage.settings || getDefaultSettings();
document.getElementById('threshold-step').value = settings.thresholdStep || 5;
document.getElementById('min-interval').value = settings.minIntervalMinutes || 3;
document.getElementById('daily-limit').value = settings.dailyLimit || 0;
document.getElementById('show-weekly-report').checked = settings.showWeeklyReport || false;
// 加载免打扰域名列表
const whitelist = document.getElementById('whitelist');
(settings.whitelist || []).forEach(domain => {
addWhitelistItem(domain);
});
}
function getDefaultSettings() {
return {
thresholdStep: 5, // 每 5 次提示一次
minIntervalMinutes: 3, // 最小提示间隔
dailyLimit: 0, // 每日上限(0=不限)
showWeeklyReport: true, // 每周报告
whitelist: [],
};
}
async function saveSettings() {
const settings = {
thresholdStep: parseInt(document.getElementById('threshold-step').value) || 5,
minIntervalMinutes: parseInt(document.getElementById('min-interval').value) || 3,
dailyLimit: parseInt(document.getElementById('daily-limit').value) || 0,
showWeeklyReport: document.getElementById('show-weekly-report').checked,
whitelist: getWhitelist(),
};
await chrome.storage.local.set({ settings });
// 保存确认
const btn = document.getElementById('save');
const original = btn.textContent;
btn.textContent = '✓ 已保存';
setTimeout(() => { btn.textContent = original; }, 2000);
}
<!-- options.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Intentional AI - 设置</title>
<style>
body {
width: 500px; padding: 24px; font-family: system-ui, sans-serif;
}
label { display: block; margin: 16px 0 4px; font-weight: 500; }
input[type="number"] { width: 80px; padding: 6px; }
input[type="checkbox"] { margin-right: 8px; }
.section { margin: 24px 0; padding: 16px; background: #f5f5f5; border-radius: 8px; }
.whitelist-item { display: flex; align-items: center; margin: 4px 0; }
.whitelist-item button { margin-left: 8px; }
</style>
</head>
<body>
<h1>⚡ Intentional AI</h1>
<p>让每一次 AI 使用都更有意识</p>
<div class="section">
<h3>提示频率</h3>
<label>每使用 <input type="number" id="threshold-step" min="1" max="50"> 次提示一次</label>
<label>提示最小间隔 <input type="number" id="min-interval" min="1" max="60"> 分钟</label>
<label>每日 AI 上限:<input type="number" id="daily-limit" min="0" max="200"> 次(0=不限)</label>
</div>
<div class="section">
<h3>统计</h3>
<label><input type="checkbox" id="show-weekly-report"> 每周五发送 AI 使用报告</label>
</div>
<div class="section">
<h3>免打扰列表</h3>
<p style="color: #666; font-size: 13px;">这些域名不会显示提示</p>
<div id="whitelist-container"></div>
<div>
<input type="text" id="new-domain" placeholder="example.com" style="width: 200px;">
<button id="add-domain">新增</button>
</div>
</div>
<button id="save" style="margin-top: 16px; padding: 10px 24px; background: #333; color: white; border: none; border-radius: 8px; cursor: pointer;">
保存设置
</button>
<script src="options.js"></script>
</body>
</html>
五、每周报告
一周结束的周五下午 5 点,扩展会发送一份"AI 使用报告":
// background.js — weekly report (接之前)
// 每周五下午 5 点发送报告
chrome.alarms.create('weeklyReport', {
periodInMinutes: 7 * 24 * 60,
delayInMinutes: getDelayToNextFriday5PM()
});
chrome.alarms.onAlarm.addListener(async (alarm) => {
if (alarm.name === 'weeklyReport') {
await sendWeeklyReport();
}
});
function getDelayToNextFriday5PM() {
const now = new Date();
const dayOfWeek = now.getDay(); // 0=Sun, 5=Fri
const targetHour = 17; // 5 PM
let daysUntilFriday = (5 - dayOfWeek + 7) % 7;
if (daysUntilFriday === 0 && now.getHours() >= targetHour) {
daysUntilFriday = 7;
}
const target = new Date(now);
target.setDate(target.getDate() + daysUntilFriday);
target.setHours(targetHour, 0, 0, 0);
return (target - now) / 60000; // 转分钟
}
async function sendWeeklyReport() {
const storage = await chrome.storage.local.get(STORAGE_KEY);
const usage = storage[STORAGE_KEY] || {};
// 计算本周数据
const weekData = calculateWeeklyUsage(usage);
// 构建报告
const report = `
=== 🤖 Intentional AI 周报 ===
时间: ${weekData.startDate} ~ ${weekData.endDate}
本周 AI 使用总量: ${weekData.totalUses} 次
日均: ${weekData.dailyAverage} 次
对比上周: ${weekData.trendText}
按工具分布:
${weekData.breakdown.join('\n')}
每日趋势:
${weekData.dailyTrend.join('\n')}
建议: ${weekData.suggestion}
---
这个工具帮助你在使用 AI 时更有意识。
不是少用,是用得更好。
`.trim();
console.log(report);
// 也可以发送通知
chrome.notifications.create({
type: 'basic',
iconUrl: 'icons/icon48.png',
title: 'Intentional AI 周报',
message: `本周使用了 ${weekData.totalUses} 次 AI。${weekData.suggestion}`,
});
}
function calculateWeeklyUsage(usage) {
// 获取本周的日期
const today = new Date();
const startOfWeek = new Date(today);
startOfWeek.setDate(today.getDate() - today.getDay() - 6);
const dates = Object.keys(usage).sort();
const weekDates = dates.filter(d => d >= startOfWeek.toISOString().split('T')[0]);
// 计算总计
let totalUses = 0;
const perDay = [];
const breakdown = {};
weekDates.forEach(date => {
const dayData = usage[date];
let dayTotal = 0;
Object.entries(dayData).forEach(([domain, data]) => {
dayTotal += data.count;
if (!breakdown[data.name]) breakdown[data.name] = 0;
breakdown[data.name] += data.count;
});
perDay.push({ date, count: dayTotal });
totalUses += dayTotal;
});
const dailyAverage = perDay.length > 0
? (totalUses / perDay.length).toFixed(1)
: 0;
let suggestion = '';
if (totalUses > 200) {
suggestion = '本周使用频率较高,建议适当增加独立解决问题的环节。';
} else if (totalUses > 100) {
suggestion = '使用频率适中。继续保持有意识的 AI 使用习惯。';
} else {
suggestion = '使用频率健康。你在使用 AI 的同时保持了独立思考。';
}
return {
totalUses,
dailyAverage,
trendText: '待计算',
breakdown: Object.entries(breakdown)
.sort((a, b) => b[1] - a[1])
.map(([name, count]) => ` - ${name}: ${count} 次`),
dailyTrend: perDay.map(d => ` - ${d.date}: ${d.count} 次`),
suggestion,
startDate: weekDates[0] || '',
endDate: weekDates[weekDates.length - 1] || '',
};
}
六、我的个人数据
我自己用了这个扩展一个月,数据如下:
第一周: 307 次 (日均 44)
第二周: 271 次 (日均 39) ↓ 12%
第三周: 218 次 (日均 31) ↓ 20%
第四周: 195 次 (日均 28) ↓ 10%
四周变化: 307 → 195,减少了 36%
更重要的不是次数降低,而是质量变化:
- 前两周:"让我问一下 AI……"是默认行为
- 后两周:"这个我自己试试"先出现,失败再求助 AI
最意外的收获:我写代码的速度没有因为少用 AI 而变慢。反而因为更少的上下文切换,进入 flow state 更快了。
七、我的观点:AI 工具的使用应该有意识
写这个扩展的时候,我想清楚了一件事:
AI 工具本身没有好坏,有坏的是无意识的使用习惯。
这和"社交媒体有害"的讨论结构一样——不是社交媒体的错,是它被设计来最大化你的使用时长,而你毫无防备地接受了。
AI 助手也在做类似的事:
- 对话式的界面鼓励你不断提问
- 即时回答让你习惯了"一秒反馈"
- 高质量的回答让你放弃了独立思考
我不是在说"不要用 AI"——恰恰相反,我在认真用它。但我觉得越重要的工具,越不应该无意识地使用。
这个扩展很小,代码不过 300 行。但它的设计理念值得思考:工具应该是帮助我们更好的工具,而不是我们习惯的默认选项。 一个简单的提示框就能改变使用习惯,说明问题不在技术,在于意识。
结尾
这个扩展的代码不到 300 行,完整版本(含设置面板和周报功能)也在 600 行以内。
但它的效果比我预期的好——不是因为代码写得多好,是因为它解决的不是技术问题,而是使用习惯问题。
如果你想试,可以自己用这 300 行代码跑起来。如果你不想试,也请你思考一个问题:你今天用 AI 的每一次,你都想清楚自己为什么用了吗?
文章由文字工作者编写。Chrome 扩展代码基于 Manifest V3 标准。使用数据来自个人实践,仅供参考。