ttctl 0.0.0 → 0.1.0-rc.1

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 CHANGED
@@ -1,27 +1,60 @@
1
1
  # ttctl
2
2
 
3
- > **Placeholder reservation.** The real release is in development.
3
+ [![npm](https://img.shields.io/npm/v/ttctl?logo=npm)](https://www.npmjs.com/package/ttctl)
4
+ [![License](https://img.shields.io/npm/l/ttctl)](https://github.com/alexey-pelykh/ttctl/blob/main/LICENSE)
4
5
 
5
- This package on npm is currently a **name reservation**. There is no working CLI, MCP server, or library here yet only a stub that exists to hold the `ttctl` name on the npm registry while the real implementation is finalized.
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
- ## What this will become
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
- `ttctl` is the unofficial personal-productivity CLI and MCP server for [Toptal Talent](https://talent.toptal.com) profiles — built for fair use against your **own** profile only.
10
+ ## Install
10
11
 
11
- For the real status of development, the source code, the architecture, and the unofficial-tool guardrails, see:
12
+ ```sh
13
+ npm install -g ttctl
14
+ ```
12
15
 
13
- **→ https://github.com/alexey-pelykh/ttctl**
16
+ Or run directly with npx:
14
17
 
15
- The real first release will replace this placeholder shortly. If you installed this package looking for a working tool, please uninstall it and watch the GitHub repository for the real release announcement.
18
+ ```sh
19
+ npx ttctl --help
20
+ ```
16
21
 
17
- ## ⚠️ Unofficial — Personal Use Only
22
+ Requires **Node.js 24**.
18
23
 
19
- `ttctl` is **NOT** affiliated with, endorsed by, or supported by Toptal LLC. It is a personal-productivity tool that interacts with Toptal Talent's interfaces using your own session, exclusively for your own profile's data.
24
+ ## What's in this package
20
25
 
21
- It is **NOT** to be used for spam, mass automation, recruiter scraping, engagement-signal manipulation, or operating against profiles that aren't your own. See the [GitHub repository](https://github.com/alexey-pelykh/ttctl) for the full unofficial-tool policy.
26
+ `ttctl` is the **umbrella binary**. It bundles two sibling packages so end users get one install:
22
27
 
23
- "Toptal" is a trademark of Toptal LLC. The name appears here as **nominative fair use** only `ttctl` is not a Toptal brand.
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](./LICENSE)
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,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -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
@@ -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"}
@@ -0,0 +1,3 @@
1
+ export { buildProgram } from "@ttctl/cli";
2
+ export { buildServer, runMcpStdio } from "@ttctl/mcp";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -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,5 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ export { buildProgram } from "@ttctl/cli";
4
+ export { buildServer, runMcpStdio } from "@ttctl/mcp";
5
+ //# sourceMappingURL=index.js.map
@@ -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.0",
4
- "description": "Unofficial CLI and MCP server for the Toptal Talent platform — placeholder reservation; real release in development",
3
+ "version": "0.1.0-rc.1",
4
+ "description": "Unofficial CLI and MCP server for the Toptal Talent platform",
5
5
  "type": "module",
6
- "main": "./index.js",
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": "git+https://github.com/alexey-pelykh/ttctl.git"
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
- "index.js",
24
- "README.md",
25
- "LICENSE"
26
- ]
27
- }
35
+ "dist"
36
+ ],
37
+ "publishConfig": {
38
+ "access": "public"
39
+ },
40
+ "dependencies": {
41
+ "@ttctl/cli": "^0.1.0-rc.1",
42
+ "@ttctl/mcp": "^0.1.0-rc.1"
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
- );