') + ')', 'gi');
if (regex.test(text)) {
found = true;
var frag = document.createDocumentFragment();
var parts = text.split(regex);
parts.forEach(function(part, i) {
if (i % 2 === 0) {
frag.appendChild(document.createTextNode(part));
} else {
var span = document.createElement('span');
span.className = 'userscript-highlight';
span.textContent = part;
frag.appendChild(span);
}
});
node.parentNode.replaceChild(frag, node);
}
});
} else if (node.nodeType === 1 && node.childNodes) { // element
var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];
if (!skipTags.includes(node.tagName)) {
Array.from(node.childNodes).forEach(highlight);
}
}
}
highlight(document.body);
// Re-highlight on dynamic content
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(m) {
m.addedNodes.forEach(function(node) {
if (node.nodeType === 1 || node.nodeType === 3) highlight(node);
});
});
});
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); }
})();
(function(){
try {
var __m = "*";
var __re = new RegExp('^' + ".*" + ', 'i');
if (__m === '*' || __re.test(location.href)) {
// Strip utm_, fbclid, gclid, etc. from all links on page
(function() {
var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',
'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',
'ref', 'ref_src', 'source', 'medium', 'campaign'];
function cleanUrl(url) {
try {
var u = new URL(url, window.location.origin);
var changed = false;
trackingParams.forEach(function(p) {
if (u.searchParams.has(p)) {
u.searchParams.delete(p);
changed = true;
}
});
return changed ? u.toString() : url;
} catch (e) {
return url;
}
}
function cleanLinks() {
document.querySelectorAll('a[href]').forEach(function(a) {
var clean = cleanUrl(a.href);
if (clean !== a.href) a.href = clean;
});
}
cleanLinks();
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(m) {
m.addedNodes.forEach(function(node) {
if (node.nodeType === 1) {
if (node.tagName === 'A') cleanLinks();
node.querySelectorAll('a[href]').forEach(function(a) {
var clean = cleanUrl(a.href);
if (clean !== a.href) a.href = clean;
});
}
});
});
});
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); }
})();
(function(){
try {
var __m = "youtube.com";
var __re = new RegExp('^' + "youtube\\.com" + ', 'i');
if (__m === '*' || __re.test(location.href)) {
// Auto-enable theater mode on YouTube
(function() {
function tryTheater() {
var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]');
if (btn && !btn.classList.contains('activated')) {
btn.click();
}
}
// Try immediately
tryTheater();
// Try after navigation (SPA)
var lastUrl = location.href;
setInterval(function() {
if (location.href !== lastUrl) {
lastUrl = location.href;
setTimeout(tryTheater, 500);
}
}, 1000);
// Also try on player load
var observer = new MutationObserver(tryTheater);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); }
})();
(function(){
try {
var __m = "*";
var __re = new RegExp('^' + ".*" + ', 'i');
if (__m === '*' || __re.test(location.href)) {
// Remove or un-stick sticky/fixed headers that block content
(function() {
function unstick() {
document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) {
if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {
el.style.position = 'static';
el.style.top = 'auto';
el.style.zIndex = 'auto';
}
});
}
unstick();
var observer = new MutationObserver(unstick);
observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });
})();
}
} catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); }
})();
})();
GitHub - RingKoAI/Ring-CLI · GitHub
Repository files navigation # 从源码构建(需要 Rust 1.85+)
git clone https://github.com/Ringaire/Ring-CLI.git
cd RingCLI
cargo install --path crates/ring-cli # 或直接运行
cargo run --release# 方式一:交互式向导
ring
# 输入 /connect,选择 provider,输入 API key# 方式二:快速连接
ring
# /connect anthropic sk-ant-xxx# 方式三:环境变量export ANTHROPIC_API_KEY=" sk-ant-xxx" export OPENAI_API_KEY=" sk-xxx" export DEEPSEEK_API_KEY=" sk-xxx" 配置文件位于 ~/.ring/config/settings.jsonc(支持注释)。
🤖 34 个 Provider — Anthropic / OpenAI / Gemini / DeepSeek / 智谱 / 通义千问 / MiniMax / 小米 / HuggingFace / Cloudflare 等,OpenAI OAuth2 登录 🛠️ 17 个内置工具 — bash、文件读写编辑、搜索、Web、LSP、TODO、会话管理 🎭 多 Agent 编排 — 子 agent 派生 + role-based 选模 + 视图分离 🔐 权限五档 — Ask(只读)→ Edit(改码)→ Plan(规划)→ Build(全开)→ Agent(自主) 🧠 七级思考程度 — /effort off|minimal|low|medium|high|xhigh|max,下拉菜单 + Shift+Tab 循环 📝 可编排 Prompt — SKILL.md 支持 $1$@${N:-default}${@:N} 参数替换 📂 项目级配置 — .ring/ 目录:SYSTEM.md / APPEND_SYSTEM.md / tool.json / mode / doc 📦 会话持久化 — JSONL 存储 + 上下文自动压缩 🔌 MCP 兼容 — tool.json / mcp_server.json / .mcp.json,多路径发现 🧩 Skill / Doc 系统 — SKILL.md(Markdown + frontmatter),兼容 .agents/skills/ 与 .ring/doc/ 🖥️ TUI 终端界面 — Ratatui + 自实现 Markdown 渲染 + 宽度感知换行 输入 / 查看:
命令 说明 /connect配置 provider(向导 / 快速连接 / ChatGPT OAuth2) /logout移除已存储的 provider 凭据(下拉选择 / /logout <provider>) /model模型选择器(跨 provider 分组 + 搜索) /mode权限模式选择器(ask/edit/plan/build/agent) /effort思考程度下拉菜单(off/minimal/low/medium/high/xhigh/max) /thinkExtended thinking(on/off [budget]) /thinking折叠/展开推理过程 /sessions会话管理 /compact压缩上下文 /new新建会话 /help完整命令列表
键 说明 ↑↓多行光标移动 / 历史(空输入时) Tab补全接受 / 权限模式切换 Shift+Tab循环思考程度 (off→minimal→low→medium→high→xhigh→max)Ctrl+T开关 extended thinking Ctrl+O折叠/展开推理过程 Ctrl+↑Ctrl+↓子 agent 视图切换 Alt+↑Alt+↓聊天滚动 Alt+Enter多行输入 @path文件引用 粘贴 file:// 自动转 @path
Provider 类型 Anthropic 原生 SDK + OAuth2 OpenAI 原生 SDK + ChatGPT OAuth2 Google Gemini 原生 SDK DeepSeek / Groq / Mistral / Together / OpenRouter / xAI OpenAI 兼容 Moonshot / SiliconFlow / Zhipu / Baidu / NVIDIA OpenAI 兼容 Cerebras / DeepInfra / Fireworks / Perplexity / Cohere OpenAI 兼容 HuggingFace / MiniMax / MiniMax-CN / Qwen / Qwen-CN OpenAI 兼容 Xiaomi / Xiaomi-AMS / Xiaomi-SGP / ZAI / ZAI-CN / Ant-Ling OpenAI 兼容 Cloudflare-Workers / Cloudflare-Gateway / Vercel-Gateway / OpenCode OpenAI 兼容 Ollama / LM Studio 本地模型(无需 key) Custom 任意 OpenAI 兼容 API
~/.ring/
├── config/
│ ├── settings.jsonc # 主配置(支持注释)
│ ├── providers.json # provider 覆盖
│ ├── tool.json # MCP 工具(新统一格式)
│ ├── mcp_server.json # MCP 工具(旧格式兼容)
│ ├── .mcp.json # Claude Code 兼容
│ ├── SYSTEM.md # 自定义系统提示词(替换默认)
│ └── APPEND_SYSTEM.md # 追加系统提示词
├── skills/ # 全局技能
├── doc/ # 全局文档(skill 新命名)
├── prompts/ # 提示词模板
├── mode/ # 模式定义
└── sessions/ # 会话存储(JSONL)
./.ring/
├── settings.jsonc # 项目配置
├── tool.json # 项目 MCP 工具
├── mcp_server.json # 项目 MCP 工具(旧格式)
├── .mcp.json # Claude Code 兼容
├── SYSTEM.md # 项目自定义系统提示词
├── APPEND_SYSTEM.md # 项目追加系统提示词
├── skills/ # 项目技能
├── doc/ # 项目文档
├── mode/ # 项目模式定义
│ └── {mode}.md # 模式提示词
└── workflow.json # 模型编排(规划中)
RingCLI 会自动发现并注入以下文件到系统提示词:
文件 说明 发现方式 AGENTS.md项目指令 从 cwd 向上遍历至 git 根 CLAUDE.md兼容 Pi / Claude Code 从 cwd 向上遍历至 git 根 .ring/SYSTEM.md自定义系统提示词 项目级 > 全局 .ring/APPEND_SYSTEM.md追加到系统提示词末尾 项目级 > 全局
按以下顺序合并(近覆盖远):
cwd/tool.json — 工作目录新格式cwd/mcp_server.json — 工作目录旧格式cwd/.mcp.json — Claude Code 兼容(向上遍历)cwd/.ring/{tool,mcp_server,.mcp}.json — 项目 .ring/~/.ring/config/{tool,mcp_server,.mcp}.json — 全局AGPL-3.0
Made with ❤️ by Ringaire玲汐
You can’t perform that action at this time.