gardusig-cli 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- gardusig_cli-0.1.0/LICENSE +21 -0
- gardusig_cli-0.1.0/PKG-INFO +274 -0
- gardusig_cli-0.1.0/README.md +238 -0
- gardusig_cli-0.1.0/cli/__init__.py +3 -0
- gardusig_cli-0.1.0/cli/__main__.py +4 -0
- gardusig_cli-0.1.0/cli/cli.py +71 -0
- gardusig_cli-0.1.0/cli/commands/__init__.py +1 -0
- gardusig_cli-0.1.0/cli/commands/backup.py +49 -0
- gardusig_cli-0.1.0/cli/commands/bookmarks.py +21 -0
- gardusig_cli-0.1.0/cli/commands/chrome.py +77 -0
- gardusig_cli-0.1.0/cli/commands/contest.py +120 -0
- gardusig_cli-0.1.0/cli/commands/docker.py +386 -0
- gardusig_cli-0.1.0/cli/commands/drive.py +223 -0
- gardusig_cli-0.1.0/cli/commands/gh.py +419 -0
- gardusig_cli-0.1.0/cli/commands/git.py +790 -0
- gardusig_cli-0.1.0/cli/commands/links.py +81 -0
- gardusig_cli-0.1.0/cli/commands/notion.py +215 -0
- gardusig_cli-0.1.0/cli/commands/publish.py +63 -0
- gardusig_cli-0.1.0/cli/commands/restore.py +8 -0
- gardusig_cli-0.1.0/cli/integration/__init__.py +5 -0
- gardusig_cli-0.1.0/cli/integration/cli_api_checks.py +531 -0
- gardusig_cli-0.1.0/cli/integration/contest_integration.py +156 -0
- gardusig_cli-0.1.0/cli/integration/docker_integration.py +346 -0
- gardusig_cli-0.1.0/cli/integration/docker_mocks.py +125 -0
- gardusig_cli-0.1.0/cli/integration/git_mocks.py +59 -0
- gardusig_cli-0.1.0/cli/integration/integration_coverage.py +329 -0
- gardusig_cli-0.1.0/cli/integration/public_commands.py +82 -0
- gardusig_cli-0.1.0/cli/integration/public_endpoints.py +1151 -0
- gardusig_cli-0.1.0/cli/integration/tag_zip_integration.py +449 -0
- gardusig_cli-0.1.0/cli/integration/workflow_integration.py +804 -0
- gardusig_cli-0.1.0/cli/integration/workspaces.py +83 -0
- gardusig_cli-0.1.0/cli/internal/__init__.py +1 -0
- gardusig_cli-0.1.0/cli/internal/read/__init__.py +9 -0
- gardusig_cli-0.1.0/cli/internal/read/git.py +47 -0
- gardusig_cli-0.1.0/cli/internal/read/safety.py +99 -0
- gardusig_cli-0.1.0/cli/internal/write/__init__.py +13 -0
- gardusig_cli-0.1.0/cli/internal/write/gate.py +66 -0
- gardusig_cli-0.1.0/cli/internal/write/git.py +38 -0
- gardusig_cli-0.1.0/cli/models/__init__.py +1 -0
- gardusig_cli-0.1.0/cli/models/backup.py +10 -0
- gardusig_cli-0.1.0/cli/models/bookmark.py +14 -0
- gardusig_cli-0.1.0/cli/models/repository.py +9 -0
- gardusig_cli-0.1.0/cli/models/task.py +68 -0
- gardusig_cli-0.1.0/cli/providers/__init__.py +1 -0
- gardusig_cli-0.1.0/cli/providers/base.py +23 -0
- gardusig_cli-0.1.0/cli/providers/chrome.py +9 -0
- gardusig_cli-0.1.0/cli/providers/drive_client.py +56 -0
- gardusig_cli-0.1.0/cli/providers/gh.py +47 -0
- gardusig_cli-0.1.0/cli/providers/github.py +13 -0
- gardusig_cli-0.1.0/cli/providers/google_drive.py +31 -0
- gardusig_cli-0.1.0/cli/providers/icloud_drive.py +17 -0
- gardusig_cli-0.1.0/cli/providers/notion.py +244 -0
- gardusig_cli-0.1.0/cli/providers/onedrive.py +31 -0
- gardusig_cli-0.1.0/cli/providers/proton_drive.py +31 -0
- gardusig_cli-0.1.0/cli/services/__init__.py +3 -0
- gardusig_cli-0.1.0/cli/services/backup_repository.py +181 -0
- gardusig_cli-0.1.0/cli/services/backup_zip.py +65 -0
- gardusig_cli-0.1.0/cli/services/bookmark_sync.py +9 -0
- gardusig_cli-0.1.0/cli/services/contest_docker.py +193 -0
- gardusig_cli-0.1.0/cli/services/contest_runner.py +274 -0
- gardusig_cli-0.1.0/cli/services/contest_serde.py +30 -0
- gardusig_cli-0.1.0/cli/services/docker_runtime.py +332 -0
- gardusig_cli-0.1.0/cli/services/drive_sync.py +108 -0
- gardusig_cli-0.1.0/cli/services/gh_sequence.py +66 -0
- gardusig_cli-0.1.0/cli/services/gh_service.py +344 -0
- gardusig_cli-0.1.0/cli/services/git_archive.py +5 -0
- gardusig_cli-0.1.0/cli/services/git_review.py +34 -0
- gardusig_cli-0.1.0/cli/services/git_shortcuts.py +610 -0
- gardusig_cli-0.1.0/cli/services/notion_markdown.py +173 -0
- gardusig_cli-0.1.0/cli/services/notion_pairs.py +232 -0
- gardusig_cli-0.1.0/cli/services/notion_sync.py +220 -0
- gardusig_cli-0.1.0/cli/services/pypi_publish.py +80 -0
- gardusig_cli-0.1.0/cli/services/replica_deploy.py +128 -0
- gardusig_cli-0.1.0/cli/utils/__init__.py +12 -0
- gardusig_cli-0.1.0/cli/utils/catalog.py +179 -0
- gardusig_cli-0.1.0/cli/utils/config.py +316 -0
- gardusig_cli-0.1.0/cli/utils/confirm.py +18 -0
- gardusig_cli-0.1.0/cli/utils/external_client.py +143 -0
- gardusig_cli-0.1.0/cli/utils/fs.py +13 -0
- gardusig_cli-0.1.0/cli/utils/hashing.py +12 -0
- gardusig_cli-0.1.0/cli/utils/http.py +10 -0
- gardusig_cli-0.1.0/cli/utils/logger.py +15 -0
- gardusig_cli-0.1.0/cli/utils/process.py +62 -0
- gardusig_cli-0.1.0/cli/utils/quick_defaults.py +40 -0
- gardusig_cli-0.1.0/cli/utils/retry.py +30 -0
- gardusig_cli-0.1.0/cli/utils/yaml.py +22 -0
- gardusig_cli-0.1.0/cli/utils/zip.py +18 -0
- gardusig_cli-0.1.0/cli/workflows/__init__.py +1 -0
- gardusig_cli-0.1.0/cli/workflows/backup.py +1 -0
- gardusig_cli-0.1.0/cli/workflows/restore.py +1 -0
- gardusig_cli-0.1.0/gardusig_cli.egg-info/PKG-INFO +274 -0
- gardusig_cli-0.1.0/gardusig_cli.egg-info/SOURCES.txt +162 -0
- gardusig_cli-0.1.0/gardusig_cli.egg-info/dependency_links.txt +1 -0
- gardusig_cli-0.1.0/gardusig_cli.egg-info/entry_points.txt +2 -0
- gardusig_cli-0.1.0/gardusig_cli.egg-info/requires.txt +13 -0
- gardusig_cli-0.1.0/gardusig_cli.egg-info/top_level.txt +1 -0
- gardusig_cli-0.1.0/pyproject.toml +80 -0
- gardusig_cli-0.1.0/setup.cfg +4 -0
- gardusig_cli-0.1.0/tests/test_api_workspaces.py +24 -0
- gardusig_cli-0.1.0/tests/test_backup_encrypt_config.py +28 -0
- gardusig_cli-0.1.0/tests/test_backup_repository.py +123 -0
- gardusig_cli-0.1.0/tests/test_backup_zip.py +51 -0
- gardusig_cli-0.1.0/tests/test_bookmark_scripts.py +149 -0
- gardusig_cli-0.1.0/tests/test_bootstrap_structure.py +172 -0
- gardusig_cli-0.1.0/tests/test_chrome_commands.py +76 -0
- gardusig_cli-0.1.0/tests/test_chrome_docker_integration.py +62 -0
- gardusig_cli-0.1.0/tests/test_cli_api_integration.py +75 -0
- gardusig_cli-0.1.0/tests/test_cli_endpoints.py +399 -0
- gardusig_cli-0.1.0/tests/test_cli_help.py +56 -0
- gardusig_cli-0.1.0/tests/test_contest_cli.py +59 -0
- gardusig_cli-0.1.0/tests/test_contest_docker_integration.py +66 -0
- gardusig_cli-0.1.0/tests/test_contest_integration_checks.py +27 -0
- gardusig_cli-0.1.0/tests/test_contest_runner.py +195 -0
- gardusig_cli-0.1.0/tests/test_contest_validate_integration.py +59 -0
- gardusig_cli-0.1.0/tests/test_coverage_unit_gate.py +47 -0
- gardusig_cli-0.1.0/tests/test_docker_commands.py +521 -0
- gardusig_cli-0.1.0/tests/test_docker_integration.py +87 -0
- gardusig_cli-0.1.0/tests/test_docker_integration_checks.py +27 -0
- gardusig_cli-0.1.0/tests/test_docker_integration_live.py +80 -0
- gardusig_cli-0.1.0/tests/test_docker_runtime.py +265 -0
- gardusig_cli-0.1.0/tests/test_drive_commands.py +129 -0
- gardusig_cli-0.1.0/tests/test_drive_docker_integration.py +45 -0
- gardusig_cli-0.1.0/tests/test_drive_internal.py +33 -0
- gardusig_cli-0.1.0/tests/test_drive_sync.py +66 -0
- gardusig_cli-0.1.0/tests/test_external_api_integration.py +250 -0
- gardusig_cli-0.1.0/tests/test_external_client.py +88 -0
- gardusig_cli-0.1.0/tests/test_gh_commands.py +134 -0
- gardusig_cli-0.1.0/tests/test_gh_docker_integration.py +38 -0
- gardusig_cli-0.1.0/tests/test_gh_labels_manifest.py +41 -0
- gardusig_cli-0.1.0/tests/test_gh_provider.py +41 -0
- gardusig_cli-0.1.0/tests/test_gh_sequence.py +35 -0
- gardusig_cli-0.1.0/tests/test_gh_service.py +192 -0
- gardusig_cli-0.1.0/tests/test_git_commands.py +335 -0
- gardusig_cli-0.1.0/tests/test_git_docker_harness.py +47 -0
- gardusig_cli-0.1.0/tests/test_git_mocks.py +36 -0
- gardusig_cli-0.1.0/tests/test_git_push_shortcut.py +105 -0
- gardusig_cli-0.1.0/tests/test_git_safety.py +47 -0
- gardusig_cli-0.1.0/tests/test_git_scripts.py +35 -0
- gardusig_cli-0.1.0/tests/test_git_shortcuts_service.py +627 -0
- gardusig_cli-0.1.0/tests/test_git_tag_zip.py +272 -0
- gardusig_cli-0.1.0/tests/test_git_workflow.py +96 -0
- gardusig_cli-0.1.0/tests/test_http_timeout.py +30 -0
- gardusig_cli-0.1.0/tests/test_integration_coverage_gate.py +82 -0
- gardusig_cli-0.1.0/tests/test_internal_read_write.py +73 -0
- gardusig_cli-0.1.0/tests/test_links_command.py +26 -0
- gardusig_cli-0.1.0/tests/test_notion_commands.py +171 -0
- gardusig_cli-0.1.0/tests/test_notion_docker_integration.py +131 -0
- gardusig_cli-0.1.0/tests/test_notion_internal.py +85 -0
- gardusig_cli-0.1.0/tests/test_notion_markdown.py +21 -0
- gardusig_cli-0.1.0/tests/test_notion_pairs.py +165 -0
- gardusig_cli-0.1.0/tests/test_notion_sync.py +186 -0
- gardusig_cli-0.1.0/tests/test_public_commands_integration.py +69 -0
- gardusig_cli-0.1.0/tests/test_public_endpoints_integration.py +73 -0
- gardusig_cli-0.1.0/tests/test_publish_commands.py +38 -0
- gardusig_cli-0.1.0/tests/test_pypi_packaging.py +28 -0
- gardusig_cli-0.1.0/tests/test_pypi_publish.py +53 -0
- gardusig_cli-0.1.0/tests/test_quick_defaults.py +40 -0
- gardusig_cli-0.1.0/tests/test_replica_deploy.py +39 -0
- gardusig_cli-0.1.0/tests/test_scripts_layout.py +25 -0
- gardusig_cli-0.1.0/tests/test_stubs_review_main.py +132 -0
- gardusig_cli-0.1.0/tests/test_tag_zip_integration.py +48 -0
- gardusig_cli-0.1.0/tests/test_unit_coverage.py +167 -0
- gardusig_cli-0.1.0/tests/test_utils_helpers.py +227 -0
- gardusig_cli-0.1.0/tests/test_workflow_integration.py +48 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Gustavo Gardusi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gardusig-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: macOS CLI for git shortcuts, backups, and sync workflows
|
|
5
|
+
Author: gardusig
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/gardusig/cli
|
|
8
|
+
Project-URL: Repository, https://github.com/gardusig/cli
|
|
9
|
+
Project-URL: Issues, https://github.com/gardusig/cli/issues
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Operating System :: MacOS
|
|
14
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Topic :: Software Development :: Version Control :: Git
|
|
19
|
+
Classifier: Topic :: Utilities
|
|
20
|
+
Requires-Python: >=3.12
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: typer>=0.12
|
|
24
|
+
Requires-Dist: pydantic>=2.0
|
|
25
|
+
Requires-Dist: pydantic-settings>=2.0
|
|
26
|
+
Requires-Dist: PyYAML>=6.0
|
|
27
|
+
Requires-Dist: rich>=13.0
|
|
28
|
+
Requires-Dist: httpx>=0.27
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: build>=1.0; extra == "dev"
|
|
31
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
32
|
+
Requires-Dist: pytest-cov>=5.0; extra == "dev"
|
|
33
|
+
Requires-Dist: pytest-timeout>=2.3; extra == "dev"
|
|
34
|
+
Requires-Dist: twine>=5.0; extra == "dev"
|
|
35
|
+
Dynamic: license-file
|
|
36
|
+
|
|
37
|
+
# cli
|
|
38
|
+
|
|
39
|
+
macOS CLI: **`cli git`** · **`cli drive`** · **`cli chrome`** · **`cli notion`**.
|
|
40
|
+
|
|
41
|
+
## Naming
|
|
42
|
+
|
|
43
|
+
| Context | Identifier |
|
|
44
|
+
| --- | --- |
|
|
45
|
+
| **GitHub repo** | [gardusig/cli](https://github.com/gardusig/cli) (clone path is usually `cli/`) |
|
|
46
|
+
| **PyPI package** | `gardusig-cli` — `pip install gardusig-cli` |
|
|
47
|
+
| **Console command** | `cli` (unchanged after PyPI install) |
|
|
48
|
+
| **Python import** | `cli` |
|
|
49
|
+
|
|
50
|
+
The repo stays **`cli`**; only the published distribution name on PyPI is **`gardusig-cli`** (`cli` is taken on PyPI).
|
|
51
|
+
|
|
52
|
+
## Requirements
|
|
53
|
+
|
|
54
|
+
| Tool | Needed for |
|
|
55
|
+
| --- | --- |
|
|
56
|
+
| **macOS** | Primary target for local use |
|
|
57
|
+
| **Python 3.12+** | Local install (`bootstrap.sh` creates a venv) |
|
|
58
|
+
| **[Homebrew](https://brew.sh/)** | Recommended way to install Python and git on macOS |
|
|
59
|
+
| **git** | `cli git` (run from inside a repository) |
|
|
60
|
+
| **zip** | Encrypted tag archives (`cli drive ingest` on `encrypted: true` repos) |
|
|
61
|
+
| **[Docker Desktop](https://www.docker.com/products/docker-desktop/)** | Verification — `./scripts/test-unit.sh` and `./scripts/test-integration.sh` in Docker |
|
|
62
|
+
|
|
63
|
+
Install Python and git with Homebrew:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
brew install python@3.12 git
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Optional: `gh` (GitHub CLI) for [cursor-skills](https://github.com/gardusig/cursor-skills) workflows — not required by cli itself.
|
|
70
|
+
|
|
71
|
+
## Configuration (global)
|
|
72
|
+
|
|
73
|
+
Cli reads **`config/config.yaml`** in the clone, or **`~/.config/cli/`** after install. Override the directory with `CLI_CONFIG_DIR`.
|
|
74
|
+
|
|
75
|
+
Copy the bundled `config/` tree and edit paths for your machine before daily use:
|
|
76
|
+
|
|
77
|
+
| Setting | Config key | Purpose |
|
|
78
|
+
| --- | --- | --- |
|
|
79
|
+
| **Git repositories** | `backup.repositories[].path` | Repos for `cli drive ingest` / `drive status` |
|
|
80
|
+
| **Tag zip folder** | `backup.tags_dir` | Local store (default: iCloud `git-tags/`) — source for `drive upload` |
|
|
81
|
+
| **Cloud upload roots** | `drives.yaml` → `google` / `onedrive` / `proton` | Remote folder names per provider |
|
|
82
|
+
| **Notion task root** | `notion.task_root` | Private `header/` + `body/` task files |
|
|
83
|
+
| **Notion pairs manifest** | `notion.pairs_file` | `config/notion/tasks.pairs.json` in this repo |
|
|
84
|
+
| **Notion database** | `notion.database_id` | Existing board ID + `NOTION_TOKEN` env |
|
|
85
|
+
| **Backup zip password** | `BACKUP_ZIP_PASSWORD` env | Encrypted repos (`encrypted: true` in `backup.repositories`) |
|
|
86
|
+
| **Chrome bookmarks file** | `chrome.bookmarks_file` | HTML backup (`chrome bookmarks ingest`) |
|
|
87
|
+
| **Chrome downloads** | `chrome.downloads_dir` | Folder polled when ingesting from Chrome |
|
|
88
|
+
|
|
89
|
+
Example `config.yaml`:
|
|
90
|
+
|
|
91
|
+
```yaml
|
|
92
|
+
backup:
|
|
93
|
+
tags_dir: ~/Library/Mobile Documents/com~apple~CloudDocs/git-tags
|
|
94
|
+
repositories:
|
|
95
|
+
- path: ~/git-local/cli
|
|
96
|
+
- path: ~/git-local/my-other-repo
|
|
97
|
+
|
|
98
|
+
notion:
|
|
99
|
+
database_id: your-notion-database-id
|
|
100
|
+
task_root: ~/git-local/private/configured/tasks
|
|
101
|
+
pairs_file: config/notion/tasks.pairs.json
|
|
102
|
+
|
|
103
|
+
chrome:
|
|
104
|
+
profile: Default
|
|
105
|
+
bookmarks_file: ~/git-local/private/bookmarks/bookmarks.html
|
|
106
|
+
downloads_dir: ~/Downloads
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Test fixtures (not for production) live under `tests/fixtures/notion/tasks` and `tests/fixtures/bookmarks.html`.
|
|
110
|
+
|
|
111
|
+
Cloud providers: `config/drives.yaml`. Notion token: **`export NOTION_TOKEN=...`** (never commit).
|
|
112
|
+
|
|
113
|
+
Environment overrides (optional): `CLI_BOOKMARKS_FILE`, `CLI_DOWNLOADS_DIR`, `CLI_CONFIG_DIR`, `NOTION_TOKEN`.
|
|
114
|
+
|
|
115
|
+
## Install (macOS)
|
|
116
|
+
|
|
117
|
+
**Global install (recommended):** `cli` works in any terminal after one setup.
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
./scripts/install.sh
|
|
121
|
+
# open a new terminal OR: source ~/.zprofile
|
|
122
|
+
cli --version
|
|
123
|
+
cli git --help
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**Dev install (current shell only):** venv + runtime deps for working in this repo.
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
./scripts/bootstrap.sh
|
|
130
|
+
source .venv/bin/activate
|
|
131
|
+
python -m cli --help
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Verification always runs in Docker — same image locally and in CI. Do not run `pytest` on the host; use `./scripts/test-unit.sh` and `./scripts/test-integration.sh` instead.
|
|
135
|
+
|
|
136
|
+
## Common git commands
|
|
137
|
+
|
|
138
|
+
Run from inside a repository (`cd` into the repo first).
|
|
139
|
+
|
|
140
|
+
| Task | Command |
|
|
141
|
+
| --- | --- |
|
|
142
|
+
| **Sync main** (before/after work) | `cli git reset --yes` (`--main-only` to skip branch prune) |
|
|
143
|
+
| **Start issue** (align main + branch) | `cli git start issue-9-slug --yes` |
|
|
144
|
+
| **During work** (add + commit + push) | `cli git push --yes` (on `main`, starts random branch first) |
|
|
145
|
+
| Branch in place (no align) | `cli git start [name] --no-prep` |
|
|
146
|
+
| Commit only | `cli git commit` |
|
|
147
|
+
| Sync feature branch | `cli git pull` |
|
|
148
|
+
| Delete merged branch | `cli git branch-delete BRANCH --yes` |
|
|
149
|
+
| Clear all branches (keep `main`) | `cli git branch-clear --yes` |
|
|
150
|
+
| Tag on main (default: today) | `cli git tag` · `cli git tag list` · `cli git tag push` |
|
|
151
|
+
| Zip one tag (cwd repo) | `cli git zip` · `cli git zip TAG` |
|
|
152
|
+
|
|
153
|
+
Short alias: `cli g push --yes` == `cli git push --yes`.
|
|
154
|
+
|
|
155
|
+
Shell wrappers: `scripts/git/` (e.g. `./scripts/git/review.sh`). See [docs/git.md](docs/git.md).
|
|
156
|
+
|
|
157
|
+
**Safety:** destructive actions (reset, clean, delete, push) require `--yes` or an interactive confirmation. Default `cli git start` aligns main then branches; pass `--no-prep` to branch from the current state.
|
|
158
|
+
|
|
159
|
+
## Drive (`cli drive`)
|
|
160
|
+
|
|
161
|
+
Local hub: **iCloud** `git-tags/{repo}/{repo}-{tag}.zip` (via `backup.tags_dir`). Cloud: append-only upload to Google Drive, OneDrive, Proton.
|
|
162
|
+
|
|
163
|
+
| Task | Command |
|
|
164
|
+
| --- | --- |
|
|
165
|
+
| **Status** (git tags vs local zips) | `cli drive status` |
|
|
166
|
+
| **Ingest** (zip all tags → local store) | `cli drive ingest` (all repos in config) or `cli drive ingest PATH` |
|
|
167
|
+
| List local zips | `cli drive list` · `cli drive list PATH` |
|
|
168
|
+
| Delete local zip | `cli drive delete PATH TAG --yes` |
|
|
169
|
+
| **Upload** to cloud | `cli drive upload` · `cli drive upload google` · `onedrive` · `proton` |
|
|
170
|
+
| **Sync** (ingest all + upload all) | `cli drive sync` |
|
|
171
|
+
|
|
172
|
+
Typical end-of-day:
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
cli git tag --yes && cli git zip # single repo (cwd)
|
|
176
|
+
cli drive upload # push missing zips to cloud
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Multi-repo:
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
cli drive sync # ingest all repos + upload all clouds
|
|
183
|
+
# or step by step:
|
|
184
|
+
cli drive ingest
|
|
185
|
+
cli drive status
|
|
186
|
+
cli drive upload
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
`git zip` is the quick path for the current repo; `drive ingest` iterates configured repositories (or one `PATH`). See [docs/drive.md](docs/drive.md) · [issue #4](https://github.com/gardusig/cli/issues/4).
|
|
190
|
+
|
|
191
|
+
Shell wrappers: `scripts/drive/` (`status.sh`, `ingest.sh`, `upload.sh`, `sync.sh`).
|
|
192
|
+
|
|
193
|
+
## Chrome (`cli chrome`)
|
|
194
|
+
|
|
195
|
+
Browser integrations; **bookmarks** is the first subcommand. Path: **`chrome.bookmarks_file`** in config.
|
|
196
|
+
|
|
197
|
+
| Direction | Command |
|
|
198
|
+
| --- | --- |
|
|
199
|
+
| **Chrome → local** | `cli chrome bookmarks ingest` |
|
|
200
|
+
| **Local → Chrome** | `cli chrome bookmarks deploy` |
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
cli chrome bookmarks ingest # Chrome → local HTML file
|
|
204
|
+
cli chrome bookmarks deploy # local file → Chrome
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Shell wrappers: `./scripts/chrome/ingest.sh` · `./scripts/chrome/deploy.sh` (deprecated: `import.sh` / `export.sh`).
|
|
208
|
+
|
|
209
|
+
See [docs/bookmarks.md](docs/bookmarks.md) · epic [#24](https://github.com/gardusig/cli/issues/24) (shell scripts: [#1](https://github.com/gardusig/cli/issues/1)).
|
|
210
|
+
|
|
211
|
+
## Notion (`cli notion`)
|
|
212
|
+
|
|
213
|
+
Local tasks: **`notion.task_root`** (private header/body) + **`notion.pairs_file`** (`config/notion/tasks.pairs.json`). Auth: **`NOTION_TOKEN`** + `notion.database_id`.
|
|
214
|
+
|
|
215
|
+
| Command | Purpose |
|
|
216
|
+
| --- | --- |
|
|
217
|
+
| `cli notion pairs build` | Scan header/ + body/ → `tasks.pairs.json` |
|
|
218
|
+
| `cli notion ingest` | Notion → local pairs |
|
|
219
|
+
| `cli notion deploy --yes` | Local pairs → Notion (archives board first by default) |
|
|
220
|
+
| `cli notion sync --yes` | Ingest from Notion, then deploy local tasks |
|
|
221
|
+
| `cli notion cleanup --yes` | Archive all database pages |
|
|
222
|
+
|
|
223
|
+
See [docs/notion.md](docs/notion.md) · epic [#2](https://github.com/gardusig/cli/issues/2) · children [#20](https://github.com/gardusig/cli/issues/20)–[#23](https://github.com/gardusig/cli/issues/23).
|
|
224
|
+
|
|
225
|
+
## Docker
|
|
226
|
+
|
|
227
|
+
Local Docker monitor and cleanup (requires `docker` on PATH; no container start):
|
|
228
|
+
|
|
229
|
+
| Task | Command |
|
|
230
|
+
| --- | --- |
|
|
231
|
+
| **Dashboard** (CPU, memory, storage) | `cli docker top` |
|
|
232
|
+
| **By domain** | `cli docker stats --by cpu` / `memory` / `storage` |
|
|
233
|
+
| **Storage lists** | `cli docker images` · `cli docker containers` · `cli docker df` |
|
|
234
|
+
| **Stop running** | `cli docker stop --yes` |
|
|
235
|
+
| **Delete containers** | `cli docker container-delete --yes` |
|
|
236
|
+
| **Prune images** | `cli docker image-delete --yes` (`--all-images` for all unused) |
|
|
237
|
+
| **Full reset** | `cli docker reset --yes` |
|
|
238
|
+
| Targeted cleanup | `cli docker clean containers --yes` · `clean images` · `clean all` |
|
|
239
|
+
|
|
240
|
+
Shell wrappers live in `scripts/docker/` (e.g. `./scripts/docker/reset.sh --yes`).
|
|
241
|
+
|
|
242
|
+
Destructive commands use the write gate; pass `--yes` in scripts.
|
|
243
|
+
|
|
244
|
+
## Verify (Docker)
|
|
245
|
+
|
|
246
|
+
Requires [Docker Desktop](https://www.docker.com/products/docker-desktop/) on macOS (or Docker Engine on Linux). The `cli:dev` Linux image is the only supported test environment:
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
./scripts/docker/build-image.sh # build once (or auto-build on first test run)
|
|
250
|
+
./scripts/test-unit.sh # unit tests (≥80% coverage)
|
|
251
|
+
./scripts/test-integration.sh # full pytest + smoke + live docker
|
|
252
|
+
./scripts/docker/shell.sh # onboard: interactive shell in container
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
See [docs/docker.md](docs/docker.md).
|
|
256
|
+
|
|
257
|
+
## Docs
|
|
258
|
+
|
|
259
|
+
- [Setup](docs/setup.md)
|
|
260
|
+
- [Git commands](docs/git.md)
|
|
261
|
+
- [GitHub (`cli gh`)](docs/gh.md)
|
|
262
|
+
- [Drive (local + cloud)](docs/drive.md)
|
|
263
|
+
- [Chrome](docs/bookmarks.md) · [Notion](docs/notion.md)
|
|
264
|
+
- [Docker integration](docs/docker.md)
|
|
265
|
+
- [Configuration](docs/configuration.md)
|
|
266
|
+
- [Architecture](docs/architecture.md)
|
|
267
|
+
|
|
268
|
+
## Related
|
|
269
|
+
|
|
270
|
+
- [cursor-skills](https://github.com/gardusig/cursor-skills) — `@gh-*` AI workflows for issues/PRs
|
|
271
|
+
- Cloud drive epic: [cli #4](https://github.com/gardusig/cli/issues/4)
|
|
272
|
+
- Bootstrap spec: [cli #3](https://github.com/gardusig/cli/issues/3)
|
|
273
|
+
- Chrome: [cli #24](https://github.com/gardusig/cli/issues/24) · bookmarks scripts [#1](https://github.com/gardusig/cli/issues/1)
|
|
274
|
+
- Docker integration: [cli #9](https://github.com/gardusig/cli/issues/9)
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
# cli
|
|
2
|
+
|
|
3
|
+
macOS CLI: **`cli git`** · **`cli drive`** · **`cli chrome`** · **`cli notion`**.
|
|
4
|
+
|
|
5
|
+
## Naming
|
|
6
|
+
|
|
7
|
+
| Context | Identifier |
|
|
8
|
+
| --- | --- |
|
|
9
|
+
| **GitHub repo** | [gardusig/cli](https://github.com/gardusig/cli) (clone path is usually `cli/`) |
|
|
10
|
+
| **PyPI package** | `gardusig-cli` — `pip install gardusig-cli` |
|
|
11
|
+
| **Console command** | `cli` (unchanged after PyPI install) |
|
|
12
|
+
| **Python import** | `cli` |
|
|
13
|
+
|
|
14
|
+
The repo stays **`cli`**; only the published distribution name on PyPI is **`gardusig-cli`** (`cli` is taken on PyPI).
|
|
15
|
+
|
|
16
|
+
## Requirements
|
|
17
|
+
|
|
18
|
+
| Tool | Needed for |
|
|
19
|
+
| --- | --- |
|
|
20
|
+
| **macOS** | Primary target for local use |
|
|
21
|
+
| **Python 3.12+** | Local install (`bootstrap.sh` creates a venv) |
|
|
22
|
+
| **[Homebrew](https://brew.sh/)** | Recommended way to install Python and git on macOS |
|
|
23
|
+
| **git** | `cli git` (run from inside a repository) |
|
|
24
|
+
| **zip** | Encrypted tag archives (`cli drive ingest` on `encrypted: true` repos) |
|
|
25
|
+
| **[Docker Desktop](https://www.docker.com/products/docker-desktop/)** | Verification — `./scripts/test-unit.sh` and `./scripts/test-integration.sh` in Docker |
|
|
26
|
+
|
|
27
|
+
Install Python and git with Homebrew:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
brew install python@3.12 git
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Optional: `gh` (GitHub CLI) for [cursor-skills](https://github.com/gardusig/cursor-skills) workflows — not required by cli itself.
|
|
34
|
+
|
|
35
|
+
## Configuration (global)
|
|
36
|
+
|
|
37
|
+
Cli reads **`config/config.yaml`** in the clone, or **`~/.config/cli/`** after install. Override the directory with `CLI_CONFIG_DIR`.
|
|
38
|
+
|
|
39
|
+
Copy the bundled `config/` tree and edit paths for your machine before daily use:
|
|
40
|
+
|
|
41
|
+
| Setting | Config key | Purpose |
|
|
42
|
+
| --- | --- | --- |
|
|
43
|
+
| **Git repositories** | `backup.repositories[].path` | Repos for `cli drive ingest` / `drive status` |
|
|
44
|
+
| **Tag zip folder** | `backup.tags_dir` | Local store (default: iCloud `git-tags/`) — source for `drive upload` |
|
|
45
|
+
| **Cloud upload roots** | `drives.yaml` → `google` / `onedrive` / `proton` | Remote folder names per provider |
|
|
46
|
+
| **Notion task root** | `notion.task_root` | Private `header/` + `body/` task files |
|
|
47
|
+
| **Notion pairs manifest** | `notion.pairs_file` | `config/notion/tasks.pairs.json` in this repo |
|
|
48
|
+
| **Notion database** | `notion.database_id` | Existing board ID + `NOTION_TOKEN` env |
|
|
49
|
+
| **Backup zip password** | `BACKUP_ZIP_PASSWORD` env | Encrypted repos (`encrypted: true` in `backup.repositories`) |
|
|
50
|
+
| **Chrome bookmarks file** | `chrome.bookmarks_file` | HTML backup (`chrome bookmarks ingest`) |
|
|
51
|
+
| **Chrome downloads** | `chrome.downloads_dir` | Folder polled when ingesting from Chrome |
|
|
52
|
+
|
|
53
|
+
Example `config.yaml`:
|
|
54
|
+
|
|
55
|
+
```yaml
|
|
56
|
+
backup:
|
|
57
|
+
tags_dir: ~/Library/Mobile Documents/com~apple~CloudDocs/git-tags
|
|
58
|
+
repositories:
|
|
59
|
+
- path: ~/git-local/cli
|
|
60
|
+
- path: ~/git-local/my-other-repo
|
|
61
|
+
|
|
62
|
+
notion:
|
|
63
|
+
database_id: your-notion-database-id
|
|
64
|
+
task_root: ~/git-local/private/configured/tasks
|
|
65
|
+
pairs_file: config/notion/tasks.pairs.json
|
|
66
|
+
|
|
67
|
+
chrome:
|
|
68
|
+
profile: Default
|
|
69
|
+
bookmarks_file: ~/git-local/private/bookmarks/bookmarks.html
|
|
70
|
+
downloads_dir: ~/Downloads
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Test fixtures (not for production) live under `tests/fixtures/notion/tasks` and `tests/fixtures/bookmarks.html`.
|
|
74
|
+
|
|
75
|
+
Cloud providers: `config/drives.yaml`. Notion token: **`export NOTION_TOKEN=...`** (never commit).
|
|
76
|
+
|
|
77
|
+
Environment overrides (optional): `CLI_BOOKMARKS_FILE`, `CLI_DOWNLOADS_DIR`, `CLI_CONFIG_DIR`, `NOTION_TOKEN`.
|
|
78
|
+
|
|
79
|
+
## Install (macOS)
|
|
80
|
+
|
|
81
|
+
**Global install (recommended):** `cli` works in any terminal after one setup.
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
./scripts/install.sh
|
|
85
|
+
# open a new terminal OR: source ~/.zprofile
|
|
86
|
+
cli --version
|
|
87
|
+
cli git --help
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Dev install (current shell only):** venv + runtime deps for working in this repo.
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
./scripts/bootstrap.sh
|
|
94
|
+
source .venv/bin/activate
|
|
95
|
+
python -m cli --help
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Verification always runs in Docker — same image locally and in CI. Do not run `pytest` on the host; use `./scripts/test-unit.sh` and `./scripts/test-integration.sh` instead.
|
|
99
|
+
|
|
100
|
+
## Common git commands
|
|
101
|
+
|
|
102
|
+
Run from inside a repository (`cd` into the repo first).
|
|
103
|
+
|
|
104
|
+
| Task | Command |
|
|
105
|
+
| --- | --- |
|
|
106
|
+
| **Sync main** (before/after work) | `cli git reset --yes` (`--main-only` to skip branch prune) |
|
|
107
|
+
| **Start issue** (align main + branch) | `cli git start issue-9-slug --yes` |
|
|
108
|
+
| **During work** (add + commit + push) | `cli git push --yes` (on `main`, starts random branch first) |
|
|
109
|
+
| Branch in place (no align) | `cli git start [name] --no-prep` |
|
|
110
|
+
| Commit only | `cli git commit` |
|
|
111
|
+
| Sync feature branch | `cli git pull` |
|
|
112
|
+
| Delete merged branch | `cli git branch-delete BRANCH --yes` |
|
|
113
|
+
| Clear all branches (keep `main`) | `cli git branch-clear --yes` |
|
|
114
|
+
| Tag on main (default: today) | `cli git tag` · `cli git tag list` · `cli git tag push` |
|
|
115
|
+
| Zip one tag (cwd repo) | `cli git zip` · `cli git zip TAG` |
|
|
116
|
+
|
|
117
|
+
Short alias: `cli g push --yes` == `cli git push --yes`.
|
|
118
|
+
|
|
119
|
+
Shell wrappers: `scripts/git/` (e.g. `./scripts/git/review.sh`). See [docs/git.md](docs/git.md).
|
|
120
|
+
|
|
121
|
+
**Safety:** destructive actions (reset, clean, delete, push) require `--yes` or an interactive confirmation. Default `cli git start` aligns main then branches; pass `--no-prep` to branch from the current state.
|
|
122
|
+
|
|
123
|
+
## Drive (`cli drive`)
|
|
124
|
+
|
|
125
|
+
Local hub: **iCloud** `git-tags/{repo}/{repo}-{tag}.zip` (via `backup.tags_dir`). Cloud: append-only upload to Google Drive, OneDrive, Proton.
|
|
126
|
+
|
|
127
|
+
| Task | Command |
|
|
128
|
+
| --- | --- |
|
|
129
|
+
| **Status** (git tags vs local zips) | `cli drive status` |
|
|
130
|
+
| **Ingest** (zip all tags → local store) | `cli drive ingest` (all repos in config) or `cli drive ingest PATH` |
|
|
131
|
+
| List local zips | `cli drive list` · `cli drive list PATH` |
|
|
132
|
+
| Delete local zip | `cli drive delete PATH TAG --yes` |
|
|
133
|
+
| **Upload** to cloud | `cli drive upload` · `cli drive upload google` · `onedrive` · `proton` |
|
|
134
|
+
| **Sync** (ingest all + upload all) | `cli drive sync` |
|
|
135
|
+
|
|
136
|
+
Typical end-of-day:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
cli git tag --yes && cli git zip # single repo (cwd)
|
|
140
|
+
cli drive upload # push missing zips to cloud
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Multi-repo:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
cli drive sync # ingest all repos + upload all clouds
|
|
147
|
+
# or step by step:
|
|
148
|
+
cli drive ingest
|
|
149
|
+
cli drive status
|
|
150
|
+
cli drive upload
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
`git zip` is the quick path for the current repo; `drive ingest` iterates configured repositories (or one `PATH`). See [docs/drive.md](docs/drive.md) · [issue #4](https://github.com/gardusig/cli/issues/4).
|
|
154
|
+
|
|
155
|
+
Shell wrappers: `scripts/drive/` (`status.sh`, `ingest.sh`, `upload.sh`, `sync.sh`).
|
|
156
|
+
|
|
157
|
+
## Chrome (`cli chrome`)
|
|
158
|
+
|
|
159
|
+
Browser integrations; **bookmarks** is the first subcommand. Path: **`chrome.bookmarks_file`** in config.
|
|
160
|
+
|
|
161
|
+
| Direction | Command |
|
|
162
|
+
| --- | --- |
|
|
163
|
+
| **Chrome → local** | `cli chrome bookmarks ingest` |
|
|
164
|
+
| **Local → Chrome** | `cli chrome bookmarks deploy` |
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
cli chrome bookmarks ingest # Chrome → local HTML file
|
|
168
|
+
cli chrome bookmarks deploy # local file → Chrome
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Shell wrappers: `./scripts/chrome/ingest.sh` · `./scripts/chrome/deploy.sh` (deprecated: `import.sh` / `export.sh`).
|
|
172
|
+
|
|
173
|
+
See [docs/bookmarks.md](docs/bookmarks.md) · epic [#24](https://github.com/gardusig/cli/issues/24) (shell scripts: [#1](https://github.com/gardusig/cli/issues/1)).
|
|
174
|
+
|
|
175
|
+
## Notion (`cli notion`)
|
|
176
|
+
|
|
177
|
+
Local tasks: **`notion.task_root`** (private header/body) + **`notion.pairs_file`** (`config/notion/tasks.pairs.json`). Auth: **`NOTION_TOKEN`** + `notion.database_id`.
|
|
178
|
+
|
|
179
|
+
| Command | Purpose |
|
|
180
|
+
| --- | --- |
|
|
181
|
+
| `cli notion pairs build` | Scan header/ + body/ → `tasks.pairs.json` |
|
|
182
|
+
| `cli notion ingest` | Notion → local pairs |
|
|
183
|
+
| `cli notion deploy --yes` | Local pairs → Notion (archives board first by default) |
|
|
184
|
+
| `cli notion sync --yes` | Ingest from Notion, then deploy local tasks |
|
|
185
|
+
| `cli notion cleanup --yes` | Archive all database pages |
|
|
186
|
+
|
|
187
|
+
See [docs/notion.md](docs/notion.md) · epic [#2](https://github.com/gardusig/cli/issues/2) · children [#20](https://github.com/gardusig/cli/issues/20)–[#23](https://github.com/gardusig/cli/issues/23).
|
|
188
|
+
|
|
189
|
+
## Docker
|
|
190
|
+
|
|
191
|
+
Local Docker monitor and cleanup (requires `docker` on PATH; no container start):
|
|
192
|
+
|
|
193
|
+
| Task | Command |
|
|
194
|
+
| --- | --- |
|
|
195
|
+
| **Dashboard** (CPU, memory, storage) | `cli docker top` |
|
|
196
|
+
| **By domain** | `cli docker stats --by cpu` / `memory` / `storage` |
|
|
197
|
+
| **Storage lists** | `cli docker images` · `cli docker containers` · `cli docker df` |
|
|
198
|
+
| **Stop running** | `cli docker stop --yes` |
|
|
199
|
+
| **Delete containers** | `cli docker container-delete --yes` |
|
|
200
|
+
| **Prune images** | `cli docker image-delete --yes` (`--all-images` for all unused) |
|
|
201
|
+
| **Full reset** | `cli docker reset --yes` |
|
|
202
|
+
| Targeted cleanup | `cli docker clean containers --yes` · `clean images` · `clean all` |
|
|
203
|
+
|
|
204
|
+
Shell wrappers live in `scripts/docker/` (e.g. `./scripts/docker/reset.sh --yes`).
|
|
205
|
+
|
|
206
|
+
Destructive commands use the write gate; pass `--yes` in scripts.
|
|
207
|
+
|
|
208
|
+
## Verify (Docker)
|
|
209
|
+
|
|
210
|
+
Requires [Docker Desktop](https://www.docker.com/products/docker-desktop/) on macOS (or Docker Engine on Linux). The `cli:dev` Linux image is the only supported test environment:
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
./scripts/docker/build-image.sh # build once (or auto-build on first test run)
|
|
214
|
+
./scripts/test-unit.sh # unit tests (≥80% coverage)
|
|
215
|
+
./scripts/test-integration.sh # full pytest + smoke + live docker
|
|
216
|
+
./scripts/docker/shell.sh # onboard: interactive shell in container
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
See [docs/docker.md](docs/docker.md).
|
|
220
|
+
|
|
221
|
+
## Docs
|
|
222
|
+
|
|
223
|
+
- [Setup](docs/setup.md)
|
|
224
|
+
- [Git commands](docs/git.md)
|
|
225
|
+
- [GitHub (`cli gh`)](docs/gh.md)
|
|
226
|
+
- [Drive (local + cloud)](docs/drive.md)
|
|
227
|
+
- [Chrome](docs/bookmarks.md) · [Notion](docs/notion.md)
|
|
228
|
+
- [Docker integration](docs/docker.md)
|
|
229
|
+
- [Configuration](docs/configuration.md)
|
|
230
|
+
- [Architecture](docs/architecture.md)
|
|
231
|
+
|
|
232
|
+
## Related
|
|
233
|
+
|
|
234
|
+
- [cursor-skills](https://github.com/gardusig/cursor-skills) — `@gh-*` AI workflows for issues/PRs
|
|
235
|
+
- Cloud drive epic: [cli #4](https://github.com/gardusig/cli/issues/4)
|
|
236
|
+
- Bootstrap spec: [cli #3](https://github.com/gardusig/cli/issues/3)
|
|
237
|
+
- Chrome: [cli #24](https://github.com/gardusig/cli/issues/24) · bookmarks scripts [#1](https://github.com/gardusig/cli/issues/1)
|
|
238
|
+
- Docker integration: [cli #9](https://github.com/gardusig/cli/issues/9)
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import typer
|
|
4
|
+
|
|
5
|
+
from cli import __version__
|
|
6
|
+
from cli.commands.backup import backup_app
|
|
7
|
+
from cli.commands.bookmarks import bookmarks_app
|
|
8
|
+
from cli.commands.chrome import chrome_app
|
|
9
|
+
from cli.commands.contest import contest_app
|
|
10
|
+
from cli.commands.docker import docker_app
|
|
11
|
+
from cli.commands.drive import drive_app
|
|
12
|
+
from cli.commands.gh import gh_app
|
|
13
|
+
from cli.commands.git import git_app
|
|
14
|
+
from cli.commands.links import links_app
|
|
15
|
+
from cli.commands.notion import notion_app
|
|
16
|
+
from cli.commands.publish import publish_app
|
|
17
|
+
from cli.commands.restore import restore_app
|
|
18
|
+
from cli.utils.logger import setup_logging
|
|
19
|
+
|
|
20
|
+
app = typer.Typer(
|
|
21
|
+
name="cli",
|
|
22
|
+
help="Git shortcuts and drive (tag zips) for macOS. Run `cli links` for docs and scripts.",
|
|
23
|
+
no_args_is_help=True,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
app.add_typer(links_app, name="links")
|
|
27
|
+
app.add_typer(git_app, name="git")
|
|
28
|
+
app.add_typer(gh_app, name="gh")
|
|
29
|
+
app.add_typer(backup_app, name="backup", hidden=True)
|
|
30
|
+
app.add_typer(restore_app, name="restore")
|
|
31
|
+
app.add_typer(drive_app, name="drive")
|
|
32
|
+
app.add_typer(notion_app, name="notion")
|
|
33
|
+
app.add_typer(chrome_app, name="chrome")
|
|
34
|
+
app.add_typer(bookmarks_app, name="bookmarks", hidden=True)
|
|
35
|
+
app.add_typer(docker_app, name="docker")
|
|
36
|
+
app.add_typer(contest_app, name="contest")
|
|
37
|
+
app.add_typer(publish_app, name="publish")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@app.callback(invoke_without_command=True)
|
|
41
|
+
def main(
|
|
42
|
+
ctx: typer.Context,
|
|
43
|
+
version: bool = typer.Option(False, "--version", "-V", help="Show version and exit."),
|
|
44
|
+
verbose: bool = typer.Option(False, "--verbose", "-v"),
|
|
45
|
+
) -> None:
|
|
46
|
+
setup_logging(verbose=verbose)
|
|
47
|
+
if version:
|
|
48
|
+
typer.echo(__version__)
|
|
49
|
+
raise typer.Exit()
|
|
50
|
+
if ctx.invoked_subcommand is None and not version:
|
|
51
|
+
typer.echo(ctx.get_help())
|
|
52
|
+
typer.echo("\nFull index: cli links | docs/README.md")
|
|
53
|
+
raise typer.Exit()
|
|
54
|
+
ctx.obj = {"verbose": verbose}
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def run() -> None:
|
|
58
|
+
"""CLI entrypoint — surfaces ExternalCallError as a clean user message."""
|
|
59
|
+
from cli.utils.config import load_local_env
|
|
60
|
+
from cli.utils.external_client import ExternalCallError
|
|
61
|
+
|
|
62
|
+
load_local_env()
|
|
63
|
+
try:
|
|
64
|
+
app()
|
|
65
|
+
except ExternalCallError as exc:
|
|
66
|
+
typer.echo(exc.user_message, err=True)
|
|
67
|
+
raise typer.Exit(1) from exc
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
# Short alias: cli g <cmd> == cli git <cmd>
|
|
71
|
+
app.add_typer(git_app, name="g", hidden=True)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""CLI command modules."""
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""Hidden aliases for legacy `cli backup` → use `cli drive` instead."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import typer
|
|
6
|
+
|
|
7
|
+
from cli.commands.drive import delete_cmd, ingest_cmd, list_cmd, status_cmd
|
|
8
|
+
|
|
9
|
+
backup_app = typer.Typer(
|
|
10
|
+
help="(deprecated) use cli drive",
|
|
11
|
+
no_args_is_help=True,
|
|
12
|
+
hidden=True,
|
|
13
|
+
)
|
|
14
|
+
repository_app = typer.Typer(help="(deprecated)", hidden=True)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@backup_app.command("status")
|
|
18
|
+
def backup_status_alias() -> None:
|
|
19
|
+
"""Deprecated: use `cli drive status`."""
|
|
20
|
+
status_cmd()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@repository_app.command("sync")
|
|
24
|
+
def repository_sync_alias(
|
|
25
|
+
path: str | None = typer.Argument(None),
|
|
26
|
+
) -> None:
|
|
27
|
+
"""Deprecated: use `cli drive ingest`."""
|
|
28
|
+
ingest_cmd(path)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@repository_app.command("list")
|
|
32
|
+
def repository_list_alias(
|
|
33
|
+
path: str | None = typer.Argument(None),
|
|
34
|
+
) -> None:
|
|
35
|
+
"""Deprecated: use `cli drive list`."""
|
|
36
|
+
list_cmd(path)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@repository_app.command("delete")
|
|
40
|
+
def repository_delete_alias(
|
|
41
|
+
path: str = typer.Argument(...),
|
|
42
|
+
tag: str = typer.Argument(...),
|
|
43
|
+
yes: bool = typer.Option(False, "--yes", "-y"),
|
|
44
|
+
) -> None:
|
|
45
|
+
"""Deprecated: use `cli drive delete`."""
|
|
46
|
+
delete_cmd(path, tag, yes=yes)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
backup_app.add_typer(repository_app, name="repository")
|