AI 时代 LLM 经常需要读取 git diff,默认行为不要用 delta 修改。
Delta 安装时可能会自动添加配置:
[core]
pager = delta
需要先移除这个配置,然后在 .gitconfig 中添加:
[alias]
ds = -c pager.diff=delta diff
git diff保持原生格式,便于 LLM 读取git ds查看带 delta 的漂亮 diff 效果
Stuff I learned recently.
AI 时代 LLM 经常需要读取 git diff,默认行为不要用 delta 修改。
Delta 安装时可能会自动添加配置:
[core]
pager = delta
需要先移除这个配置,然后在 .gitconfig 中添加:
[alias]
ds = -c pager.diff=delta diff
git diff 保持原生格式,便于 LLM 读取git ds 查看带 delta 的漂亮 diff 效果Bitwarden SSH Agent 默认会暴露所有可用密钥给 SSH 客户端,可能导致 Too many authentication failures 错误。通过 SSH Config 指定特定密钥解决。
# ~/.ssh/config
Host vps1
HostName domain.com
StrictHostKeyChecking no
User root
Port 26456
IdentityFile ~/.ssh/bw_keys/vps-auth.pub
IdentitiesOnly yes
Host vps2
HostName 1.1.1.1
StrictHostKeyChecking no
User root
Port 27644
IdentityFile ~/.ssh/bw_keys/vps-auth.pub
IdentitiesOnly yes
IdentitiesOnly yes 强制 SSH 只使用指定的密钥,跳过 Agent 中的其他密钥。
/usr/bin/env 是 Unix/Linux 系统中用于查找并运行程序的工具,主要用于 Shebang 中以提高脚本可移植性。
#!/usr/bin/python3 - 直接指定路径,跨系统兼容性差。
#!/usr/bin/env python3 - 在 $PATH 中搜索,兼容性极佳。
envenv 查看 $PATH 环境变量python3| 特性 | 直接路径 | 使用 env |
|---|---|---|
| 可移植性 | 差 | 极佳 |
| 虚拟环境支持 | 不支持 | 完美支持 |
| 灵活性 | 低 | 高 |
# 临时设置语言
env LANG=en_US.UTF-8 check_system_status
# 查看所有环境变量
env
env 不支持传递多个参数,如 #!/usr/bin/env python3 -u 在旧系统上可能失效。
使用 brew install 命令安装某些 cask 软件时,可以省略 cask 关键字,直接 brew install yaak 也能安装成功。
但在使用 brew bundle 命令时,必须在 Brewfile 中明确指定 cask 关键字:
# 正确写法
cask "yaak"
# 错误写法,会报错
brew "yaak"
原因:brew bundle 解析 Brewfile 时需要明确区分安装类型,而命令行 brew install 有自动检测能力。
测试覆盖率报告是构建产物,可以在本地或 CI 环境中随时重新生成,不应提交到 Git 仓库。
将 Git 仓库的默认分支从 master 修改为 main。
# 重命名本地分支
git branch -m master main
# 获取远程更新
git fetch origin
# 设置本地 main 分支跟踪远程 main 分支
git branch -u origin/main main
# 设置远程仓库的默认分支
git remote set-head origin -a 在 macOS 下配置如下参数,可以使用快捷键 ctrl+cmd来在任意位置拖拽窗口,而不是仅仅通过标题栏。
defaults write -g NSWindowShouldDragOnGesture YES

参考链接:https://www.reddit.com/r/MacOS/comments/k6hiwk/keyboard_modifier_to_simplify_click_drag_of/
Formula 用于从源码编译,Cask 用于分发预编译二进制。
Homebrew 团队希望统一 CLI 和 GUI 的安装体验,推动 brew install 作为唯一入口。因此 GoReleaser 官方推荐使用 Cask:
何时用 Cask:Go CLI 工具官方通常提供预编译二进制。
何时用 Formula:上游只提供源码、需要编译定制、或依赖本地库的软件。
自定义 tap 可同时包含两者:
# Formula
brew install zhaochunqi/homebrew-tap/<tool>
# Cask
brew install --cask zhaochunqi/homebrew-tap/<tool>
通过 homebrew-tap,可以让自己的项目通过 brew install 直接安装。
brew install zhaochunqi/tap/git-open
homebrew-<tap-name>,例如 homebrew-tapFormula/<formula-name>.rb 文件⚠️ 注意: Homebrew 官方不提倡在 Formula 中分发预编译二进制,这被认为是不好的实践。对于 Go CLI 工具等提供预编译二进制的项目,推荐使用 Homebrew Cask 进行分发。参考 Go CLI 工具更适合通过 Homebrew Cask 分发预编译二进制。
class GitOpen < Formula
desc "Open your git repo in browser using one command"
homepage "https://github.com/zhaochunqi/git-open"
version "2.2.1"
on_macos do
on_arm do
url "https://github.com/zhaochunqi/git-open/releases/download/v2.2.1/git-open_Darwin_arm64.tar.gz"
sha256 "9b653ba97f5095e8764f43eeb9ab0e46d01f4bbd14eadd51760b636512812a8c"
end
on_intel do
url "https://github.com/zhaochunqi/git-open/releases/download/v2.2.1/git-open_Darwin_x86_64.tar.gz"
sha256 "ab24e6fe8a49b6f526a785a94a10b56a139430f795346d30f8a5a5db1387223d"
end
end
on_linux do
on_arm64 do
url "https://github.com/zhaochunqi/git-open/releases/download/v2.2.1/git-open_Linux_arm64.tar.gz"
sha256 "8776da29b63a21f0949cda1814e30cc2c926bb6dee4199a9f7f0684486671c70"
end
on_x86_64 do
url "https://github.com/zhaochunqi/git-open/releases/download/v2.2.1/git-open_Linux_x86_64.tar.gz"
sha256 "cf91815149c341d718ea7b26d5d671e261bb8a5701e2de2da803d9a5a6c278c4"
end
end
def install
bin.install "git-open"
end
test do
system "#{bin}/git-open", "--version"
end
end
查看 ctrl + r绑定的键位::
❯ bindkey '^r'
"^R" history-incremental-search-backward
比如绑定 fzf-ghq-widget方法:
zle -N fzf-ghq-widget
# 1. 绑定默认 (Emacs) 模式
bindkey '^g' fzf-ghq-widget
# 2. 绑定 Vi 插入模式 (防止使用 Vi 模式时失效)
bindkey -M viins '^g' fzf-ghq-widget
解析:
在所有的 git 全局配置中,配置:
# Configure Git to ensure line endings in files you checkout are correct for macOS
git config --global core.autocrlf input
或者在对应的 ~/.gitconfig 中配置:
[core]
autocrlf = input
但是 github 推荐在 windows 中将这个选项设置为 true,我查了下觉得在三端均采用 input 是非常合理的。
| 配置值 | 含义 |
|---|---|
| true | 双向转换: • 输入(commit)时:CRLF → LF • 输出(checkout)时:LF → CRLF |
| input | 仅输入时转换: • 输入(commit)时:CRLF → LF • 输出(checkout)时:不做转换(保留 LF) |
| false | 完全不转换 |
“CR” 在电池型号中是标准命名:
下载软件 Karabiner-Elements, 在 Complex Modifications 中点击 add prefined rule, 找到 Caps Lock to ESC and Ctrl 启用即可。
至此,macos/nixos/windows 的修改方法已经补全。
直接使用项目 https://github.com/ililim/dual-key-remap , 按照里面的说明添加开机启动即可。
运行 uv python install --default 即可。
Software Heritage Archive 是一个代码档案库,可以下载已被删除的 GitHub、GitLab 等平台的代码。
参考:https://til.simonwillison.net/github/software-archive-recovery
Unleash 是一个企业级的 Feature Toggle 管理平台,核心价值是解耦部署与发布。
Unleash 采用本地求值架构:
今天学到了可以在对应的 pr 中添加 .diff 直接查看 diff, 然后可以将链接直接丢给在线的 ai 大模型给你 review
比如 https://github.com/zhaochunqi/git-open/pull/24 可以使用 https://github.com/zhaochunqi/git-open/pull/24.diff, 然后提交给大模型说:review https://github.com/zhaochunqi/git-open/pull/24.diff 即可,我看了下纯文本,感觉复制粘贴都行。
traefik 中生成的证书如果已经不再使用 (表现其实就是过期了) 的证书,经查询发现有人写了相关的脚本来处理,稍作修改直接使用 uv 来管理避免需要手动安装依赖。
uv run - <<EOF
# /// script
# requires-python = ">=3.12"
# dependencies = [
# "cryptography",
# ]
# ///
import json
import sys
import base64
from datetime import datetime, timedelta, timezone
from cryptography import x509
import os
DEBUG = os.environ.get("DEBUG", False)
def cleanup_certs(acme_file="acme.json"):
"""
Deletes all expired certificates from acme.json.
"""
try:
with open(acme_file, "r") as f:
data = json.load(f)
except FileNotFoundError:
print(f"Error: {acme_file} not found.")
return
now = datetime.now()
if DEBUG:
print(f"DEBUG: current time: {now}")
cleaned_count = 0
def process_certificates(certificates, version):
nonlocal cleaned_count
if not certificates:
return [], 0
original_cert_count = len(certificates)
certs_to_keep = []
removed_certs = []
for cert in certificates:
cert_b64 = ""
domain = "N/A"
try:
if version == 1:
cert_b64 = cert.get("Certificate", "")
domain = cert.get("Domain", {}).get("Main", "N/A")
elif version in [2, 3]:
cert_b64 = cert.get("certificate", "")
domain = cert.get("domain", {}).get("main", "N/A")
if cert_b64:
cert_b64_decoded = cert_b64.replace("-", "+").replace("_", "/")
padding_needed = len(cert_b64_decoded) % 4
if padding_needed != 0:
cert_b64_decoded += "=" * (4 - padding_needed)
cert_pem_bytes = base64.b64decode(cert_b64_decoded)
x509_cert = x509.load_pem_x509_certificate(cert_pem_bytes)
not_after_date = x509_cert.not_valid_after_utc
if DEBUG:
print(
f"DEBUG: Processing domain {domain}, not_valid_after: {not_after_date}"
)
if not_after_date > datetime.now(timezone.utc):
certs_to_keep.append(cert)
else:
removed_certs.append(domain)
else:
certs_to_keep.append(cert)
except Exception as e:
print(f"Could not process certificate for domain {domain}: {e}")
certs_to_keep.append(cert)
removed_count = original_cert_count - len(certs_to_keep)
# We only want to add to the cleaned_count if we are in a v2/v3 file,
# because the v1 file has only one list of certs and we will get the
# count from the return value of this function.
if version in [2, 3]:
cleaned_count += removed_count
for domain_name in removed_certs:
print(f"Removed certificate for: {domain_name}")
return certs_to_keep, removed_count
# Detect acme.json version
version = None
if (
isinstance(data, dict)
and "Certificates" in data
and isinstance(data.get("Certificates"), list)
):
version = 1
elif isinstance(data, dict):
for key, value in data.items():
if isinstance(value, dict) and "Certificates" in value:
version = 2 # Treat as v2/v3 generic
break
if DEBUG:
print(f"DEBUG: Detected version: {version}")
if version == 1:
certs_to_keep, removed_count = process_certificates(
data["Certificates"], version
)
if removed_count > 0:
data["Certificates"] = certs_to_keep
cleaned_count = removed_count
elif version == 2:
for resolver, resolver_data in data.items():
if (
isinstance(resolver_data, dict)
and "Certificates" in resolver_data
and resolver_data["Certificates"] is not None
):
if DEBUG:
print(f"DEBUG: Processing resolver: '{resolver}'")
certs_to_keep, _ = process_certificates(
resolver_data["Certificates"], version
)
resolver_data["Certificates"] = certs_to_keep
else:
if DEBUG:
print(f"DEBUG: Resolver '{resolver}': No certificates to process.")
else:
print("Could not determine the structure of the acme.json file.")
return
if cleaned_count == 0:
print("No expired certificates to remove.")
else:
try:
with open(acme_file, "w") as f:
json.dump(data, f, indent=4)
print(
f"Successfully cleaned up {cleaned_count} certificates in {acme_file}."
)
except Exception as e:
print(f"Error writing to {acme_file}: {e}")
if __name__ == "__main__":
help_message = """
Usage: python3 cleanup_certs.py [--help] [acme_file]
Deletes all expired certificates from an acme.json file.
The script attempts to auto-detect the acme.json file version (v1 or v2/v3).
Arguments:
acme_file Optional. Path to the acme.json file. Defaults to "acme.json".
--help Display this help message and exit.
"""
if "--help" in sys.argv:
print(help_message)
sys.exit(0)
if len(sys.argv) > 1 and sys.argv[1] != "--help":
file_path = sys.argv[1]
else:
file_path = "acme.json"
cleanup_certs(file_path)
EOF 根据 POSIX 标准:文本行必须以换行符结尾。这意味着 rbw get xxx 的时候,实际上屏幕输出的是带有空格的。但是为什么 export a = $(rbw get xxx) 不会存在问题呢?因为 ${} (命令替换|Command Substitution) 会去掉尾部的换行。
参考链接: