diff --git a/Makefile b/Makefile index d09cea8..83a412e 100644 --- a/Makefile +++ b/Makefile @@ -1,15 +1,30 @@ ROOT_DIR := $(shell pwd) +VENV_MYCLAUDE := $(ROOT_DIR)/.venv/bin/myclaude +USER_LOCAL_MYCLAUDE := $(HOME)/.local/bin/myclaude -.PHONY: help install +.PHONY: help install uninstall _symlink-myclaude help: @echo "Usage: make [target]" @echo "" - @echo " install Editable pip install of myclaude (uses uv when available)" + @echo " install Sync venv (uv or pip), symlink $(USER_LOCAL_MYCLAUDE) -> .venv/bin/myclaude" + @echo " uninstall Remove $(USER_LOCAL_MYCLAUDE) if it is a symlink to this repo" install: - @if command -v uv >/dev/null 2>&1; then \ - uv pip install -e "$(ROOT_DIR)"; \ + @cd "$(ROOT_DIR)" && \ + if command -v uv >/dev/null 2>&1; then \ + uv sync; \ else \ - python3 -m pip install -e "$(ROOT_DIR)"; \ + test -x .venv/bin/pip || python3 -m venv .venv; \ + .venv/bin/pip install -e .; \ fi + @$(MAKE) _symlink-myclaude + +_symlink-myclaude: + @test -x "$(VENV_MYCLAUDE)" || { echo "error: missing $(VENV_MYCLAUDE)"; exit 1; } + @mkdir -p "$(HOME)/.local/bin" + @ln -sf "$(VENV_MYCLAUDE)" "$(USER_LOCAL_MYCLAUDE)" + @echo "Linked $(USER_LOCAL_MYCLAUDE) -> $(VENV_MYCLAUDE)" + +uninstall: + @ROOT_DIR="$(ROOT_DIR)" python3 "$(ROOT_DIR)/scripts/rm_user_local_myclaude.py" diff --git a/README.md b/README.md index 8fd96d8..565c503 100644 --- a/README.md +++ b/README.md @@ -151,38 +151,23 @@ git --version # 确认已安装 git clone ~/your-path/myclaude cd ~/your-path/myclaude -# 安装(会自动检测并使用 uv 或 pip) +# 安装(uv 则 uv sync,否则创建 .venv 并用 pip install -e) make install ``` -> 💡 **提示**:如未安装 uv,会使用系统 pip 安装,速度稍慢 +会在 `~/.local/bin/myclaude` 创建指向本仓库 `.venv/bin/myclaude` 的符号链接;请保证 `~/.local/bin` 在 `PATH` 中(多数发行版默认已包含)。移除该链接:`make uninstall`(仅当链接目标为本仓库的 `.venv/bin/myclaude` 时才会删除)。 -**配置快捷命令:** +> 💡 **提示**:无 uv 时会创建项目 `.venv` 并用其中的 pip 做可编辑安装。 -将 `myclaude` 添加到 shell 配置,方便全局调用: +**Shell 补全(可选):** 在 `~/.zshrc` 或 `~/.bashrc` 中加入(有命令再注册,避免未安装时报错): ```bash -# 编辑 ~/.zshrc 或 ~/.bashrc -MYCLAUDE_PATH="$HOME/your-path/myclaude" # 修改为你的实际路径 -if [ -d "$MYCLAUDE_PATH/.venv/bin" ]; then - alias myclaude=$MYCLAUDE_PATH/.venv/bin/myclaude - eval "$(_MYCLAUDE_COMPLETE=zsh_source myclaude)" # zsh 补全 - # eval "$(_MYCLAUDE_COMPLETE=bash_source myclaude)" # bash 补全 +if command -v myclaude >/dev/null 2>&1; then + eval "$(_MYCLAUDE_COMPLETE=zsh_source myclaude)" fi - -# 使配置生效 -source ~/.zshrc # 或 source ~/.bashrc ``` -验证并启动: - -```bash -# 验证安装 -myclaude --version - -# 启动本地交互模式 -myclaude chat -``` +Bash 将 `zsh_source` 换成 `bash_source`。保存后 `source` 该配置文件。 ### 5. 安装 Metabot diff --git a/scripts/rm_user_local_myclaude.py b/scripts/rm_user_local_myclaude.py new file mode 100644 index 0000000..ad0a4b6 --- /dev/null +++ b/scripts/rm_user_local_myclaude.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +"""Remove ~/.local/bin/myclaude if it is a symlink to this repo's .venv/bin/myclaude.""" + +from __future__ import annotations + +import os +import sys + + +def main() -> int: + root = os.path.normpath(os.environ.get("ROOT_DIR", os.getcwd())) + link = os.path.expanduser("~/.local/bin/myclaude") + want = os.path.normpath(os.path.join(root, ".venv", "bin", "myclaude")) + + if not os.path.islink(link): + if os.path.lexists(link): + print("Skip: not a symlink, leaving untouched") + else: + print("Nothing to remove") + return 0 + + target = os.readlink(link) + if not os.path.isabs(target): + target = os.path.join(os.path.dirname(link), target) + target = os.path.normpath(target) + + if target == want: + os.unlink(link) + print("Removed", link) + return 0 + + print("Skip: points to", target, "(not this repo's", want + ")") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..1a5ce57 --- /dev/null +++ b/uv.lock @@ -0,0 +1,82 @@ +version = 1 +revision = 3 +requires-python = ">=3.10" + +[[package]] +name = "click" +version = "8.3.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/57/75/31212c6bf2503fdf920d87fee5d7a86a2e3bcf444984126f13d8e4016804/click-8.3.2.tar.gz", hash = "sha256:14162b8b3b3550a7d479eafa77dfd3c38d9dc8951f6f69c78913a8f9a7540fd5", size = 302856, upload-time = "2026-04-03T19:14:45.118Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e4/20/71885d8b97d4f3dde17b1fdb92dbd4908b00541c5a3379787137285f602e/click-8.3.2-py3-none-any.whl", hash = "sha256:1924d2c27c5653561cd2cae4548d1406039cb79b858b747cfea24924bbc1616d", size = 108379, upload-time = "2026-04-03T19:14:43.505Z" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "markdown-it-py" +version = "4.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mdurl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" }, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, +] + +[[package]] +name = "myclaude" +version = "0.1.0" +source = { editable = "." } +dependencies = [ + { name = "click" }, + { name = "rich" }, +] + +[package.metadata] +requires-dist = [ + { name = "click", specifier = ">=8.0.0" }, + { name = "rich", specifier = ">=13.0.0" }, +] + +[[package]] +name = "pygments" +version = "2.20.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, +] + +[[package]] +name = "rich" +version = "14.3.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b3/c6/f3b320c27991c46f43ee9d856302c70dc2d0fb2dba4842ff739d5f46b393/rich-14.3.3.tar.gz", hash = "sha256:b8daa0b9e4eef54dd8cf7c86c03713f53241884e814f4e2f5fb342fe520f639b", size = 230582, upload-time = "2026-02-19T17:23:12.474Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/14/25/b208c5683343959b670dc001595f2f3737e051da617f66c31f7c4fa93abc/rich-14.3.3-py3-none-any.whl", hash = "sha256:793431c1f8619afa7d3b52b2cdec859562b950ea0d4b6b505397612db8d5362d", size = 310458, upload-time = "2026-02-19T17:23:13.732Z" }, +]