Posts for: #Tech

什么是贡献者许可协议(CLA)

最近我让 AI 给 Slax Reader 加了书签导入功能。代码提交成 PR 后,CLA Assistant 要求我先签一份协议,检查才会通过。我自己也签了一次,顺便弄清楚了 CLA 是什么。

CLA 的全称是 Contributor License Agreement,中文一般叫“贡献者许可协议”。它是代码贡献者和开源项目之间的一份协议,约定项目可以怎样使用贡献者提交的代码、文档和其他内容。

开源许可证规定别人可以怎样使用已经发布的项目。CLA 规定项目可以怎样使用别人提交进来的内容。

签 CLA 代表什么

具体权利要看协议文本。常见的 CLA 会要求贡献者确认几件事:

  • 这份代码是自己写的,或者自己有权提交。
  • 项目可以长期使用、修改和发布这份代码。
  • 与这份代码有关的部分专利,也一并授权给项目使用。
  • 如果代码受到雇主或第三方协议限制,需要提前说明。

贡献者一般仍然保留自己代码的版权,只是把一组明确的使用权授予项目。Apache 基金会对 CLA 的解释也是这样:贡献者保留原有权利,同时允许项目发布和继续开发这些贡献。

这份记录可以减少以后的争议。比如贡献者离职后,公司声称代码属于公司;或者项目几年后调整许可证,却发现没有权利处理早期贡献。CLA 会事先把这些问题写清楚。

有些 CLA 还允许项目把贡献放进采用其他许可证的产品,包括商业或闭源产品。这类权利适合双重许可的项目,也意味着贡献者给出的授权超过了普通开源许可证。

每次提 PR 都要签吗

使用 CLA Assistant 这类工具时,每个 PR 都会检查签署状态。贡献者签过当前版本后,后面的 PR 通常不用重复签。协议内容发生变化时,工具会要求重新签署。

这个步骤仍然会增加贡献门槛。修一个错字或改几行代码,也要先阅读一份法律文件。有些人看到这里就会放弃提交。

另一个轻量做法是 DCO。贡献者在每次提交里加一行 Signed-off-by,确认自己有权提交这份代码。DCO 主要确认代码来源,不额外授予项目广泛的再许可权。

Slax Reader 怎么用

Slax Reader 采用 Apache 2.0。它的第 5 条已经规定,提交给项目的贡献默认使用同一份许可证,除非双方另有协议。GitHub 服务条款也写了同样的规则。

Slax Reader 目前更需要降低参与门槛,让更多人愿意提交小改动。我的建议是先停用所有 PR 强制签 CLA 的规则。普通贡献使用 Apache 2.0 和 GitHub 的默认条款;如果想多留一份代码来源记录,可以使用 DCO。

[阅读全文]

从 Omarchy 截图,贴进远程 Mac 上的 herdr

问题

我的日常是:坐在 Linux(Omarchy)前面,ssh 到 Mac,在 Mac 上跑 herdr,里面开 Claude Code / Codex。

在 Linux 上截图,想贴给 agent 看,贴不过去。没有报错,没有 [Image #1],什么都没发生。

原因

SSH 只传文字。截图在 Linux 的剪贴板里,Mac 根本看不到。

ssh mac 之后再运行 herdr,herdr 整个跑在 Mac 上。它读的是 Mac 的剪贴板,不是我面前这台机器的。

这不是 Omarchy 的问题,也不是 herdr 的 bug。是架构决定的。

解法:反过来跑

在 Linux 上也装一个 herdr,用它作为客户端去连 Mac:

herdr --remote username@host

这样 herdr 客户端在 Linux 上运行,UI 从 Mac 那边流过来。剪贴板在本地,所以图片可以桥接过去:按 Ctrl+V,herdr 把 PNG 通过 SSH 传到 Mac,再把 Mac 上的文件路径贴进 agent 的输入框。agent 读路径就行。

谁跑在哪

这样做以后 herdr 两边都有,但分工不一样:

[阅读全文]

Omarchy 触摸板滚动加速

在 ThinkPad 上跑 Omarchy,触摸板滚动一直比 Mac 慢而平:手指快慢不同,页面走的距离都差不多。今天让 AI 查了一下,原因和改法都很短。

原因

Hyprland 把触摸板交给 libinput 处理。libinput 默认只给鼠标指针做加速,双指滚动是线性的,手指走多少页面走多少。Omarchy 在这之上还乘了一个 0.4 的系数(input.touchpad.scroll_factor),所以整体又慢了一截。Mac 的手感来自两样东西:一条按手速变化的加速曲线,加上抬手后的惯性滑动。

改法

libinput 有一个“custom”配置,可以给滚动单独画一条曲线。Hyprland 通过 accel_profile 和 scroll_points 两个选项把它暴露出来,Omarchy 的 Lua 配置里用 hl.device 可以只对触摸板生效,不影响小红点和外接鼠标。

在 ~/.config/hypr/input.lua 末尾加了这一段:

hl.device({
  name = "elan06b6:00-04f3:335a-touchpad",
  accel_profile = "custom 0.5 0 0.5 1.05 1.7 2.5 3.4 4.4 5.5",
  scroll_points = "0.5 0 0.4 0.9 1.5 2.3 3.3 4.5 6.0 7.8 10",
})

两行曲线的格式一样:第一个数是步长,后面是各个采样点的输出值。横轴是手指速度,纵轴是页面速度。慢慢滑的时候接近一比一,甩得快的时候往上翘。

设备名用 hyprctl devices 查。保存后 Hyprland 自动重载,hyprctl configerrors 为空就是生效了。

两个注意点

  • 换成 custom 之后,触摸板的指针加速也一起换掉了,所以 accel_profile 后面必须同时给一条指针曲线,不然指针会变成没有加速。
  • 曲线上的数字是起点,要靠手感调。想让快甩更猛就调大 scroll_points 后面几个数;想让慢滑更细就调小前面几个。整体都嫌慢的话,第二个旋钮是 Omarchy 默认的 scroll_factor = 0.4,改到 0.6 试试。

惯性滑动改不了。那是每个应用自己决定的,GTK 应用和 Chromium 有,其他不一定有,合成器这层没有开关。

[阅读全文]

我理解的 Omarchy

今天下决心,把日常工作的电脑从 Mac 切换到了 Linux。

想这么做其实已经有些日子了,手边也有几台设备分别装着 Debian(喜欢了很多年)、NixOS(去年接触到之后,非常喜欢这个发行版的理念),但始终觉得还是有些许不方便。这次的“临门一脚”,是 Omarchy 推动的。

我大概半年多前第一次用 Omarchy,那时觉得这个发行版带着作者 DHH 非常强烈的观点——他喜欢的软件、习惯的配置,而我也有些偏执的喜好,于是只是浅尝辄止。

我也想了想,为什么最近两周 Omarchy 会在 X 上爆火,我觉得的几个原因有:

  • DHH 的个人魅力——他有着极强的感染力,而且几十年持续创造输出,Ruby on Rails、Basecamp、Hey 等作品背后都是他。在 Omarchy 发布后,他极高强度地开发、宣传。最近更是组建了基金会,十几天时间里,募集了超过 1300 万美金——包括我在 Caoz 群里认识了几十年的 xdanger 也捐了 100 万美金。
  • Omarchy 的尝试成本很低——找一台旧笔记本电脑,插上启动 U 盘,几分钟时间就能装好,所有东西都按照 DHH 的品味,所谓“大厨精选”帮你装好了,可以快速开箱即用——这里其实解决了 Linux 桌面一直以来的大问题:选择过多导致普通用户无从下手。
  • AI first 的操作系统这样的说法,现阶段还是挺占便宜的,很多用户好奇心起就会试试。而且确实,AI 时代,每个人应该都能有一台真正顺手的,适合自己的电脑,这时的 AI first 很合理。
  • AI 极大降低了开发、支持、使用、改进的成本。例如:内置了 Omarchy Skill,你可以通过问 AI 直接得到如何修改配置等问题的准确做法。例如:当系统里有软件出错时,调用分析 skill,直接分析日志和代码,最后提交 PR 给开发者——挺好的闭环,也极大鼓励了用户的参与。
  • 很好的插件机制,用户几句话就能做出自己需要的小插件,成就感很强,容易激发参与感和传播。
  • 审美在线。很漂亮的系统,截图在社交媒体被广泛传播。

而且,据说后续 Omarchy 会改用 nix 来做包管理——那就真是我心目中完美的桌面系统了——我本来昨天想让 AI 往这个方向做的,听说之后,停下了任务,省 token 了。

Quickshell 是什么

Linux 上做桌面部件的工具箱,官网 quickshell.org。状态栏、通知弹窗、锁屏、音量面板、壁纸切换器,这些东西用它来写。

它解决什么

上一篇讲 Hyprland 时提过,那种窗口管理器只管窗口怎么摆,状态栏、通知、锁屏都要另外找程序拼。常见的拼法是 Waybar 加 mako 加 hyprlock,各是各的程序,各有各的配置格式,样式对不齐,之间也不通消息。

Quickshell 换一个思路:这些部件全都自己写,用同一种语言,跑在同一个进程里。状态栏上的音量图标和按音量键弹出的那个提示,可以共用一份状态。

用什么写

QML,Qt 的界面语言。长这样:

import Quickshell
import QtQuick

PanelWindow {
  anchors {
    top: true
    left: true
    right: true
  }
  implicitHeight: 30
  Text {
    anchors.centerIn: parent
    text: "hello world"
  }
}

这段就是屏幕顶部一条 30 像素高的栏,中间写着一行字。anchors 指定贴哪几条边,贴住之后 Quickshell 会自动向窗口管理器申请这块空间,其他窗口不会被它盖住。

QML 是声明式的:你写界面长什么样、数据变了界面怎么跟着变,不用自己写"收到消息 → 找到那个控件 → 改它的文字"这种流程。

存盘就生效

配置放在 ~/.config/quickshell/,每个子目录里有一个 shell.qml 就算一套配置。跑起来之后编辑文件,存盘界面立刻变,不用重启。改一个像素挪一下位置,改完扭头就能看见。

自带的接口

写桌面部件要拿系统数据。Quickshell 内置了这些:

  • PipeWire:音量、当前播放设备
  • MPRIS:正在放什么歌,暂停下一首
  • 系统托盘:那些图标
  • PAM:验证密码,锁屏要用
  • 蓝牙
  • Hyprland 和 i3/Sway:当前工作区、窗口标题这类窗口管理器内部状态

官方只内置了 Hyprland 和 i3 两家的接口。用别的窗口管理器,得自己通过 socket 或者调命令去拿。

代价

  • 得会写代码。Waybar 改个配置文件就能用,Quickshell 是让你自己写一个状态栏出来
  • 从空白开始。它是工具箱不是成品,装完什么都没有
  • API 还在变。官方明说后续版本会有破坏性改动,升级时要照迁移指南改配置

现状

LGPL 3 开源,主力开发者 outfoxxed。源码在 GitHub,文档在 quickshell.org/docs。Wayland 和 X11 都支持。

[阅读全文]

Hyprland 是什么

Linux 上的一个窗口管理器,官网 hypr.land。它决定窗口怎么摆、怎么切换、动画长什么样。

平铺

一般桌面上窗口是叠在一起的,像桌上摊开的一堆纸,你拖来拖去调整位置和大小。平铺是另一种摆法:窗口不重叠,自动铺满整个屏幕。开第一个窗口占满屏,开第二个屏幕自动一分为二,开第三个再分。

好处是不用手动拖窗口,也不会有窗口被压在下面找不到。切换、移动、调整大小全走键盘快捷键。

Linux 上平铺窗口管理器有很多,i3、dwm、sway 都是。Hyprland 的区别在于它有圆角、模糊、阴影和动画,窗口开关和切换都有过渡效果。

Wayland

Hyprland 只能在 Wayland 上跑。

Wayland 是 Linux 上画图形界面的一套协议,用来取代 1987 年的 X11。在 X11 时代,窗口管理器和显示服务器是两个程序;到了 Wayland,两者合并成一个,叫合成器(compositor)。所以 Hyprland 既管窗口布局,也管画面合成。

老程序只认 X11 的,通过 XWayland 这个兼容层照样能跑。

它不是完整桌面

GNOME、KDE 装完就能用:状态栏、文件管理器、设置面板、通知、锁屏,全都有。Hyprland 只管窗口,其余要自己拼:

装完第一次启动是一块黑屏加一个鼠标指针,什么都没有。所有东西都得自己配出来。

配置

一个文本文件,~/.config/hypr/hyprland.conf。按键绑定、动画、窗口规则都写在里面,存盘立刻生效,不用重启。所有配置项在 Wiki 上。

bind = SUPER, Return, exec, ghostty
bind = SUPER, Q, killactive
bind = SUPER, 1, workspace, 1

animations {
    enabled = true
    bezier = smooth, 0.05, 0.9, 0.1, 1.05
}

现状

滚动发布,两三个月一个版本,最新是 0.56.2(2026 年 8 月)。主力开发者是 Vaxry。版本号还在 0.x。源码和发布记录在 GitHub。

[阅读全文]

Brave Origin 盲签名方案

Brave 6 月上线了 Origin,59.99 美元买断。Leo、News、Rewards、VPN、Wallet、Talk、Tor、Speedreader、Web Discovery 全部从二进制里编译掉,只留 Shields 和 Chromium 内核。Linux 免费。

我买了一个。翻文档的时候看到激活这一步的做法:Brave 的服务器没办法知道是谁在用这份授权。

它用的是盲签名。

常规做法是查表

付费解锁都要回答一个问题:这台设备凭什么证明自己付过钱。

一般是账号体系。你登录,服务器查表,这个 user_id 买过,放行。表里就记着某某邮箱在用 Origin、今天启动了几次。

盲签名把这张表去掉了。名字里的「盲」就是服务器闭着眼睛签——它签的时候不知道自己在签什么,签完也认不出来。

用数字走一遍

服务器手里有个只有它知道的私章,就当它是「乘以 7」。

我在自己电脑上随手生成一个 token,是 3。我要拿到「服务器给 3 盖过章」的证据,又不想让它知道 3 是多少。

  • 我再挑一个随机数 5,把 3 乘上去:3 × 5 = 15。把 15 发过去
  • 服务器盖章:15 × 7 = 105。把 105 还给我
  • 我把 5 除掉:105 ÷ 5 = 21。21 正好是 3 × 7

现在我手上有一对数 (3, 21)。以后要用 premium 功能,把这两个数交出去,服务器算一下 3 × 7 是不是 21,对上了就放行。

[阅读全文]

在手机上用自己电脑里的 AI Agent

DeepSeek 开源了自己的 agent harness,叫 dsh。装上跑一条命令就能用:

npx @deepseek-ai/dsh web

它没有终端界面,只有浏览器 UI,默认起在 http://127.0.0.1:3080。我想在手机上也能用——躺着的时候给它派个活,回到电脑前看结果。

不要直接开放到局域网

第一反应是把它绑到 0.0.0.0,手机连同一个 wifi 就能访问。dsh 直接拒绝了这个参数,报错写得很直白:

--host 0.0.0.0 is intentionally not supported yet for safety: it would expose remote code execution to the network

这不是没做完,是故意堵死的。这类 agent 能跑 shell、能读写你整个文件系统,而它目前没有任何用户认证。裸奔在局域网上,等于把电脑的 shell 交给任何连了你 wifi 的人。

用 Tailscale 反代

正确的做法是:程序继续只绑本地回环,前面放一层带认证的代理。Tailscale 正好干这个。

# 1. 启动,同时声明信任的域名
dsh web --trusted-host 你的机器名.你的tailnet.ts.net

# 2. Tailscale 在前面反代
tailscale serve --bg 3080

完事。手机连上 Tailscale,打开 https://你的机器名.你的tailnet.ts.net/ 就能用,自带 HTTPS 和设备级认证,家里 wifi 上什么都没暴露。

[阅读全文]

让 Mac 保持清醒:caffeinate

macOS 自带一个命令,caffeinate,给机器灌咖啡,不让它睡。跑长任务、下载大文件的时候用,不用去系统设置里改电源选项。

caffeinate

运行后 Mac 不睡眠。Ctrl+C 退出,恢复正常。

常用参数

屏幕常亮:

caffeinate -d

默认只防系统睡眠,屏幕照样熄。加 -d,屏幕也一起保持。

限时,单位是秒:

caffeinate -t 7200

两小时后自动失效,不用手动关。

跟着任务走:

caffeinate -i ./backup.sh

任务跑多久,机器醒多久。任务结束,自动恢复。

合盖

管不了。caffeinate 挡的是空闲睡眠,合盖触发的是另一套强制睡眠,合上照样睡。

接了外接屏、电源和键鼠,macOS 本身就支持合盖运行,不用任何命令,这是官方的 clamshell 模式。

没有外接屏,还想合盖继续跑:

sudo pmset -a disablesleep 1

设置重启后还在。用完改回 0,否则 Mac 塞进包里也不睡,发热耗电。

怕忘关,套一层自动恢复:

sudo sh -c 'pmset -a disablesleep 1; trap "pmset -a disablesleep 0" INT TERM EXIT; sleep 28800'

合盖不睡 8 小时。到点、Ctrl+C、关终端,都会自动恢复睡眠。把 sleep 28800 换成任务本身,就是合盖版的 caffeinate -i。

查当前状态:

pmset -g | grep SleepDisabled

1 是不睡,0 是正常。

[阅读全文]

ntfy.sh 是什么

ntfy.sh 是一个很轻的通知服务。手机或电脑先订阅一个 topic,你的服务器、脚本、监控工具或任何程序,只要向 https://ntfy.sh/你的-topic 发一个 HTTP 请求,这条消息就会变成推送通知弹出来。

它适合做小而确定的提醒:备份失败、网站挂了、长任务跑完、家里传感器触发。最简单的用法只有一行:

curl -d "Backup failed" https://ntfy.sh/my-secret-topic

ntfy 是开源项目,可以直接用官方服务,也可以自己部署。默认不需要注册,所以 topic 名字本身就像密码,要取一个不容易被猜到的名字。敏感信息不要随手发到公共服务上。

官网:https://ntfy.sh/

GitHub:https://github.com/binwiederhier/ntfy