@zernio/cli
Advanced tools
+21
-15
@@ -14,8 +14,9 @@ #!/usr/bin/env node | ||
| import { join } from "path"; | ||
| var CONFIG_DIR = join(homedir(), ".late"); | ||
| var CONFIG_DIR = join(homedir(), ".zernio"); | ||
| var CONFIG_FILE = join(CONFIG_DIR, "config.json"); | ||
| function readConfigFile() { | ||
| var LEGACY_CONFIG_FILE = join(homedir(), ".late", "config.json"); | ||
| function readJsonConfig(filePath) { | ||
| try { | ||
| if (!existsSync(CONFIG_FILE)) return {}; | ||
| const raw = readFileSync(CONFIG_FILE, "utf-8"); | ||
| if (!existsSync(filePath)) return {}; | ||
| const raw = readFileSync(filePath, "utf-8"); | ||
| return JSON.parse(raw); | ||
@@ -26,4 +27,9 @@ } catch { | ||
| } | ||
| function readConfigFile() { | ||
| const config = readJsonConfig(CONFIG_FILE); | ||
| if (config.apiKey) return config; | ||
| return readJsonConfig(LEGACY_CONFIG_FILE); | ||
| } | ||
| function writeConfig(updates) { | ||
| const existing = readConfigFile(); | ||
| const existing = readJsonConfig(CONFIG_FILE); | ||
| const merged = { ...existing, ...updates }; | ||
@@ -38,5 +44,5 @@ if (!existsSync(CONFIG_DIR)) { | ||
| return { | ||
| apiKey: process.env.LATE_API_KEY || file.apiKey, | ||
| apiKey: process.env.ZERNIO_API_KEY || process.env.LATE_API_KEY || file.apiKey, | ||
| // SDK default is https://zernio.com/api (it adds /v1/ prefix to paths internally) | ||
| baseUrl: process.env.LATE_API_URL || file.baseUrl | ||
| baseUrl: process.env.ZERNIO_API_URL || process.env.LATE_API_URL || file.baseUrl | ||
| }; | ||
@@ -49,3 +55,3 @@ } | ||
| error: true, | ||
| message: 'No API key configured. Run "late auth:set" or set LATE_API_KEY env var.' | ||
| message: 'No API key configured. Run "zernio auth:set" or set ZERNIO_API_KEY env var.' | ||
| })); | ||
@@ -152,3 +158,3 @@ process.exit(1); | ||
| if (pollRes.status === 410) { | ||
| outputError("Authorization session expired. Run `late auth:login` again."); | ||
| outputError("Authorization session expired. Run `zernio auth:login` again."); | ||
| } | ||
@@ -164,3 +170,3 @@ if (pollRes.status === 429) { | ||
| writeConfig({ apiKey: data.apiKey }); | ||
| process.stderr.write(" Authorized! API key saved to ~/.late/config.json\n\n"); | ||
| process.stderr.write(" Authorized! API key saved to ~/.zernio/config.json\n\n"); | ||
| output( | ||
@@ -176,7 +182,7 @@ { success: true, message: "Logged in successfully. API key saved." }, | ||
| } | ||
| outputError("Authorization timed out. Run `late auth:login` again."); | ||
| outputError("Authorization timed out. Run `zernio auth:login` again."); | ||
| } | ||
| ).command( | ||
| "auth:set", | ||
| "Save API key to ~/.late/config.json", | ||
| "Save API key to ~/.zernio/config.json", | ||
| (y) => y.option("key", { | ||
@@ -194,3 +200,3 @@ type: "string", | ||
| writeConfig(updates); | ||
| output({ success: true, message: "API key saved to ~/.late/config.json" }, argv.pretty); | ||
| output({ success: true, message: "API key saved to ~/.zernio/config.json" }, argv.pretty); | ||
| } | ||
@@ -608,3 +614,3 @@ ).command( | ||
| // src/index.ts | ||
| var cli = yargs(hideBin(process.argv)).scriptName("late").usage("Usage: late <command> [options]").option("pretty", { | ||
| var cli = yargs(hideBin(process.argv)).scriptName("zernio").usage("Usage: zernio <command> [options]").option("pretty", { | ||
| type: "boolean", | ||
@@ -614,3 +620,3 @@ describe: "Pretty-print JSON output", | ||
| global: true | ||
| }).strict().demandCommand(1, 'You need to specify a command. Run "late --help" for available commands.').help().alias("h", "help").version().alias("v", "version"); | ||
| }).strict().demandCommand(1, 'You need to specify a command. Run "zernio --help" for available commands.').help().alias("h", "help").version().alias("v", "version"); | ||
| cli = registerAuthCommands(cli); | ||
@@ -617,0 +623,0 @@ cli = registerProfileCommands(cli); |
+1
-1
| { | ||
| "name": "@zernio/cli", | ||
| "version": "0.1.1", | ||
| "version": "0.2.0", | ||
| "description": "CLI for Zernio - Schedule and manage social media posts across 13 platforms", | ||
@@ -5,0 +5,0 @@ "type": "module", |
+6
-4
@@ -37,3 +37,3 @@ # Zernio CLI | ||
| Opens your browser to authorize the CLI. An API key is created automatically and saved to `~/.late/config.json`. Running it again from the same device replaces the existing key. | ||
| Opens your browser to authorize the CLI. An API key is created automatically and saved to `~/.zernio/config.json`. Running it again from the same device replaces the existing key. | ||
@@ -82,9 +82,11 @@ Options: | ||
| Config is stored at `~/.late/config.json`. Environment variables take precedence: | ||
| Config is stored at `~/.zernio/config.json`. Environment variables take precedence: | ||
| | Env Var | Description | | ||
| |---------|-------------| | ||
| | `LATE_API_KEY` | API key (required) | | ||
| | `LATE_API_URL` | Custom API base URL | | ||
| | `ZERNIO_API_KEY` | API key (required) | | ||
| | `ZERNIO_API_URL` | Custom API base URL | | ||
| Legacy env vars `LATE_API_KEY` / `LATE_API_URL` and config at `~/.late/config.json` are still supported as fallbacks. | ||
| ## AI Agent Integration | ||
@@ -91,0 +93,0 @@ |
+55
-55
| --- | ||
| name: late | ||
| name: zernio | ||
| description: Schedule and manage social media posts across 13 platforms from the CLI | ||
| version: 0.1.0 | ||
| version: 0.2.0 | ||
| homepage: https://docs.zernio.com | ||
@@ -9,7 +9,7 @@ tags: [social-media, scheduling, instagram, tiktok, twitter, linkedin, facebook, threads, youtube, bluesky, pinterest, reddit, snapchat, telegram] | ||
| env: | ||
| - LATE_API_KEY (required) - Your Zernio API key from https://zernio.com/settings/api | ||
| - LATE_API_URL (optional) - Defaults to https://zernio.com/api | ||
| - ZERNIO_API_KEY (required) - Your Zernio API key from https://zernio.com/settings/api | ||
| - ZERNIO_API_URL (optional) - Defaults to https://zernio.com/api | ||
| --- | ||
| # Late CLI | ||
| # Zernio CLI | ||
@@ -21,15 +21,15 @@ Schedule and publish social media posts across 13 platforms (Instagram, TikTok, X/Twitter, LinkedIn, Facebook, Threads, YouTube, Bluesky, Pinterest, Reddit, Snapchat, Telegram, Google Business) from any terminal or AI agent. | ||
| ```bash | ||
| npm install -g late | ||
| npm install -g @zernio/cli | ||
| # Log in via browser (recommended) | ||
| late auth:login | ||
| zernio auth:login | ||
| # Or set your API key manually | ||
| late auth:set --key "sk_your-api-key" | ||
| zernio auth:set --key "sk_your-api-key" | ||
| # Verify it works | ||
| late auth:check | ||
| zernio auth:check | ||
| ``` | ||
| Or set the env var directly: `export LATE_API_KEY="sk_your-api-key"` | ||
| Or set the env var directly: `export ZERNIO_API_KEY="sk_your-api-key"` | ||
@@ -42,15 +42,15 @@ ## Core Workflow | ||
| # 1. See your profiles | ||
| late profiles:list | ||
| zernio profiles:list | ||
| # 2. See connected social accounts | ||
| late accounts:list | ||
| zernio accounts:list | ||
| # 3. Schedule a post | ||
| late posts:create --text "Hello world!" --accounts <accountId1>,<accountId2> --scheduledAt "2025-01-15T10:00:00Z" | ||
| zernio posts:create --text "Hello world!" --accounts <accountId1>,<accountId2> --scheduledAt "2025-01-15T10:00:00Z" | ||
| # 4. Check post status | ||
| late posts:list --status scheduled | ||
| zernio posts:list --status scheduled | ||
| # 5. View analytics (requires analytics add-on) | ||
| late analytics:posts --profileId <profileId> | ||
| zernio analytics:posts --profileId <profileId> | ||
| ``` | ||
@@ -70,15 +70,15 @@ | ||
| # Log in via browser (opens browser, creates API key automatically) | ||
| late auth:login | ||
| zernio auth:login | ||
| # Or with a custom device name | ||
| late auth:login --device-name "my-server" | ||
| zernio auth:login --device-name "my-server" | ||
| # Save API key manually | ||
| late auth:set --key "sk_your-api-key" | ||
| zernio auth:set --key "sk_your-api-key" | ||
| # Optionally set custom API URL | ||
| late auth:set --key "sk_..." --url "https://custom.api.url/api/v1" | ||
| zernio auth:set --key "sk_..." --url "https://custom.api.url/api/v1" | ||
| # Verify key works | ||
| late auth:check | ||
| zernio auth:check | ||
| ``` | ||
@@ -90,15 +90,15 @@ | ||
| # List all profiles | ||
| late profiles:list | ||
| zernio profiles:list | ||
| # Create a profile | ||
| late profiles:create --name "My Brand" | ||
| zernio profiles:create --name "My Brand" | ||
| # Get profile details | ||
| late profiles:get <profileId> | ||
| zernio profiles:get <profileId> | ||
| # Update profile | ||
| late profiles:update <profileId> --name "New Name" | ||
| zernio profiles:update <profileId> --name "New Name" | ||
| # Delete profile (must have no connected accounts) | ||
| late profiles:delete <profileId> | ||
| zernio profiles:delete <profileId> | ||
| ``` | ||
@@ -110,12 +110,12 @@ | ||
| # List all connected accounts | ||
| late accounts:list | ||
| zernio accounts:list | ||
| # Filter by profile or platform | ||
| late accounts:list --profileId <id> --platform instagram | ||
| zernio accounts:list --profileId <id> --platform instagram | ||
| # Get single account | ||
| late accounts:get <accountId> | ||
| zernio accounts:get <accountId> | ||
| # Check health of all accounts (rate limits, token expiry) | ||
| late accounts:health | ||
| zernio accounts:health | ||
| ``` | ||
@@ -127,29 +127,29 @@ | ||
| # Publish immediately | ||
| late posts:create --text "Hello!" --accounts <id1>,<id2> | ||
| zernio posts:create --text "Hello!" --accounts <id1>,<id2> | ||
| # Schedule for later | ||
| late posts:create --text "Scheduled post" --accounts <id> --scheduledAt "2025-06-01T14:00:00Z" | ||
| zernio posts:create --text "Scheduled post" --accounts <id> --scheduledAt "2025-06-01T14:00:00Z" | ||
| # Save as draft | ||
| late posts:create --text "Draft idea" --accounts <id> --draft | ||
| zernio posts:create --text "Draft idea" --accounts <id> --draft | ||
| # With media | ||
| late posts:create --text "Check this out" --accounts <id> --media "https://example.com/image.jpg" | ||
| zernio posts:create --text "Check this out" --accounts <id> --media "https://example.com/image.jpg" | ||
| # With title (YouTube, Reddit) | ||
| late posts:create --text "Description" --accounts <id> --title "My Video Title" | ||
| zernio posts:create --text "Description" --accounts <id> --title "My Video Title" | ||
| # List posts with filters | ||
| late posts:list --status published --page 1 --limit 20 | ||
| late posts:list --profileId <id> --from "2025-01-01" --to "2025-01-31" | ||
| late posts:list --search "product launch" | ||
| zernio posts:list --status published --page 1 --limit 20 | ||
| zernio posts:list --profileId <id> --from "2025-01-01" --to "2025-01-31" | ||
| zernio posts:list --search "product launch" | ||
| # Get post details | ||
| late posts:get <postId> | ||
| zernio posts:get <postId> | ||
| # Delete a post | ||
| late posts:delete <postId> | ||
| zernio posts:delete <postId> | ||
| # Retry a failed post | ||
| late posts:retry <postId> | ||
| zernio posts:retry <postId> | ||
| ``` | ||
@@ -161,11 +161,11 @@ | ||
| # Post analytics | ||
| late analytics:posts --profileId <id> | ||
| late analytics:posts --postId <postId> | ||
| late analytics:posts --platform instagram --sortBy engagement | ||
| zernio analytics:posts --profileId <id> | ||
| zernio analytics:posts --postId <postId> | ||
| zernio analytics:posts --platform instagram --sortBy engagement | ||
| # Daily metrics | ||
| late analytics:daily --accountId <id> --from "2025-01-01" --to "2025-01-31" | ||
| zernio analytics:daily --accountId <id> --from "2025-01-01" --to "2025-01-31" | ||
| # Best posting times | ||
| late analytics:best-time --accountId <id> | ||
| zernio analytics:best-time --accountId <id> | ||
| ``` | ||
@@ -177,4 +177,4 @@ | ||
| # Upload a file (returns URL for use in posts:create --media) | ||
| late media:upload ./photo.jpg | ||
| late media:upload ./video.mp4 | ||
| zernio media:upload ./photo.jpg | ||
| zernio media:upload ./video.mp4 | ||
| ``` | ||
@@ -186,5 +186,5 @@ | ||
| ```bash | ||
| late media:upload ./reel.mp4 | ||
| zernio media:upload ./reel.mp4 | ||
| # Use the returned URL: | ||
| late posts:create --text "New reel!" --accounts <instagramAccountId> --media "<returned-url>" | ||
| zernio posts:create --text "New reel!" --accounts <instagramAccountId> --media "<returned-url>" | ||
| ``` | ||
@@ -194,3 +194,3 @@ | ||
| ```bash | ||
| late posts:create \ | ||
| zernio posts:create \ | ||
| --text "Big announcement!" \ | ||
@@ -205,3 +205,3 @@ --accounts <instagramId>,<twitterId>,<linkedinId> \ | ||
| ```bash | ||
| late posts:create --text "Thoughts on AI agents..." --accounts <threadsId>,<twitterId> | ||
| zernio posts:create --text "Thoughts on AI agents..." --accounts <threadsId>,<twitterId> | ||
| ``` | ||
@@ -224,6 +224,6 @@ | ||
| - Always call `late accounts:list` first to get valid account IDs before creating posts | ||
| - Use `late accounts:health` to check if accounts are rate-limited before posting | ||
| - Post IDs from `late posts:create` can be used with `late posts:get` to check publish status | ||
| - For multi-image posts, upload each file with `late media:upload` first, then pass all URLs comma-separated to `--media` | ||
| - Always call `zernio accounts:list` first to get valid account IDs before creating posts | ||
| - Use `zernio accounts:health` to check if accounts are rate-limited before posting | ||
| - Post IDs from `zernio posts:create` can be used with `zernio posts:get` to check publish status | ||
| - For multi-image posts, upload each file with `zernio media:upload` first, then pass all URLs comma-separated to `--media` | ||
| - Schedule posts at least 5 minutes in the future for reliable delivery |
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 4 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
32179
1.77%608
1%101
2.02%7
40%