sync-pilot 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.
- sync_pilot-0.1.0/.gitignore +7 -0
- sync_pilot-0.1.0/LICENSE +21 -0
- sync_pilot-0.1.0/PKG-INFO +127 -0
- sync_pilot-0.1.0/README.md +105 -0
- sync_pilot-0.1.0/pyproject.toml +33 -0
- sync_pilot-0.1.0/src/sync_pilot/__init__.py +3 -0
- sync_pilot-0.1.0/src/sync_pilot/cli.py +113 -0
- sync_pilot-0.1.0/src/sync_pilot/core.py +628 -0
- sync_pilot-0.1.0/src/sync_pilot/i18n.py +365 -0
- sync_pilot-0.1.0/src/sync_pilot/templates/rsync_exclude.txt +45 -0
- sync_pilot-0.1.0/src/sync_pilot/templates/sync_config.yaml +29 -0
sync_pilot-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Liang Yi
|
|
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,127 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sync-pilot
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Interactive TUI tool for syncing projects to remote servers via rsync + SSH
|
|
5
|
+
Project-URL: Homepage, https://github.com/cidxb/sync-pilot
|
|
6
|
+
Project-URL: Repository, https://github.com/cidxb/sync-pilot
|
|
7
|
+
Author: Liang Yi
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: remote,rsync,ssh,sync,training,tui
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Topic :: System :: Systems Administration
|
|
17
|
+
Classifier: Topic :: Utilities
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Requires-Dist: pyyaml>=6.0
|
|
20
|
+
Requires-Dist: rich>=13.0
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
|
|
23
|
+
# sync-pilot
|
|
24
|
+
|
|
25
|
+
交互式 TUI 工具,通过 rsync + SSH 同步项目到远端服务器。专为 ML/DL 训练工作流设计。
|
|
26
|
+
|
|
27
|
+
Interactive TUI tool for syncing projects to remote servers via rsync + SSH. Built for ML/DL training workflows.
|
|
28
|
+
|
|
29
|
+
## Features / 功能
|
|
30
|
+
|
|
31
|
+
- **Push/Pull** — rsync 同步代码和 checkpoints
|
|
32
|
+
- **Remote Training** — 一键推送代码 + tmux 启动远端训练,自动加 `uv run` 前缀
|
|
33
|
+
- **Monitor** — GPU 状态、tmux session 输出查看、实时 attach、session 管理
|
|
34
|
+
- **Status** — 项目状态总览(远端目录大小、checkpoint 数量)
|
|
35
|
+
- **Data Push** — 一次性推送大型数据集
|
|
36
|
+
- **i18n** — 自动检测系统语言(中/英),支持 `--lang` 和 `SYNC_PILOT_LANG` 覆盖
|
|
37
|
+
|
|
38
|
+
## Install / 安装
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pip install sync-pilot
|
|
42
|
+
# or
|
|
43
|
+
uv add sync-pilot
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Quick Start / 快速开始
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# 1. Initialize config in your project directory
|
|
50
|
+
cd /path/to/your/project
|
|
51
|
+
sync-pilot init
|
|
52
|
+
|
|
53
|
+
# 2. Edit sync_config.yaml with your remote server info
|
|
54
|
+
vim sync_config.yaml
|
|
55
|
+
|
|
56
|
+
# 3. Launch interactive TUI
|
|
57
|
+
sync-pilot
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Usage / 使用
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
sync-pilot # Interactive TUI menu
|
|
64
|
+
sync-pilot init # Generate config files in current directory
|
|
65
|
+
sync-pilot push # Push code to remote
|
|
66
|
+
sync-pilot pull # Pull checkpoints from remote
|
|
67
|
+
sync-pilot train # Push + launch remote training
|
|
68
|
+
sync-pilot push-data # One-time data upload
|
|
69
|
+
sync-pilot watch # Monitor GPU & tmux sessions
|
|
70
|
+
sync-pilot status # Project status overview
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Options
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
-c, --config FILE Config file path (default: auto-detect)
|
|
77
|
+
-p, --project NAME Target project name
|
|
78
|
+
--lang zh|en Force UI language
|
|
79
|
+
-V, --version Show version
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Configuration / 配置
|
|
83
|
+
|
|
84
|
+
`sync_config.yaml`:
|
|
85
|
+
|
|
86
|
+
```yaml
|
|
87
|
+
remote_host: 1.2.3.4
|
|
88
|
+
remote_user: root
|
|
89
|
+
remote_port: 22 # Optional, default 22
|
|
90
|
+
|
|
91
|
+
projects:
|
|
92
|
+
my_project:
|
|
93
|
+
description: "My ML project"
|
|
94
|
+
local_path: /home/user/workspace/project/
|
|
95
|
+
remote_path: /mnt/workspace/project/
|
|
96
|
+
exclude_file: rsync_exclude.txt # Relative to this config file
|
|
97
|
+
use_uv: true # Auto-prefix python commands with uv run
|
|
98
|
+
pull_directories:
|
|
99
|
+
- checkpoints/
|
|
100
|
+
checkpoint_patterns: # For status search (default: *.pth, *.pt)
|
|
101
|
+
- "*.pth"
|
|
102
|
+
- "*.safetensors"
|
|
103
|
+
|
|
104
|
+
training_data:
|
|
105
|
+
description: "Training dataset (32GB)"
|
|
106
|
+
local_path: /home/user/data/
|
|
107
|
+
remote_path: /mnt/data/
|
|
108
|
+
pull_only: true # Prevent accidental push
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Config file auto-detection
|
|
112
|
+
|
|
113
|
+
sync-pilot looks for config files in this order:
|
|
114
|
+
1. `sync_config.yaml`
|
|
115
|
+
2. `sync-pilot.yaml`
|
|
116
|
+
3. `.sync-pilot.yaml`
|
|
117
|
+
|
|
118
|
+
## Requirements / 依赖
|
|
119
|
+
|
|
120
|
+
- Python >= 3.10
|
|
121
|
+
- `rsync` and `ssh` available on PATH
|
|
122
|
+
- `tmux` on the remote server (for training/watch features)
|
|
123
|
+
- SSH key-based auth configured (recommended)
|
|
124
|
+
|
|
125
|
+
## License
|
|
126
|
+
|
|
127
|
+
MIT
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# sync-pilot
|
|
2
|
+
|
|
3
|
+
交互式 TUI 工具,通过 rsync + SSH 同步项目到远端服务器。专为 ML/DL 训练工作流设计。
|
|
4
|
+
|
|
5
|
+
Interactive TUI tool for syncing projects to remote servers via rsync + SSH. Built for ML/DL training workflows.
|
|
6
|
+
|
|
7
|
+
## Features / 功能
|
|
8
|
+
|
|
9
|
+
- **Push/Pull** — rsync 同步代码和 checkpoints
|
|
10
|
+
- **Remote Training** — 一键推送代码 + tmux 启动远端训练,自动加 `uv run` 前缀
|
|
11
|
+
- **Monitor** — GPU 状态、tmux session 输出查看、实时 attach、session 管理
|
|
12
|
+
- **Status** — 项目状态总览(远端目录大小、checkpoint 数量)
|
|
13
|
+
- **Data Push** — 一次性推送大型数据集
|
|
14
|
+
- **i18n** — 自动检测系统语言(中/英),支持 `--lang` 和 `SYNC_PILOT_LANG` 覆盖
|
|
15
|
+
|
|
16
|
+
## Install / 安装
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pip install sync-pilot
|
|
20
|
+
# or
|
|
21
|
+
uv add sync-pilot
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Quick Start / 快速开始
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# 1. Initialize config in your project directory
|
|
28
|
+
cd /path/to/your/project
|
|
29
|
+
sync-pilot init
|
|
30
|
+
|
|
31
|
+
# 2. Edit sync_config.yaml with your remote server info
|
|
32
|
+
vim sync_config.yaml
|
|
33
|
+
|
|
34
|
+
# 3. Launch interactive TUI
|
|
35
|
+
sync-pilot
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Usage / 使用
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
sync-pilot # Interactive TUI menu
|
|
42
|
+
sync-pilot init # Generate config files in current directory
|
|
43
|
+
sync-pilot push # Push code to remote
|
|
44
|
+
sync-pilot pull # Pull checkpoints from remote
|
|
45
|
+
sync-pilot train # Push + launch remote training
|
|
46
|
+
sync-pilot push-data # One-time data upload
|
|
47
|
+
sync-pilot watch # Monitor GPU & tmux sessions
|
|
48
|
+
sync-pilot status # Project status overview
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Options
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
-c, --config FILE Config file path (default: auto-detect)
|
|
55
|
+
-p, --project NAME Target project name
|
|
56
|
+
--lang zh|en Force UI language
|
|
57
|
+
-V, --version Show version
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Configuration / 配置
|
|
61
|
+
|
|
62
|
+
`sync_config.yaml`:
|
|
63
|
+
|
|
64
|
+
```yaml
|
|
65
|
+
remote_host: 1.2.3.4
|
|
66
|
+
remote_user: root
|
|
67
|
+
remote_port: 22 # Optional, default 22
|
|
68
|
+
|
|
69
|
+
projects:
|
|
70
|
+
my_project:
|
|
71
|
+
description: "My ML project"
|
|
72
|
+
local_path: /home/user/workspace/project/
|
|
73
|
+
remote_path: /mnt/workspace/project/
|
|
74
|
+
exclude_file: rsync_exclude.txt # Relative to this config file
|
|
75
|
+
use_uv: true # Auto-prefix python commands with uv run
|
|
76
|
+
pull_directories:
|
|
77
|
+
- checkpoints/
|
|
78
|
+
checkpoint_patterns: # For status search (default: *.pth, *.pt)
|
|
79
|
+
- "*.pth"
|
|
80
|
+
- "*.safetensors"
|
|
81
|
+
|
|
82
|
+
training_data:
|
|
83
|
+
description: "Training dataset (32GB)"
|
|
84
|
+
local_path: /home/user/data/
|
|
85
|
+
remote_path: /mnt/data/
|
|
86
|
+
pull_only: true # Prevent accidental push
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Config file auto-detection
|
|
90
|
+
|
|
91
|
+
sync-pilot looks for config files in this order:
|
|
92
|
+
1. `sync_config.yaml`
|
|
93
|
+
2. `sync-pilot.yaml`
|
|
94
|
+
3. `.sync-pilot.yaml`
|
|
95
|
+
|
|
96
|
+
## Requirements / 依赖
|
|
97
|
+
|
|
98
|
+
- Python >= 3.10
|
|
99
|
+
- `rsync` and `ssh` available on PATH
|
|
100
|
+
- `tmux` on the remote server (for training/watch features)
|
|
101
|
+
- SSH key-based auth configured (recommended)
|
|
102
|
+
|
|
103
|
+
## License
|
|
104
|
+
|
|
105
|
+
MIT
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "sync-pilot"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Interactive TUI tool for syncing projects to remote servers via rsync + SSH"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
authors = [{ name = "Liang Yi" }]
|
|
13
|
+
keywords = ["rsync", "ssh", "sync", "tui", "remote", "training"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Environment :: Console",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Topic :: System :: Systems Administration",
|
|
21
|
+
"Topic :: Utilities",
|
|
22
|
+
]
|
|
23
|
+
dependencies = [
|
|
24
|
+
"pyyaml>=6.0",
|
|
25
|
+
"rich>=13.0",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
[project.scripts]
|
|
29
|
+
sync-pilot = "sync_pilot.cli:main"
|
|
30
|
+
|
|
31
|
+
[project.urls]
|
|
32
|
+
Homepage = "https://github.com/cidxb/sync-pilot"
|
|
33
|
+
Repository = "https://github.com/cidxb/sync-pilot"
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"""CLI entry point for sync-pilot."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import sys
|
|
5
|
+
import shutil
|
|
6
|
+
import argparse
|
|
7
|
+
from importlib import resources
|
|
8
|
+
|
|
9
|
+
from rich.console import Console
|
|
10
|
+
|
|
11
|
+
from . import __version__
|
|
12
|
+
from .i18n import t, set_locale
|
|
13
|
+
from .core import (
|
|
14
|
+
find_config,
|
|
15
|
+
load_config,
|
|
16
|
+
interactive_menu,
|
|
17
|
+
action_push,
|
|
18
|
+
action_pull,
|
|
19
|
+
action_train,
|
|
20
|
+
action_push_data,
|
|
21
|
+
action_watch,
|
|
22
|
+
action_status,
|
|
23
|
+
console,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def action_init():
|
|
28
|
+
"""Generate default config files in CWD."""
|
|
29
|
+
template_dir = resources.files("sync_pilot") / "templates"
|
|
30
|
+
files = ["sync_config.yaml", "rsync_exclude.txt"]
|
|
31
|
+
|
|
32
|
+
for fname in files:
|
|
33
|
+
dest = os.path.join(os.getcwd(), fname)
|
|
34
|
+
if os.path.exists(dest):
|
|
35
|
+
console.print(f"[yellow]{t('config_exists', path=fname)}[/yellow]")
|
|
36
|
+
continue
|
|
37
|
+
|
|
38
|
+
src = template_dir / fname
|
|
39
|
+
with resources.as_file(src) as src_path:
|
|
40
|
+
shutil.copy2(str(src_path), dest)
|
|
41
|
+
console.print(f"[green]{t('config_created', path=fname)}[/green]")
|
|
42
|
+
|
|
43
|
+
console.print(f"\n{t('init_done')}")
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def main():
|
|
47
|
+
parser = argparse.ArgumentParser(
|
|
48
|
+
prog="sync-pilot",
|
|
49
|
+
description="Interactive TUI for syncing projects to remote servers via rsync + SSH",
|
|
50
|
+
)
|
|
51
|
+
parser.add_argument(
|
|
52
|
+
"-V", "--version",
|
|
53
|
+
action="version",
|
|
54
|
+
version=f"sync-pilot {__version__}",
|
|
55
|
+
)
|
|
56
|
+
parser.add_argument(
|
|
57
|
+
"action",
|
|
58
|
+
nargs="?",
|
|
59
|
+
default=None,
|
|
60
|
+
choices=["init", "push", "pull", "train", "push-data", "watch", "status"],
|
|
61
|
+
help="Action to execute (omit for interactive menu)",
|
|
62
|
+
)
|
|
63
|
+
parser.add_argument(
|
|
64
|
+
"command",
|
|
65
|
+
nargs="?",
|
|
66
|
+
default=None,
|
|
67
|
+
help="Training command (only for 'train' action)",
|
|
68
|
+
)
|
|
69
|
+
parser.add_argument("--project", "-p", default=None, help="Project name")
|
|
70
|
+
parser.add_argument("--config", "-c", default=None, help="Config file path")
|
|
71
|
+
parser.add_argument("--lang", default=None, choices=["zh", "en"], help="Force UI language")
|
|
72
|
+
|
|
73
|
+
args = parser.parse_args()
|
|
74
|
+
|
|
75
|
+
# Language override
|
|
76
|
+
if args.lang:
|
|
77
|
+
set_locale(args.lang)
|
|
78
|
+
|
|
79
|
+
# init doesn't need config
|
|
80
|
+
if args.action == "init":
|
|
81
|
+
action_init()
|
|
82
|
+
return
|
|
83
|
+
|
|
84
|
+
config_path = find_config(args.config)
|
|
85
|
+
config = load_config(config_path)
|
|
86
|
+
|
|
87
|
+
if args.action is None:
|
|
88
|
+
interactive_menu(config)
|
|
89
|
+
elif args.action == "push":
|
|
90
|
+
action_push(config, args.project)
|
|
91
|
+
elif args.action == "pull":
|
|
92
|
+
action_pull(config, args.project)
|
|
93
|
+
elif args.action == "train":
|
|
94
|
+
action_train(config, command=args.command, project_name=args.project)
|
|
95
|
+
elif args.action == "push-data":
|
|
96
|
+
project = args.project
|
|
97
|
+
if project is None:
|
|
98
|
+
for name, proj in config["projects"].items():
|
|
99
|
+
if proj.get("pull_only") and not proj.get("pull_directories") and not proj.get("pull_directory"):
|
|
100
|
+
project = name
|
|
101
|
+
break
|
|
102
|
+
if project is None:
|
|
103
|
+
console.print(f"[yellow]{t('specify_data_project')}[/yellow]")
|
|
104
|
+
sys.exit(1)
|
|
105
|
+
action_push_data(config, project)
|
|
106
|
+
elif args.action == "watch":
|
|
107
|
+
action_watch(config)
|
|
108
|
+
elif args.action == "status":
|
|
109
|
+
action_status(config)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
if __name__ == "__main__":
|
|
113
|
+
main()
|