A powerful CLI tool for syncing files and directories from GitHub repositories to your local machine using workflow configurations.
- Node.js 16+ installed
- Git installed
- GitHub personal access token with appropriate repository access
# Install globally
npm install -g open-code-cli
# Or use with npx
npx open-code-cli workflow workflow.json
The gh_sync
task allows you to synchronize files and directories from GitHub repositories to your local machine.
Create a JSON workflow file (e.g., sync-config.json
) with the following structure:
{
"workflow": [
{
"task": "gh_sync",
"repos": [
{
"repo": "owner/repo-name",
"sync": true,
"force": false,
"branch": "main",
"files": [
{
"source": "path/in/repo",
"local": "local/path"
}
]
}
]
}
]
}
Run the workflow:
open-code-cli workflow sync-config.json
Property | Type | Required | Description |
---|---|---|---|
repo | string | Yes | GitHub repository in format owner/repo |
sync | boolean | No | Whether to sync this repository (default: true) |
force | boolean | No | Force sync even if files haven't changed |
branch | string | No | Branch to sync from (default: main) |
forkRepo | string | No | (For contribute command) Fork repository to use for creating pull requests |
files | File[] | Yes | Array of file mappings |
Property | Type | Required | Description |
---|---|---|---|
source | string | Yes | Path in the repository to sync from |
local | string | Yes | Local path to sync to |
{
"workflow": [
{
"task": "gh_sync",
"repos": [
{
"repo": "locospec/lens",
"sync": true,
"force": false,
"branch": "main",
"files": [
{
"source": "packages/lens-react/lib",
"local": "resources/shared-js/locospec/lens-react/lib"
}
]
},
{
"repo": "locospec/engine-php",
"sync": true,
"force": false,
"branch": "main",
"forkRepo": "locospec/engine-php",
"files": [
{
"source": "/",
"local": "LCS/engine-php"
}
]
},
{
"repo": "locospec/locospec-laravel",
"sync": true,
"force": false,
"branch": "main",
"forkRepo": "locospec/locospec-laravel",
"files": [
{
"source": "/",
"local": "LCS/locospec-laravel"
}
]
}
]
}
]
}
- The tool checks if the local copy of each file exists and compares it with the remote version
- If the remote file is different, it will be downloaded and saved locally
- If
force: true
, files will be re-downloaded even if they haven't changed - The tool maintains a cache of file hashes to track changes
- The repository is cloned once, and only changed files are copied locally
- Always specify the
branch
to avoid unexpected updates - Use
force: true
sparingly to avoid unnecessary downloads - Organize your file mappings logically for easier maintenance
- Add
.open-code-cli
to your.gitignore
to avoid committing cache files
The AI-powered tasks require an OpenRouter API key. You can configure this using the init-open-router
command:
open-code-cli init-open-router
This will prompt you for your API key and preferred model, storing the configuration in ~/.open-code-cli/openrouter.json
.
The actionOnFile
function determines what action to take on a file during synchronization by comparing file hashes and checking the tracker state:
Function: actionOnFile(
sourcePath,
localPath,
repo,
relativeLocalPath,
trackerConfig,
sourceCommitHash,
force = false
)
1. If force is true:
- Return COPY action (overrides all other logic)
2. If local file doesn't exist:
- Return COPY action
3. Calculate hashes:
- sourceFileHash = hash of source file
- localFileHash = hash of local file
- trackerFileHash = hash from tracker (if exists)
- trackerAction = previous action from tracker (if exists)
- lastCommitHash = last commit hash from tracker
- currentCommitHash = sourceCommitHash or lastCommitHash
4. Special case for previously merged files (trackerAction === 'MERGE'):
- If commit hash hasn't changed: Return NONE
- If commit hash changed: Return MERGE
5. If no tracking data exists (first sync):
- Return COPY action
6. Compare hashes to determine action:
- If localFileHash === trackerFileHash && localFileHash !== sourceFileHash:
- Return COPY (only source changed)
- If localFileHash !== trackerFileHash && trackerFileHash === sourceFileHash:
- Return NONE (only local changed)
- If localFileHash !== trackerFileHash && localFileHash === sourceFileHash:
- Return UPDATE_TRACKER (local changes pushed to source)
- If localFileHash !== trackerFileHash && localFileHash !== sourceFileHash:
- Return MERGE (both source and local changed)
7. Default: Return NONE (no changes detected)
2. Calculate hashes:
- sourceFileHash = hash of source file
- localFileHash = hash of local file
- trackerFileHash = hash from tracker config (or null if not tracked)
- lastCommitHash = commit hash from tracker (or null)
- currentCommitHash = sourceCommitHash or lastCommitHash (or null)
3. Special handling for previously merged files:
- If trackerAction is MERGE:
- If lastCommitHash equals currentCommitHash:
- Return NONE action (no changes needed)
- Otherwise:
- Return MERGE action (commit hash changed)
4. If no tracking data exists (trackerFileHash is null):
- Return COPY action (first time syncing)
5. Compare file hashes:
- If localFileHash equals trackerFileHash AND localFileHash doesn't equal sourceFileHash:
- Return COPY action (only source file changed)
- If localFileHash doesn't equal trackerFileHash AND trackerFileHash equals sourceFileHash:
- Return NONE action (only local file changed)
- If localFileHash doesn't equal trackerFileHash AND localFileHash equals sourceFileHash:
- Return COPY action (local changes pushed to source)
- If localFileHash doesn't equal trackerFileHash AND localFileHash doesn't equal sourceFileHash:
- Return MERGE action (both files changed independently)
6. Default case:
- Return NONE action (no changes detected)
This algorithm ensures files are properly synchronized while preserving local changes when appropriate and merging when necessary.
This project is licensed under the MIT License - see the LICENSE file for details.
Happy Automating!