ttctl 0.0.0 → 0.1.0-rc.2
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.
- package/README.md +45 -12
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +75 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/package.json +42 -11
- package/index.js +0 -7
package/README.md
CHANGED
|
@@ -1,27 +1,60 @@
|
|
|
1
1
|
# ttctl
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/ttctl)
|
|
4
|
+
[](https://github.com/alexey-pelykh/ttctl/blob/main/LICENSE)
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
Unofficial CLI and MCP server for [Toptal Talent](https://talent.toptal.com) — your own profile, your own session, your own data.
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
> **Unofficial.** TTCtl is NOT affiliated with, endorsed by, or supported by Toptal LLC. See the [project README](https://github.com/alexey-pelykh/ttctl#readme) for the full use policy and disclaimer.
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
## Install
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
```sh
|
|
13
|
+
npm install -g ttctl
|
|
14
|
+
```
|
|
12
15
|
|
|
13
|
-
|
|
16
|
+
Or run directly with npx:
|
|
14
17
|
|
|
15
|
-
|
|
18
|
+
```sh
|
|
19
|
+
npx ttctl --help
|
|
20
|
+
```
|
|
16
21
|
|
|
17
|
-
|
|
22
|
+
Requires **Node.js ≥ 24**.
|
|
18
23
|
|
|
19
|
-
|
|
24
|
+
## What's in this package
|
|
20
25
|
|
|
21
|
-
|
|
26
|
+
`ttctl` is the **umbrella binary**. It bundles two sibling packages so end users get one install:
|
|
22
27
|
|
|
23
|
-
|
|
28
|
+
- [`@ttctl/cli`](https://www.npmjs.com/package/@ttctl/cli) — the Commander program (`ttctl profile show`, `ttctl timesheet list`, `ttctl auth signin`, …)
|
|
29
|
+
- [`@ttctl/mcp`](https://www.npmjs.com/package/@ttctl/mcp) — the MCP server (`ttctl mcp` on stdio)
|
|
30
|
+
|
|
31
|
+
If you only need part of TTCtl in another program, install the sibling package directly. For interactive use, this umbrella is the package you want.
|
|
32
|
+
|
|
33
|
+
## Quick Start
|
|
34
|
+
|
|
35
|
+
```sh
|
|
36
|
+
# 1. Bootstrap config interactively (Form A: 1Password reference, recommended)
|
|
37
|
+
ttctl auth init
|
|
38
|
+
|
|
39
|
+
# 2. Sign in — captures the bearer back into ~/.ttctl.yaml
|
|
40
|
+
ttctl auth signin
|
|
41
|
+
|
|
42
|
+
# 3. Verify
|
|
43
|
+
ttctl auth status
|
|
44
|
+
|
|
45
|
+
# 4. View your profile
|
|
46
|
+
ttctl profile show
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## MCP
|
|
50
|
+
|
|
51
|
+
```sh
|
|
52
|
+
# Start the MCP server on stdio (typically spawned by your MCP client)
|
|
53
|
+
ttctl mcp
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
For Claude Desktop / Claude Code / Cursor configuration snippets, the full sub-command reference, configuration shapes (Forms A–D, sync-root exclusions, debug instrumentation), and the disclaimer / fair-use posture, see the [**project README**](https://github.com/alexey-pelykh/ttctl#readme).
|
|
24
57
|
|
|
25
58
|
## License
|
|
26
59
|
|
|
27
|
-
[AGPL-3.0-only](
|
|
60
|
+
[AGPL-3.0-only](https://github.com/alexey-pelykh/ttctl/blob/main/LICENSE). Using the `ttctl` binary as a tool does not impose AGPL obligations on your own code; importing the constituent libraries (`@ttctl/cli` / `@ttctl/mcp` / `@ttctl/core`) does. See the project README's [License](https://github.com/alexey-pelykh/ttctl#license) section.
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
|
+
// Copyright (C) 2026 Oleksii PELYKH
|
|
4
|
+
import { ConfigError, TtctlError, buildProgram, installCrashHandlers, presentTtctlError } from "@ttctl/cli";
|
|
5
|
+
import { runMcpStdio } from "@ttctl/mcp";
|
|
6
|
+
// Wire `uncaughtException` and `unhandledRejection` handlers BEFORE any other
|
|
7
|
+
// executable code (issue #207). The `main().catch()` below covers anything
|
|
8
|
+
// that flows through the awaited Promise chain; the global handlers cover
|
|
9
|
+
// what escapes — fire-and-forget Promise rejections in tool callbacks,
|
|
10
|
+
// throws from `setTimeout` / `setImmediate` / `process.nextTick` callbacks,
|
|
11
|
+
// EventEmitter listeners not in `main`'s chain. Both paths redact captured
|
|
12
|
+
// Toptal session bearers via `redactString` from `@ttctl/core`.
|
|
13
|
+
installCrashHandlers();
|
|
14
|
+
/**
|
|
15
|
+
* Umbrella entrypoint: dispatches to MCP-server mode if invoked as
|
|
16
|
+
* `ttctl mcp`, otherwise routes to the Commander CLI program.
|
|
17
|
+
*
|
|
18
|
+
* The MCP branch is kept first so its early dispatch doesn't conflict with
|
|
19
|
+
* commander's argv parsing.
|
|
20
|
+
*
|
|
21
|
+
* MCP `--config <path>` (#113): the umbrella parses the flag from argv
|
|
22
|
+
* after the `mcp` subcommand position and threads it into
|
|
23
|
+
* `runMcpStdio({ configPath })`. The path is captured ONCE inside
|
|
24
|
+
* `buildServer`; subsequent tool invocations read/write the same path
|
|
25
|
+
* regardless of mid-session env-var changes. Startup-time
|
|
26
|
+
* `resolveConfig(NO_CREDS)` propagates as a non-zero exit so the MCP
|
|
27
|
+
* client sees a clean failure rather than a half-initialized server.
|
|
28
|
+
*/
|
|
29
|
+
async function main() {
|
|
30
|
+
if (process.argv[2] === "mcp") {
|
|
31
|
+
const configPath = parseConfigFlag(process.argv.slice(3));
|
|
32
|
+
try {
|
|
33
|
+
await runMcpStdio(configPath !== undefined ? { configPath } : {});
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
if (err instanceof ConfigError) {
|
|
37
|
+
process.stderr.write(`Error (${err.code}): ${err.message}\n`);
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
throw err;
|
|
41
|
+
}
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const program = buildProgram();
|
|
45
|
+
await program.parseAsync(process.argv);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Parse `--config <path>` (and `--config=<path>`) from a flat argv slice.
|
|
49
|
+
* Returns the first match or `undefined`. Unknown flags are ignored —
|
|
50
|
+
* the MCP server has no other entry-flags today, but this keeps the
|
|
51
|
+
* function tolerant for future additions (SSE port, transport selector,
|
|
52
|
+
* …) layered on top by sister tools.
|
|
53
|
+
*/
|
|
54
|
+
function parseConfigFlag(args) {
|
|
55
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
56
|
+
const arg = args[i];
|
|
57
|
+
if (arg === "--config") {
|
|
58
|
+
return args[i + 1];
|
|
59
|
+
}
|
|
60
|
+
if (arg !== undefined && arg.startsWith("--config=")) {
|
|
61
|
+
return arg.slice("--config=".length);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
main().catch((err) => {
|
|
67
|
+
// Top-level safety net: any TtctlError that escapes a command handler is
|
|
68
|
+
// rendered in the uniform Error/Recovery/Code format (issue #77). Other
|
|
69
|
+
// unexpected errors fall through to the generic single-line stderr.
|
|
70
|
+
if (err instanceof TtctlError)
|
|
71
|
+
presentTtctlError(err);
|
|
72
|
+
console.error(err instanceof Error ? err.message : err);
|
|
73
|
+
process.exit(1);
|
|
74
|
+
});
|
|
75
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,yCAAyC;AACzC,oCAAoC;AAEpC,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC5G,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,8EAA8E;AAC9E,2EAA2E;AAC3E,0EAA0E;AAC1E,uEAAuE;AACvE,4EAA4E;AAC5E,2EAA2E;AAC3E,gEAAgE;AAChE,oBAAoB,EAAE,CAAC;AAEvB;;;;;;;;;;;;;;GAcG;AACH,KAAK,UAAU,IAAI;IACjB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC;QAC9B,MAAM,UAAU,GAAG,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1D,IAAI,CAAC;YACH,MAAM,WAAW,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACpE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,WAAW,EAAE,CAAC;gBAC/B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,IAAI,MAAM,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC;gBAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;QACD,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,YAAY,EAAE,CAAC;IAC/B,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC;AAED;;;;;;GAMG;AACH,SAAS,eAAe,CAAC,IAAuB;IAC9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACxC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,GAAG,KAAK,UAAU,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACrB,CAAC;QACD,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YACrD,OAAO,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IAC5B,yEAAyE;IACzE,wEAAwE;IACxE,oEAAoE;IACpE,IAAI,GAAG,YAAY,UAAU;QAAE,iBAAiB,CAAC,GAAG,CAAC,CAAC;IACtD,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ttctl",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "Unofficial CLI and MCP server for the Toptal Talent platform
|
|
3
|
+
"version": "0.1.0-rc.2",
|
|
4
|
+
"description": "Unofficial CLI and MCP server for the Toptal Talent platform",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=22.19.0"
|
|
8
|
+
},
|
|
7
9
|
"license": "AGPL-3.0-only",
|
|
8
10
|
"author": "Alexey Pelykh (https://github.com/alexey-pelykh)",
|
|
9
11
|
"homepage": "https://github.com/alexey-pelykh/ttctl",
|
|
@@ -11,17 +13,46 @@
|
|
|
11
13
|
"funding": "https://github.com/sponsors/alexey-pelykh",
|
|
12
14
|
"repository": {
|
|
13
15
|
"type": "git",
|
|
14
|
-
"url": "
|
|
16
|
+
"url": "https://github.com/alexey-pelykh/ttctl.git",
|
|
17
|
+
"directory": "packages/ttctl"
|
|
18
|
+
},
|
|
19
|
+
"exports": {
|
|
20
|
+
".": {
|
|
21
|
+
"types": "./dist/cli.d.ts",
|
|
22
|
+
"import": "./dist/cli.js"
|
|
23
|
+
}
|
|
15
24
|
},
|
|
25
|
+
"bin": {
|
|
26
|
+
"ttctl": "./dist/cli.js"
|
|
27
|
+
},
|
|
28
|
+
"mcpName": "io.github.alexey-pelykh/ttctl",
|
|
16
29
|
"keywords": [
|
|
17
30
|
"toptal-talent",
|
|
18
31
|
"mcp",
|
|
19
|
-
"cli"
|
|
20
|
-
"placeholder"
|
|
32
|
+
"cli"
|
|
21
33
|
],
|
|
22
34
|
"files": [
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
35
|
+
"dist"
|
|
36
|
+
],
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@ttctl/cli": "^0.1.0-rc.2",
|
|
42
|
+
"@ttctl/mcp": "^0.1.0-rc.2"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@types/node": "^25",
|
|
46
|
+
"eslint": "^10.3.0",
|
|
47
|
+
"typescript": "~6.0.3",
|
|
48
|
+
"vitest": "^4.1.1"
|
|
49
|
+
},
|
|
50
|
+
"scripts": {
|
|
51
|
+
"clean": "rm -rf dist tsconfig.tsbuildinfo",
|
|
52
|
+
"build": "tsc",
|
|
53
|
+
"typecheck": "tsc --noEmit",
|
|
54
|
+
"test": "vitest run --passWithNoTests",
|
|
55
|
+
"lint": "eslint src/",
|
|
56
|
+
"dev": "tsc --watch"
|
|
57
|
+
}
|
|
58
|
+
}
|
package/index.js
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
// ttctl placeholder — name reservation only.
|
|
2
|
-
// The real release is in development at https://github.com/alexey-pelykh/ttctl
|
|
3
|
-
console.log(
|
|
4
|
-
"ttctl: this is a placeholder reservation, not a functional release.\n" +
|
|
5
|
-
"The real CLI / MCP server is in development. See:\n" +
|
|
6
|
-
" https://github.com/alexey-pelykh/ttctl",
|
|
7
|
-
);
|