🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

tracklify

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

tracklify - npm Package Compare versions

Comparing version
1.0.6
to
1.0.7
+137
README.md
# Tracklify CLI — Local Debug Guide
Run and test the Tracklify CLI locally (without compiling or publishing to npm). This guide also explains how the CLI stores your personal token separately for local vs production use.
## Prerequisites
- Node.js 16+ installed
- Tracklify backend reachable:
- Production: https://ws1.tracklify.com (default)
- Local dev: http://tracklify.localhost:3102 (requires your local stack running)
- A CLI secret token from Tracklify:
- Production UI: https://web.tracklify.com/get-cli/
- Local UI: http://web.tracklify.localhost:8080/get-cli/
## Project layout
This folder (`npm-cli`) contains the CLI entry `tracklify.js`. The `package.json` already maps the binary name `tracklify` to this file.
```
npm-cli/
├─ tracklify.js # CLI entry point
└─ package.json # exposes `tracklify` bin
```
## How secrets are stored
The CLI keeps your secret in your home directory under `~/.tracklify/`:
- Production (default): `~/.tracklify/key`
- Local dev (`--local`): `~/.tracklify/key_local`
This separation lets you use different tokens for production and local stacks without overwriting each other.
## Run locally without publishing
You have two easy options.
### Option A — Run directly with Node
From the repo root:
```bash
# Show help
node npm-cli/tracklify.js --help
# Log in (prod)
node npm-cli/tracklify.js login <SECRET>
# Log in (local) — stores token in ~/.tracklify/key_local and uses local API
node npm-cli/tracklify.js login <SECRET> --local
# Print current-task branch name (prod)
node npm-cli/tracklify.js branch
# Print current-task branch name (local)
node npm-cli/tracklify.js branch --local
# Print current-task commit suffix (prod)
node npm-cli/tracklify.js task
# Print current-task commit suffix (local)
node npm-cli/tracklify.js task --local
```
### Option B — Use npm link (optional)
If you prefer to use the `tracklify` command directly without `node` prefix:
```bash
cd npm-cli
npm link
# Then anywhere on your machine you can run:
tracklify --help
tracklify login <SECRET>
tracklify login <SECRET> --local
tracklify branch
tracklify branch --local
tracklify task
tracklify task --local
```
To remove the link later:
```bash
cd npm-cli
npm unlink -g
```
## Commands and behavior
- `login <secret> [--local]`
- Saves your token to `~/.tracklify/key` (prod) or `~/.tracklify/key_local` (local).
- If `--local` is provided, subsequent commands with `--local` talk to `http://tracklify.localhost:3102`.
- `branch [--local]`
- Prints the suggested Git branch for your currently tracked task.
- `task [--local]`
- Prints the `<project>/<taskHid>/<taskSlug>` suffix for commit messages.
## Examples
```bash
# Create a new branch for the current task (prod)
git checkout -b $(node npm-cli/tracklify.js branch)
# Same, but against your local Tracklify stack
git checkout -b $(node npm-cli/tracklify.js branch --local)
# Add task suffix to commit message (prod)
git commit -m "my text $(node npm-cli/tracklify.js task)"
# Local stack variant
git commit -m "my text $(node npm-cli/tracklify.js task --local)"
```
## Where do I get the secret?
- Production: open the Tracklify web app → user menu → "Get CLI" → copy your token.
- Local dev: open http://web.tracklify.localhost:8080/get-cli/ and copy the local token.
Regenerating the token in the web UI will require you to run the CLI `login` again.
## Troubleshooting
- Not logged in / bad token
- The CLI prints a helpful message and exits with code `2`.
- Run `login` again with the correct token (remember to include `--local` if you’re testing locally).
- No active task
- The CLI exits with code `3` and tells you you’re not tracking any task. Start tracking a task in Tracklify and retry.
- Other errors
- The CLI exits with code `1` and prints the error message.
## Notes
- `--local` switches both the API base URL and the secret file (`key_local`).
- For backward compatibility, if `--local` is used but `key_local` isn’t present, the CLI will try falling back to `key` when reading the token.
- Secrets are stored with `0600` permissions under a `0700` directory for safety.
+1
-1
{
"name": "tracklify",
"version": "1.0.6",
"version": "1.0.7",
"description": "Tracklify CLI integration tool (get active task)",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -1,1 +0,1 @@

NPM_TOKEN=`cat ~/.npm_tracklify` npm version patch && npm publish --access public.
npm version patch && npm publish --access public.
#!/usr/bin/env node
// Tracklify CLI
// Commands:
// - login <secret> [--local]: stores secret into ~/.tracklify/key (prod) or ~/.tracklify/key_local (local)
// - branch [--local]: prints branch name for current task
// - task [--local]: prints project/task suffix for commit message
const fs = require('fs');
const os = require('os');
const path = require('path');
const http = require('http');
const PC_INTEGRATIONS_PORT = 59600;
const cmd = process.argv[2];
const https = require('https');
function doComm(url, callback) {
http.get({
hostname: '127.0.0.1',
port: PC_INTEGRATIONS_PORT,
path: url,
agent: false // Create a new agent just for this one request
}, (resp) => {
let data = '';
// A chunk of data has been recieved.
resp.on('data', (chunk) => {
data += chunk;
});
// The whole response has been received. Print out the result.
resp.on('end', () => {
console.log(data);
process.exit(0);
});
}).on("error", (err) => {
// err.message
console.error("Error: can't get active task, is tracking started? ");
process.exit(-1);
});
const REMOTE_BASE = 'https://ws1.tracklify.com';
const LOCAL_BASE = 'http://tracklify.localhost:3102';
const PROD_GET_CLI_URL = 'https://web.tracklify.com/get-cli/';
const LOCAL_GET_CLI_URL = 'http://web.tracklify.localhost:8080/get-cli/';
const KEY_DIR = path.join(os.homedir(), '.tracklify');
const KEY_FILE = path.join(KEY_DIR, 'key');
const KEY_LOCAL_FILE = path.join(KEY_DIR, 'key_local');
function printUsage() {
console.log('Usage: tracklify <command> [options]');
console.log('Commands:');
console.log(' login <secret> [--local] Store your personal CLI secret');
console.log(' branch [--local] Print branch name for current task');
console.log(' task [--local] Print commit suffix for current task');
console.log('');
console.log('Secrets are stored in:');
console.log(' Prod (default): ~/.tracklify/key');
console.log(' Local (--local): ~/.tracklify/key_local');
}
const callers = {
'task': {
call: function () {
doComm('/taskUrl');
},
description: 'Get current tracked task URL 🔗',
},
'taskname': {
call: function () {
doComm('/taskName');
},
description: 'Get current tracked task name ✒',
},
function parseArgs(argv) {
const args = argv.slice(2);
const flags = new Set(args.filter(a => a.startsWith('--')));
const positional = args.filter(a => !a.startsWith('--'));
return { args: positional, flags };
}
if (!Object.keys(callers).includes(cmd)) {
let e = 'Wrong argument 🤷‍♂️ Supported commands:\n';
Object.keys(callers).forEach((el) => {
e += `${el.padStart(10, ' ')} - ${callers[el].description}\n`;
})
console.error(e);
process.exit(-1);
function readSecret(useLocal) {
try {
const file = useLocal ? KEY_LOCAL_FILE : KEY_FILE;
const data = fs.readFileSync(file, 'utf8').trim();
return data;
} catch (e) {
// Backward compatibility: if local requested but key_local doesn't exist, try prod key
if (useLocal) {
try {
const fallback = fs.readFileSync(KEY_FILE, 'utf8').trim();
return fallback;
} catch (_) {}
}
return null;
}
}
callers[cmd].call();
function writeSecret(secret, useLocal) {
if (!fs.existsSync(KEY_DIR)) fs.mkdirSync(KEY_DIR, { recursive: true, mode: 0o700 });
const file = useLocal ? KEY_LOCAL_FILE : KEY_FILE;
fs.writeFileSync(file, secret + '\n', { mode: 0o600 });
}
function postJSON(base, pathName, payload) {
const url = new URL(pathName, base);
const isHttps = url.protocol === 'https:';
const data = JSON.stringify(payload || {});
const options = {
method: 'POST',
hostname: url.hostname,
port: url.port || (isHttps ? 443 : 80),
path: url.pathname,
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(data),
},
};
const client = isHttps ? https : http;
return new Promise((resolve, reject) => {
const req = client.request(options, (res) => {
let body = '';
res.setEncoding('utf8');
res.on('data', chunk => body += chunk);
res.on('end', () => {
try {
const json = JSON.parse(body || '{}');
if (res.statusCode >= 200 && res.statusCode < 300) {
resolve(json);
} else {
const err = new Error(json.error || `HTTP ${res.statusCode}`);
err.statusCode = res.statusCode;
reject(err);
}
} catch (e) {
const err = new Error('Invalid response');
err.cause = e;
reject(err);
}
});
});
req.on('error', reject);
req.write(data);
req.end();
});
}
async function cmdLogin(secret, base, useLocal) {
if (!secret || secret.length < 8) {
console.error('Error: secret is required and should look like a token');
process.exit(2);
}
try {
writeSecret(secret, useLocal);
console.log(`Tracklify CLI: secret saved to ${useLocal ? '~/.tracklify/key_local' : '~/.tracklify/key'}`);
// Optional sanity check: call /task but ignore errors silently
try { await postJSON(base, '/api/cli/task', { secret }); } catch (_) {}
} catch (e) {
console.error('Failed to save secret:', e.message);
process.exit(1);
}
}
async function cmdBranch(base, useLocal) {
const secret = readSecret(useLocal);
if (!secret) {
const url = useLocal ? LOCAL_GET_CLI_URL : PROD_GET_CLI_URL;
console.error(`\nSeams like you are not logged in\n\nPlease go to ${url}, and re-run login command`);
process.exit(2);
}
try {
const resp = await postJSON(base, '/api/cli/branch', { secret });
if (!resp.branch) throw new Error('No branch in response');
console.log(resp.branch);
} catch (e) {
if (e && e.statusCode === 401) {
const url = useLocal ? LOCAL_GET_CLI_URL : PROD_GET_CLI_URL;
console.error(`\nSeams like you are not logged in\n\nPlease go to ${url}, and re-run login command`);
process.exit(2);
}
if (e && e.statusCode === 404) {
console.error('You are not tracking any task right now. Start tracking a task in Tracklify and try again.');
process.exit(3);
}
console.error('Error:', e.message);
process.exit(1);
}
}
async function cmdTask(base, useLocal) {
const secret = readSecret(useLocal);
if (!secret) {
const url = useLocal ? LOCAL_GET_CLI_URL : PROD_GET_CLI_URL;
console.error(`\nSeams like you are not logged in\n\nPlease go to ${url}, and re-run login command`);
process.exit(2);
}
try {
const resp = await postJSON(base, '/api/cli/task', { secret });
if (!resp.task) throw new Error('No task in response');
console.log(resp.task);
} catch (e) {
if (e && e.statusCode === 401) {
const url = useLocal ? LOCAL_GET_CLI_URL : PROD_GET_CLI_URL;
console.error(`\nSeams like you are not logged in\n\nPlease go to ${url}, and re-run login command`);
process.exit(2);
}
if (e && e.statusCode === 404) {
console.error('You are not tracking any task right now. Start tracking a task in Tracklify and try again.');
process.exit(3);
}
console.error('Error:', e.message);
process.exit(1);
}
}
(async function main() {
const { args, flags } = parseArgs(process.argv);
const useLocal = flags.has('--local');
const base = useLocal ? LOCAL_BASE : REMOTE_BASE;
const cmd = args[0];
if (!cmd || flags.has('--help') || flags.has('-h')) {
printUsage();
process.exit(0);
}
if (cmd === 'login') {
await cmdLogin(args[1], base, useLocal);
return;
}
if (cmd === 'branch') {
await cmdBranch(base, useLocal);
return;
}
if (cmd === 'task') {
await cmdTask(base, useLocal);
return;
}
console.error(`Unknown command: ${cmd}`);
printUsage();
process.exit(2);
})();
CLI for https://tracklify.com - Next-age task management tool with built-in time tracking
How to use CLI: https://tracklify.com/features/git-commit-messages-from-an-active-task
Basically two commands are avaialble:
```
tracklify task
```
return full task url
```
tracklify taskname
```
Returns only taskname