From bd167cfb6d7918586394a5b0eb0c6324d556a165 Mon Sep 17 00:00:00 2001 From: Zhengshou Lai Date: Mon, 13 Apr 2026 11:41:57 +0800 Subject: [PATCH] feat: add API keys management and config CRUD operations - Add api_keys and feishu_apps to config.json - Add env export/init commands for shell integration - Add config CRUD: list, set, delete, init - Add config.json.example template - Add config.json to .gitignore for security - Update README with new commands Usage: mycli env export # Export all env vars mycli config set key value # Set config value mycli config delete key # Delete config key --- .gitignore | 3 + README.md | 56 ++++++- .../__pycache__/config_cmd.cpython-310.pyc | Bin 1959 -> 5364 bytes .../commands/__pycache__/env.cpython-310.pyc | Bin 2744 -> 5535 bytes mycli/commands/config_cmd.py | 144 +++++++++++++++++- mycli/commands/env.py | 97 ++++++++++++ mycli/config.json | 16 +- mycli/config.json.example | 48 ++++++ 8 files changed, 354 insertions(+), 10 deletions(-) create mode 100644 mycli/config.json.example diff --git a/.gitignore b/.gitignore index f45e8b0..8842f02 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,6 @@ build/ .venv/ .pytest_cache/ .mypy_cache/ + +# Config contains sensitive data (API keys) +mycli/config.json diff --git a/README.md b/README.md index 649eba0..757bc23 100644 --- a/README.md +++ b/README.md @@ -64,13 +64,31 @@ mycli self update # Update mycli mycli self uninstall # Uninstall mycli mycli self info # Show installation info -# Configuration (config.json) -mycli config show # Show full config -mycli config get paths # Get paths section -mycli config get paths.apaam # Get specific path -mycli config paths # List all paths with existence check -mycli config where # Show config file location -mycli config edit # Edit config in $EDITOR +# Configuration (config.json) - 增删改查 +mycli config show # Show full config +mycli config list # List top-level sections +mycli config get paths # Get paths section +mycli config get paths.apaam # Get specific path +mycli config get api_keys.deepseek # Get API key +mycli config set paths.new ~/Documents/new # Set simple value +mycli config set api_keys.newkey abc123 # Set new API key +mycli config set --json ssh_hosts.new '{"host":"user@host","port":22}' +mycli config delete paths.old # Delete a key +mycli config delete api_keys.old -y # Delete without confirmation +mycli config paths # List all paths with existence check +mycli config where # Show config file location +mycli config edit # Edit config in $EDITOR +mycli config init # Create config from template + +# Environment Variables (API Keys) +mycli env status # Show paths, API keys, Feishu status +mycli env export # Print all export statements +mycli env export deepseek # Export specific API key +mycli env export qwen +mycli env export feishu # Export all Feishu apps +mycli env export claude # Export specific Feishu app +eval "$(mycli env export)" # Load all in current shell +mycli env init # Print shell init snippet ``` ## Configuration @@ -80,6 +98,30 @@ All settings are stored in `mycli/config.json`: - `ssh_hosts`: SSH connection settings - `git_proxies`: Git proxy URLs - `openfoam`: OpenFOAM mount settings +- `api_keys`: API keys (deepseek, qwen) +- `feishu_apps`: Feishu app credentials + +### Security Note + +`config.json` contains sensitive information (API keys) and is **gitignored**. +The repository includes `config.json.example` as a template. + +### Setup + +1. Copy the example config: + ```bash + cp mycli/config.json.example mycli/config.json + ``` + +2. Edit with your actual API keys: + ```bash + mycli config edit + ``` + +3. Add to your `~/.zshrc` to auto-load: + ```bash + eval "$(mycli env export 2>/dev/null)" + ``` ## Uninstall diff --git a/mycli/commands/__pycache__/config_cmd.cpython-310.pyc b/mycli/commands/__pycache__/config_cmd.cpython-310.pyc index 031511384b3f84dfe60b1a19cf0d27d458811164..44e291fb5b8eb46ec604ceb223a16c6b83e52685 100644 GIT binary patch literal 5364 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 Hbt|D?cFOE8 diff --git a/mycli/commands/__pycache__/env.cpython-310.pyc b/mycli/commands/__pycache__/env.cpython-310.pyc index 44ee59ecb3e9ccc9be856b28b29b46f985db8410..07069eb4f16f9593dc42afdc75b7065d4a7031da 100644 GIT binary patch literal 5535 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 A6#xJL delta 762 zcmY*XOK;Oa5cY2T%)?F7gho6IZ3Koug+#efP$i^tK~+U6A%%lwylxWY#MRgVgh2cP zq@uln5L^*Q4shZJ@DtqLxB_QxFte@FFw%VX?96;K``Pa=eQmUpN~Nfw8Df91XKUII z3Z~7#U=2O}t-WslGzITy-f{VceQ98E-EDP2KQJD9Tm6b+Sw~hMICXgGd|#_wx(g zW~C#3NA4Q;N(bYI!Bc3+U&e`*8r9Arcm~YlqibQ#kE0PNZk@Pck&337ZkjFDlA*b8 z&0uN^s&d`hY!Ek02;mroi}I7@EfJTZ&&@0VR3|smeiX<5k^ZsT7p`DoZl+m~jnfd{ zCr0a5BZn9FrmW=&S(-h6KPzDPpf&z/dev/null)" +""" + click.echo(snippet) diff --git a/mycli/config.json b/mycli/config.json index 3cdff66..14d40f7 100644 --- a/mycli/config.json +++ b/mycli/config.json @@ -30,5 +30,19 @@ "mount_point": "/Volumes/OpenFOAM", "build_path": "/Volumes/OpenFOAM/openfoam/build" }, - "cv": "~/Documents/Personal/resume_cv/cv_lai_maintaining_latex/cv_lai_maintaining" + "cv": "~/Documents/Personal/resume_cv/cv_lai_maintaining_latex/cv_lai_maintaining", + "api_keys": { + "deepseek": "sk-5c2f22ad351a485380e29385c710c2b2", + "qwen": "sk-dcbbcce8cce94ecebb4c19417757d32f" + }, + "feishu_apps": { + "claude": { + "app_id": "cli_a9452b9024781bd2", + "app_secret": "YIyWNMOUhuPxrs1emA6H7mOvbZajJHBw" + }, + "myagent": { + "app_id": "cli_a916d9fef8b89bc7", + "app_secret": "WxhZe8N8MuMuzCjYduDe8btitLeiFUFj" + } + } } diff --git a/mycli/config.json.example b/mycli/config.json.example new file mode 100644 index 0000000..f924c30 --- /dev/null +++ b/mycli/config.json.example @@ -0,0 +1,48 @@ +{ + "paths": { + "study": "~/Documents/myStudy/self_learning", + "research": "~/Documents/myResearch", + "apaam": "~/Documents/myResearch/myProjects/apaam", + "tianhe": "~/Documents/myWork/sysu/0_中山大学/hpc_tianhe", + "academia": "~/Library/Mobile Documents/iCloud~md~obsidian/Documents/myacademia", + "webpage": "~/Documents/myWork/sysu/4_成果归档/mywebpage", + "slides": "~/Documents/myWork/sysu/4_成果归档/myslides", + "myclaude": "~/Documents/myResearch/myProjects/apaam/repo/myclaude", + "myagent": "~/Documents/myResearch/myProjects/apaam/repo/myagent" + }, + "ssh_hosts": { + "tianhe": { + "host": "sysu_lchuangxy_1@172.16.31.31", + "port": 6666, + "key": "~/Documents/myWork/sysu/0_中山大学/hpc_tianhe/sysu_lchuangxy_1.id" + }, + "starlight": { + "host": "sysu_lchuang_1@proxy.nscc-gz.cn", + "port": 23 + } + }, + "git_proxies": { + "fastgithub": "http://127.0.0.1:38457", + "pandafan": "http://127.0.0.1:10080" + }, + "openfoam": { + "dmg_path": "~/Documents/myResearch/myProjects/apaam/repo/OpenFOAM.dmg", + "mount_point": "/Volumes/OpenFOAM", + "build_path": "/Volumes/OpenFOAM/openfoam/build" + }, + "cv": "~/Documents/Personal/resume_cv/cv_lai_maintaining_latex/cv_lai_maintaining", + "api_keys": { + "deepseek": "YOUR_DEEPSEEK_API_KEY_HERE", + "qwen": "YOUR_QWEN_API_KEY_HERE" + }, + "feishu_apps": { + "claude": { + "app_id": "YOUR_CLAUDE_APP_ID", + "app_secret": "YOUR_CLAUDE_APP_SECRET" + }, + "myagent": { + "app_id": "YOUR_MYAGENT_APP_ID", + "app_secret": "YOUR_MYAGENT_APP_SECRET" + } + } +}