github-sync-agent 0.1.4__tar.gz → 0.2.1__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.
@@ -1,14 +1,14 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: github-sync-agent
3
- Version: 0.1.4
3
+ Version: 0.2.1
4
4
  Summary: Sync all your local projects to GitHub automatically
5
- License: MIT
5
+ Author-email: GitHub Sync Agent Maintainers <yuvalavni@users.noreply.github.com>
6
+ License-Expression: MIT
6
7
  Project-URL: Homepage, https://github.com/yuvalavni/Agents
7
8
  Project-URL: Repository, https://github.com/yuvalavni/Agents
8
- Project-URL: Bug Tracker, https://github.com/yuvalavni/Agents/issues
9
- Keywords: github,git,sync,backup,automation,cli
9
+ Project-URL: Issues, https://github.com/yuvalavni/Agents/issues
10
+ Keywords: github,git,sync,backup,automation,cli,api
10
11
  Classifier: Programming Language :: Python :: 3
11
- Classifier: License :: OSI Approved :: MIT License
12
12
  Classifier: Operating System :: POSIX :: Linux
13
13
  Classifier: Environment :: Console
14
14
  Classifier: Topic :: Software Development :: Version Control :: Git
@@ -16,6 +16,9 @@ Requires-Python: >=3.10
16
16
  Description-Content-Type: text/markdown
17
17
  Requires-Dist: pyyaml>=6.0
18
18
  Requires-Dist: click>=8.0
19
+ Provides-Extra: api
20
+ Requires-Dist: fastapi>=0.100; extra == "api"
21
+ Requires-Dist: uvicorn>=0.23; extra == "api"
19
22
 
20
23
  # GitHub Sync Agent
21
24
 
@@ -74,6 +77,64 @@ github-sync status
74
77
 
75
78
  ---
76
79
 
80
+ ## HTTP API
81
+
82
+ Install API dependencies:
83
+
84
+ ```bash
85
+ pip install 'github-sync-agent[api]'
86
+ ```
87
+
88
+ Start the server:
89
+
90
+ ```bash
91
+ github-sync serve
92
+ # → http://127.0.0.1:8741
93
+ ```
94
+
95
+ ### Endpoints
96
+
97
+ | Method | Path | Description |
98
+ |--------|------|-------------|
99
+ | `GET` | `/health` | Health check (no auth) |
100
+ | `GET` | `/status` | Sync status for all projects |
101
+ | `POST` | `/sync` | Sync all projects |
102
+ | `POST` | `/sync/{project}` | Sync one project |
103
+
104
+ Optional body for POST: `{"dry_run": false}`
105
+
106
+ ### Examples
107
+
108
+ ```bash
109
+ curl http://127.0.0.1:8741/health
110
+ curl http://127.0.0.1:8741/status
111
+ curl -X POST http://127.0.0.1:8741/sync
112
+ curl -X POST http://127.0.0.1:8741/sync/Agents
113
+ ```
114
+
115
+ ### API authentication (optional)
116
+
117
+ Add to `config.yaml`:
118
+
119
+ ```yaml
120
+ api_key: "your-secret-key"
121
+ ```
122
+
123
+ Then pass the key on every request (except `/health`):
124
+
125
+ ```bash
126
+ curl -H "Authorization: Bearer your-secret-key" http://127.0.0.1:8741/status
127
+ ```
128
+
129
+ ### Run as a systemd service
130
+
131
+ ```bash
132
+ cp systemd/github-sync-api.service ~/.config/systemd/user/
133
+ systemctl --user enable --now github-sync-api.service
134
+ ```
135
+
136
+ ---
137
+
77
138
  ## Configuration (`~/.config/github-sync/config.yaml`)
78
139
 
79
140
  Generated by `github-sync init`. You can edit it at any time.
@@ -88,6 +149,9 @@ Generated by `github-sync init`. You can edit it at any time.
88
149
  | `exclude` | `[]` | Directory names to skip |
89
150
  | `log_file` | `~/.local/share/github-sync/github-sync.log` | Log file path |
90
151
  | `log_level` | `INFO` | `DEBUG` / `INFO` / `WARNING` / `ERROR` |
152
+ | `api_host` | `127.0.0.1` | API bind address |
153
+ | `api_port` | `8741` | API port |
154
+ | `api_key` | _(empty)_ | Optional Bearer token for API auth |
91
155
 
92
156
  ### Excluding a project
93
157
 
@@ -1,22 +1,3 @@
1
- Metadata-Version: 2.4
2
- Name: github-sync-agent
3
- Version: 0.1.4
4
- Summary: Sync all your local projects to GitHub automatically
5
- License: MIT
6
- Project-URL: Homepage, https://github.com/yuvalavni/Agents
7
- Project-URL: Repository, https://github.com/yuvalavni/Agents
8
- Project-URL: Bug Tracker, https://github.com/yuvalavni/Agents/issues
9
- Keywords: github,git,sync,backup,automation,cli
10
- Classifier: Programming Language :: Python :: 3
11
- Classifier: License :: OSI Approved :: MIT License
12
- Classifier: Operating System :: POSIX :: Linux
13
- Classifier: Environment :: Console
14
- Classifier: Topic :: Software Development :: Version Control :: Git
15
- Requires-Python: >=3.10
16
- Description-Content-Type: text/markdown
17
- Requires-Dist: pyyaml>=6.0
18
- Requires-Dist: click>=8.0
19
-
20
1
  # GitHub Sync Agent
21
2
 
22
3
  Automatically syncs every local project directory to its own GitHub repository.
@@ -74,6 +55,64 @@ github-sync status
74
55
 
75
56
  ---
76
57
 
58
+ ## HTTP API
59
+
60
+ Install API dependencies:
61
+
62
+ ```bash
63
+ pip install 'github-sync-agent[api]'
64
+ ```
65
+
66
+ Start the server:
67
+
68
+ ```bash
69
+ github-sync serve
70
+ # → http://127.0.0.1:8741
71
+ ```
72
+
73
+ ### Endpoints
74
+
75
+ | Method | Path | Description |
76
+ |--------|------|-------------|
77
+ | `GET` | `/health` | Health check (no auth) |
78
+ | `GET` | `/status` | Sync status for all projects |
79
+ | `POST` | `/sync` | Sync all projects |
80
+ | `POST` | `/sync/{project}` | Sync one project |
81
+
82
+ Optional body for POST: `{"dry_run": false}`
83
+
84
+ ### Examples
85
+
86
+ ```bash
87
+ curl http://127.0.0.1:8741/health
88
+ curl http://127.0.0.1:8741/status
89
+ curl -X POST http://127.0.0.1:8741/sync
90
+ curl -X POST http://127.0.0.1:8741/sync/Agents
91
+ ```
92
+
93
+ ### API authentication (optional)
94
+
95
+ Add to `config.yaml`:
96
+
97
+ ```yaml
98
+ api_key: "your-secret-key"
99
+ ```
100
+
101
+ Then pass the key on every request (except `/health`):
102
+
103
+ ```bash
104
+ curl -H "Authorization: Bearer your-secret-key" http://127.0.0.1:8741/status
105
+ ```
106
+
107
+ ### Run as a systemd service
108
+
109
+ ```bash
110
+ cp systemd/github-sync-api.service ~/.config/systemd/user/
111
+ systemctl --user enable --now github-sync-api.service
112
+ ```
113
+
114
+ ---
115
+
77
116
  ## Configuration (`~/.config/github-sync/config.yaml`)
78
117
 
79
118
  Generated by `github-sync init`. You can edit it at any time.
@@ -88,6 +127,9 @@ Generated by `github-sync init`. You can edit it at any time.
88
127
  | `exclude` | `[]` | Directory names to skip |
89
128
  | `log_file` | `~/.local/share/github-sync/github-sync.log` | Log file path |
90
129
  | `log_level` | `INFO` | `DEBUG` / `INFO` / `WARNING` / `ERROR` |
130
+ | `api_host` | `127.0.0.1` | API bind address |
131
+ | `api_port` | `8741` | API port |
132
+ | `api_key` | _(empty)_ | Optional Bearer token for API auth |
91
133
 
92
134
  ### Excluding a project
93
135
 
@@ -0,0 +1 @@
1
+ __version__ = "0.2.1"
@@ -0,0 +1,111 @@
1
+ """HTTP API for the GitHub Sync Agent."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ import logging
7
+
8
+ from fastapi import Depends, FastAPI, HTTPException, Security
9
+ from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
10
+ from pydantic import BaseModel, Field
11
+
12
+ from . import __version__
13
+ from . import agent
14
+
15
+ LOG = logging.getLogger(__name__)
16
+ _security = HTTPBearer(auto_error=False)
17
+
18
+
19
+ class SyncRequest(BaseModel):
20
+ dry_run: bool = False
21
+
22
+
23
+ class SyncResult(BaseModel):
24
+ project: str
25
+ success: bool
26
+
27
+
28
+ class SyncResponse(BaseModel):
29
+ success: bool
30
+ synced: int
31
+ failed: int
32
+ results: list[SyncResult]
33
+
34
+
35
+ class StatusRow(BaseModel):
36
+ project: str
37
+ root: str
38
+ git: bool
39
+ remote: bool
40
+ changes: bool
41
+ on_github: bool
42
+
43
+
44
+ class StatusResponse(BaseModel):
45
+ github_user: str
46
+ projects_root: list[str]
47
+ projects: list[StatusRow]
48
+
49
+
50
+ def create_app(cfg: dict) -> FastAPI:
51
+ api_key: str = cfg.get("api_key") or ""
52
+
53
+ app = FastAPI(
54
+ title="GitHub Sync Agent API",
55
+ description="Trigger and inspect GitHub sync operations over HTTP.",
56
+ version=__version__,
57
+ )
58
+
59
+ async def require_auth(
60
+ credentials: HTTPAuthorizationCredentials | None = Security(_security),
61
+ ) -> None:
62
+ if not api_key:
63
+ return
64
+ if credentials is None or credentials.credentials != api_key:
65
+ raise HTTPException(status_code=401, detail="Invalid or missing API key")
66
+
67
+ @app.get("/health")
68
+ async def health() -> dict[str, str]:
69
+ return {"status": "ok", "version": __version__}
70
+
71
+ @app.get("/status", response_model=StatusResponse, dependencies=[Depends(require_auth)])
72
+ async def status() -> StatusResponse:
73
+ rows = await asyncio.to_thread(agent.get_status, cfg)
74
+ return StatusResponse(
75
+ github_user=cfg["github_user"],
76
+ projects_root=cfg["projects_root"],
77
+ projects=[StatusRow(**row) for row in rows],
78
+ )
79
+
80
+ @app.post("/sync", response_model=SyncResponse, dependencies=[Depends(require_auth)])
81
+ async def sync_all(body: SyncRequest = SyncRequest()) -> SyncResponse:
82
+ return await _run_sync(cfg, project=None, dry_run=body.dry_run)
83
+
84
+ @app.post("/sync/{project}", response_model=SyncResponse, dependencies=[Depends(require_auth)])
85
+ async def sync_one(project: str, body: SyncRequest = SyncRequest()) -> SyncResponse:
86
+ return await _run_sync(cfg, project=project, dry_run=body.dry_run)
87
+
88
+ return app
89
+
90
+
91
+ async def _run_sync(cfg: dict, project: str | None, dry_run: bool) -> SyncResponse:
92
+ try:
93
+ projects = await asyncio.to_thread(agent.discover_projects, cfg, project)
94
+ except ValueError as exc:
95
+ raise HTTPException(status_code=404, detail=str(exc)) from exc
96
+
97
+ results: list[SyncResult] = []
98
+ for path in projects:
99
+ ok = await asyncio.to_thread(agent.sync_project, path, cfg, dry_run)
100
+ results.append(SyncResult(project=path.name, success=ok))
101
+ level = logging.INFO if ok else logging.ERROR
102
+ LOG.log(level, "%s %s", path.name, "synced" if ok else "FAILED")
103
+
104
+ synced = sum(1 for r in results if r.success)
105
+ failed = len(results) - synced
106
+ return SyncResponse(
107
+ success=failed == 0,
108
+ synced=synced,
109
+ failed=failed,
110
+ results=results,
111
+ )
@@ -253,9 +253,44 @@ def init() -> None:
253
253
  click.echo(f" github-sync status # see all your projects")
254
254
  click.echo(f" github-sync sync --dry-run # preview what will be synced")
255
255
  click.echo(f" github-sync sync # sync everything to GitHub")
256
+ click.echo(f" github-sync serve # start HTTP API (requires [api] extra)")
256
257
  click.echo()
257
258
 
258
259
 
260
+ # ---------------------------------------------------------------------------
261
+ # serve
262
+ # ---------------------------------------------------------------------------
263
+
264
+ @cli.command()
265
+ @click.option("--host", default=None, help="Bind address (default: api_host from config)")
266
+ @click.option("--port", default=None, type=int, help="Port (default: api_port from config)")
267
+ @click.pass_context
268
+ def serve(ctx: click.Context, host: str | None, port: int | None) -> None:
269
+ """Start the HTTP API server."""
270
+ try:
271
+ import uvicorn
272
+ except ImportError:
273
+ click.echo("Error: API dependencies not installed.", err=True)
274
+ click.echo("Run: pip install 'github-sync-agent[api]'", err=True)
275
+ sys.exit(1)
276
+
277
+ cfg = ctx.obj["cfg"]
278
+ _setup_logging(cfg)
279
+
280
+ from .api import create_app
281
+
282
+ bind_host = host or cfg.get("api_host", "127.0.0.1")
283
+ bind_port = port or int(cfg.get("api_port", 8741))
284
+ app = create_app(cfg)
285
+
286
+ auth_note = "API key required" if cfg.get("api_key") else "no auth (localhost only recommended)"
287
+ click.echo(f"Starting GitHub Sync API on http://{bind_host}:{bind_port} ({auth_note})")
288
+ click.echo("Endpoints: GET /health GET /status POST /sync POST /sync/{project}")
289
+ click.echo()
290
+
291
+ uvicorn.run(app, host=bind_host, port=bind_port, log_level=cfg.get("log_level", "info").lower())
292
+
293
+
259
294
  # ---------------------------------------------------------------------------
260
295
  # Entry point
261
296
  # ---------------------------------------------------------------------------
@@ -26,6 +26,9 @@ def _apply_defaults(cfg: dict) -> None:
26
26
  cfg.setdefault("exclude", [])
27
27
  cfg.setdefault("log_file", str(Path.home() / ".local" / "share" / "github-sync" / "github-sync.log"))
28
28
  cfg.setdefault("log_level", "INFO")
29
+ cfg.setdefault("api_host", "127.0.0.1")
30
+ cfg.setdefault("api_port", 8741)
31
+ cfg.setdefault("api_key", "")
29
32
 
30
33
  if not cfg.get("github_user"):
31
34
  raise ValueError("Missing required config key: 'github_user'")
@@ -276,6 +276,11 @@ exclude: []
276
276
  # Logging
277
277
  log_file: {log_file}
278
278
  log_level: INFO
279
+
280
+ # HTTP API (github-sync serve)
281
+ api_host: "127.0.0.1"
282
+ api_port: 8741
283
+ # api_key: "change-me" # uncomment to require: Authorization: Bearer <key>
279
284
  """
280
285
 
281
286
 
@@ -0,0 +1,175 @@
1
+ Metadata-Version: 2.4
2
+ Name: github-sync-agent
3
+ Version: 0.2.1
4
+ Summary: Sync all your local projects to GitHub automatically
5
+ Author-email: GitHub Sync Agent Maintainers <yuvalavni@users.noreply.github.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/yuvalavni/Agents
8
+ Project-URL: Repository, https://github.com/yuvalavni/Agents
9
+ Project-URL: Issues, https://github.com/yuvalavni/Agents/issues
10
+ Keywords: github,git,sync,backup,automation,cli,api
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Operating System :: POSIX :: Linux
13
+ Classifier: Environment :: Console
14
+ Classifier: Topic :: Software Development :: Version Control :: Git
15
+ Requires-Python: >=3.10
16
+ Description-Content-Type: text/markdown
17
+ Requires-Dist: pyyaml>=6.0
18
+ Requires-Dist: click>=8.0
19
+ Provides-Extra: api
20
+ Requires-Dist: fastapi>=0.100; extra == "api"
21
+ Requires-Dist: uvicorn>=0.23; extra == "api"
22
+
23
+ # GitHub Sync Agent
24
+
25
+ Automatically syncs every local project directory to its own GitHub repository.
26
+
27
+ For each project it will:
28
+ 1. `git init` if not already a repo
29
+ 2. Create the GitHub repo if it doesn't exist yet
30
+ 3. Ensure the remote uses SSH
31
+ 4. Stage + commit any uncommitted changes
32
+ 5. Push to `origin`
33
+
34
+ Runs daily via a systemd user timer, and on-demand via CLI.
35
+
36
+ ---
37
+
38
+ ## Installation
39
+
40
+ ```bash
41
+ pip install github-sync-agent
42
+ ```
43
+
44
+ ## First-time setup
45
+
46
+ ```bash
47
+ github-sync init
48
+ ```
49
+
50
+ The wizard will:
51
+ - Check `git` and `gh` are installed
52
+ - Authenticate with GitHub (`gh auth login`)
53
+ - Ask which folder to scan for projects
54
+ - Set up your SSH key automatically
55
+ - **Verify SSH works** (auto-fixes port 443 and ssh-agent if needed)
56
+ - Write a config file to `~/.config/github-sync/config.yaml`
57
+
58
+ Setup will **not** complete until `ssh -T git@github.com` succeeds.
59
+
60
+ ---
61
+
62
+ ## Usage
63
+
64
+ ```bash
65
+ # Sync all projects
66
+ github-sync sync
67
+
68
+ # Sync a single project
69
+ github-sync sync --project my-project
70
+
71
+ # Preview without making changes
72
+ github-sync sync --dry-run
73
+
74
+ # Show status of all projects
75
+ github-sync status
76
+ ```
77
+
78
+ ---
79
+
80
+ ## HTTP API
81
+
82
+ Install API dependencies:
83
+
84
+ ```bash
85
+ pip install 'github-sync-agent[api]'
86
+ ```
87
+
88
+ Start the server:
89
+
90
+ ```bash
91
+ github-sync serve
92
+ # → http://127.0.0.1:8741
93
+ ```
94
+
95
+ ### Endpoints
96
+
97
+ | Method | Path | Description |
98
+ |--------|------|-------------|
99
+ | `GET` | `/health` | Health check (no auth) |
100
+ | `GET` | `/status` | Sync status for all projects |
101
+ | `POST` | `/sync` | Sync all projects |
102
+ | `POST` | `/sync/{project}` | Sync one project |
103
+
104
+ Optional body for POST: `{"dry_run": false}`
105
+
106
+ ### Examples
107
+
108
+ ```bash
109
+ curl http://127.0.0.1:8741/health
110
+ curl http://127.0.0.1:8741/status
111
+ curl -X POST http://127.0.0.1:8741/sync
112
+ curl -X POST http://127.0.0.1:8741/sync/Agents
113
+ ```
114
+
115
+ ### API authentication (optional)
116
+
117
+ Add to `config.yaml`:
118
+
119
+ ```yaml
120
+ api_key: "your-secret-key"
121
+ ```
122
+
123
+ Then pass the key on every request (except `/health`):
124
+
125
+ ```bash
126
+ curl -H "Authorization: Bearer your-secret-key" http://127.0.0.1:8741/status
127
+ ```
128
+
129
+ ### Run as a systemd service
130
+
131
+ ```bash
132
+ cp systemd/github-sync-api.service ~/.config/systemd/user/
133
+ systemctl --user enable --now github-sync-api.service
134
+ ```
135
+
136
+ ---
137
+
138
+ ## Configuration (`~/.config/github-sync/config.yaml`)
139
+
140
+ Generated by `github-sync init`. You can edit it at any time.
141
+
142
+ | Key | Default | Description |
143
+ |-----|---------|-------------|
144
+ | `github_user` | _(detected from gh auth)_ | Your GitHub username |
145
+ | `projects_root` | `~/projects` | Scans all subdirectories here |
146
+ | `schedule_time` | `02:00` | Daily run time |
147
+ | `default_visibility` | `private` | `private` or `public` for new repos |
148
+ | `auto_commit_message` | `chore: auto-sync` | Commit message for auto-commits |
149
+ | `exclude` | `[]` | Directory names to skip |
150
+ | `log_file` | `~/.local/share/github-sync/github-sync.log` | Log file path |
151
+ | `log_level` | `INFO` | `DEBUG` / `INFO` / `WARNING` / `ERROR` |
152
+ | `api_host` | `127.0.0.1` | API bind address |
153
+ | `api_port` | `8741` | API port |
154
+ | `api_key` | _(empty)_ | Optional Bearer token for API auth |
155
+
156
+ ### Excluding a project
157
+
158
+ ```yaml
159
+ exclude:
160
+ - SomeProjectToSkip
161
+ ```
162
+
163
+ ---
164
+
165
+ ## Requirements
166
+
167
+ - Python 3.10+
168
+ - `git` installed
169
+ - `gh` (GitHub CLI) installed — [installation guide](https://cli.github.com)
170
+
171
+ ---
172
+
173
+ ## License
174
+
175
+ MIT
@@ -2,6 +2,7 @@ README.md
2
2
  pyproject.toml
3
3
  github_sync/__init__.py
4
4
  github_sync/agent.py
5
+ github_sync/api.py
5
6
  github_sync/cli.py
6
7
  github_sync/config.py
7
8
  github_sync/setup.py
@@ -0,0 +1,6 @@
1
+ pyyaml>=6.0
2
+ click>=8.0
3
+
4
+ [api]
5
+ fastapi>=0.100
6
+ uvicorn>=0.23
@@ -4,16 +4,17 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "github-sync-agent"
7
- version = "0.1.4"
7
+ version = "0.2.1"
8
8
  description = "Sync all your local projects to GitHub automatically"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
11
- license = { text = "MIT" }
12
- authors = []
13
- keywords = ["github", "git", "sync", "backup", "automation", "cli"]
11
+ license = "MIT"
12
+ authors = [
13
+ { name = "GitHub Sync Agent Maintainers", email = "yuvalavni@users.noreply.github.com" },
14
+ ]
15
+ keywords = ["github", "git", "sync", "backup", "automation", "cli", "api"]
14
16
  classifiers = [
15
17
  "Programming Language :: Python :: 3",
16
- "License :: OSI Approved :: MIT License",
17
18
  "Operating System :: POSIX :: Linux",
18
19
  "Environment :: Console",
19
20
  "Topic :: Software Development :: Version Control :: Git",
@@ -23,10 +24,16 @@ dependencies = [
23
24
  "click>=8.0",
24
25
  ]
25
26
 
27
+ [project.optional-dependencies]
28
+ api = [
29
+ "fastapi>=0.100",
30
+ "uvicorn>=0.23",
31
+ ]
32
+
26
33
  [project.urls]
27
34
  Homepage = "https://github.com/yuvalavni/Agents"
28
35
  Repository = "https://github.com/yuvalavni/Agents"
29
- "Bug Tracker" = "https://github.com/yuvalavni/Agents/issues"
36
+ Issues = "https://github.com/yuvalavni/Agents/issues"
30
37
 
31
38
  [project.scripts]
32
39
  github-sync = "github_sync.cli:main"
@@ -1,92 +0,0 @@
1
- # GitHub Sync Agent
2
-
3
- Automatically syncs every local project directory to its own GitHub repository.
4
-
5
- For each project it will:
6
- 1. `git init` if not already a repo
7
- 2. Create the GitHub repo if it doesn't exist yet
8
- 3. Ensure the remote uses SSH
9
- 4. Stage + commit any uncommitted changes
10
- 5. Push to `origin`
11
-
12
- Runs daily via a systemd user timer, and on-demand via CLI.
13
-
14
- ---
15
-
16
- ## Installation
17
-
18
- ```bash
19
- pip install github-sync-agent
20
- ```
21
-
22
- ## First-time setup
23
-
24
- ```bash
25
- github-sync init
26
- ```
27
-
28
- The wizard will:
29
- - Check `git` and `gh` are installed
30
- - Authenticate with GitHub (`gh auth login`)
31
- - Ask which folder to scan for projects
32
- - Set up your SSH key automatically
33
- - **Verify SSH works** (auto-fixes port 443 and ssh-agent if needed)
34
- - Write a config file to `~/.config/github-sync/config.yaml`
35
-
36
- Setup will **not** complete until `ssh -T git@github.com` succeeds.
37
-
38
- ---
39
-
40
- ## Usage
41
-
42
- ```bash
43
- # Sync all projects
44
- github-sync sync
45
-
46
- # Sync a single project
47
- github-sync sync --project my-project
48
-
49
- # Preview without making changes
50
- github-sync sync --dry-run
51
-
52
- # Show status of all projects
53
- github-sync status
54
- ```
55
-
56
- ---
57
-
58
- ## Configuration (`~/.config/github-sync/config.yaml`)
59
-
60
- Generated by `github-sync init`. You can edit it at any time.
61
-
62
- | Key | Default | Description |
63
- |-----|---------|-------------|
64
- | `github_user` | _(detected from gh auth)_ | Your GitHub username |
65
- | `projects_root` | `~/projects` | Scans all subdirectories here |
66
- | `schedule_time` | `02:00` | Daily run time |
67
- | `default_visibility` | `private` | `private` or `public` for new repos |
68
- | `auto_commit_message` | `chore: auto-sync` | Commit message for auto-commits |
69
- | `exclude` | `[]` | Directory names to skip |
70
- | `log_file` | `~/.local/share/github-sync/github-sync.log` | Log file path |
71
- | `log_level` | `INFO` | `DEBUG` / `INFO` / `WARNING` / `ERROR` |
72
-
73
- ### Excluding a project
74
-
75
- ```yaml
76
- exclude:
77
- - SomeProjectToSkip
78
- ```
79
-
80
- ---
81
-
82
- ## Requirements
83
-
84
- - Python 3.10+
85
- - `git` installed
86
- - `gh` (GitHub CLI) installed — [installation guide](https://cli.github.com)
87
-
88
- ---
89
-
90
- ## License
91
-
92
- MIT
@@ -1 +0,0 @@
1
- __version__ = "0.1.4"
@@ -1,2 +0,0 @@
1
- pyyaml>=6.0
2
- click>=8.0