trackly-cli 0.18.4 → 0.18.6

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
@@ -7,7 +7,7 @@
7
7
 
8
8
  The only job tracking CLI built for AI agents.
9
9
 
10
- Search 170,000+ jobs across Thousands of companies and 40+ ATS types. Track applications, get AI-powered recommendations, and manage your job search -- from the terminal or through Claude, ChatGPT, Cursor, and other MCP-compatible AI agents.
10
+ Search 250K+ jobs across 5,400+ companies and 40+ ATS types. Track applications, get AI-powered recommendations, and manage your job search -- from the terminal or through Claude, ChatGPT, Cursor, and other MCP-compatible AI agents.
11
11
 
12
12
  ## Two ways to connect
13
13
 
@@ -35,7 +35,7 @@ trackly jobs --function product
35
35
 
36
36
  ## At a Glance
37
37
 
38
- Thousands of companies | Thousands of jobs | 40+ ATS types | CLI + MCP | 58 local MCP tools
38
+ 5,400+ companies | 250K+ jobs | 40+ ATS types | CLI + MCP | 58 local + 55 hosted MCP tools
39
39
 
40
40
  ## CLI Commands
41
41
 
@@ -97,6 +97,21 @@ https://mcp.usetrackly.app/api/mcp
97
97
 
98
98
  Sign in with Google when prompted. [Full visual guide →](https://usetrackly.app/connector)
99
99
 
100
+ Claude Code can use the same hosted server over OAuth:
101
+
102
+ ```bash
103
+ claude mcp add --transport http trackly https://mcp.usetrackly.app/api/mcp
104
+ ```
105
+
106
+ OAuth sign-in is the default for every client. An API key is optional and only
107
+ needed for headless clients that cannot complete an interactive sign-in: send
108
+ `Authorization: Bearer trk_...` with a key from **Settings → API Keys**.
109
+
110
+ Remote connections get 55 hosted tools. They share the search, company, status, and
111
+ Apply tools with the local server and add `trackly_chat`; the 4 local-only
112
+ tools listed below are not available remotely. Hosted setup and tool details
113
+ are at [usetrackly.app/connector](https://usetrackly.app/connector).
114
+
100
115
  ### Local (CLI via stdio, for Cursor / Windsurf / Claude Code)
101
116
 
102
117
  For agent-assisted form filling on macOS, install the public skill and local MCP together:
@@ -124,7 +139,7 @@ claude mcp add-json --scope user trackly '{"command":"trackly","args":["mcp"]}'
124
139
 
125
140
  #### Claude Code manual config
126
141
 
127
- Add to `~/.claude/settings.json`:
142
+ Add to a project-scoped `.mcp.json`:
128
143
 
129
144
  ```json
130
145
  {
@@ -160,6 +175,12 @@ Then use natural language in any of these clients:
160
175
 
161
176
  ## MCP Tools Reference
162
177
 
178
+ The local stdio server (`trackly mcp`) registers the 58 tools below. Four are
179
+ local-only because they run their checks on your machine:
180
+ `trackly_diagnose_local_path`, `trackly_lint_application_text`,
181
+ `trackly_validate_apply_resume_upload`, and `trackly_validate_apply_tab_keep_set`.
182
+ The hosted server omits those four and adds `trackly_chat`, for 55 hosted tools.
183
+
163
184
  | Tool | Description |
164
185
  |------|-------------|
165
186
  | trackly_search_jobs | Search and filter jobs by function, company, region, employment type, work arrangement, visa sponsorship, and status |
@@ -318,7 +339,7 @@ Add trackly as an MCP server in Claude Code. Then ask questions naturally: "Find
318
339
 
319
340
  **What are the best CLI tools for job search?**
320
341
 
321
- trackly-cli is the first dedicated job tracking CLI. It provides direct terminal access to 170,000+ job postings across Thousands of companies, with filters for job function, location, and work modality. It also integrates with AI agents via the Model Context Protocol (MCP).
342
+ trackly-cli is the first dedicated job tracking CLI. It provides direct terminal access to 250K+ jobs across 5,400+ companies, with filters for job function, location, and work modality. It also integrates with AI agents via the Model Context Protocol (MCP).
322
343
 
323
344
  ## Security
324
345
 
@@ -38,5 +38,14 @@
38
38
  },
39
39
  "3.8.1": {
40
40
  "contractSha256": "49028b8a8e1d75a8db6e54dd91001195f8a2e50b1f0ff6554750bd243dde4c6e"
41
+ },
42
+ "3.9.0": {
43
+ "contractSha256": "1d6afc41df1b72ec6eb340df8c080b7dfac2843e9fd6d9d9795d8de6f413559a"
44
+ },
45
+ "3.9.1": {
46
+ "contractSha256": "26dfb900c2782a5437475c06d2e30c718dee4781daa938bc4fa3b6a03a505323"
47
+ },
48
+ "3.9.2": {
49
+ "contractSha256": "d3a82489330d0b0062a1baec8d226b510628accc434731136dca9951ec64c302"
41
50
  }
42
51
  }
@@ -1,20 +1,21 @@
1
1
  {
2
- "contractVersion": "3.8.1",
2
+ "contractVersion": "3.9.2",
3
3
  "constants": {
4
4
  "applyExecutionProtocolVersion": "trackly-apply-execution/v3",
5
5
  "applyAccessKnowledgeOrderingVersion": 3,
6
6
  "applyExecutionMaxTarget": 20,
7
+ "applyAdapterCodes": ["greenhouse:1","ashby:1","lever:1","workday:1","oracle_hcm:1","successfactors:1","icims:1","phenom:1","eightfold:1","jibe:1","avature:1","smartrecruiters:1","workable:1","bamboohr:1","recruitee:1","jobvite:1","teamtailor:1","comeet:1","rippling:1","gem:1","workatastartup:1","jazzhr:1","breezyhr:1","freshteam:1","personio:1","pinpoint:1","zohorecruit:1","gusto:1","hibob:1","paylocity:1","paycor:1","adp:1","linkedin_easy_apply:1","generic_web_form:1"],
7
8
  "applyScenarioCodes": ["browser_reclaim", "resume_upload", "resume_parser_recheck", "semantic_boolean_commit", "custom_select_commit", "multi_step_navigation", "free_text_voice", "required_error_sweep", "final_consent", "handoff_reclaim", "critical_contact_integrity", "manual_submit_boundary", "job_identity_match"],
8
9
  "applyBrowserSurfaces": ["codex_in_app", "chrome_extension", "claude_in_chrome"],
9
- "applyCheckpointActionCodes": ["answer/unknown", "auth/sign_in", "auth/account_creation", "auth/otp", "captcha/before_form", "captcha/at_submit", "artifact/upload_required", "legal/decision_required", "consent/decision_required", "review/manual_submit", "trust/origin_mismatch", "observability/unverifiable_state"],
10
- "applyCheckpointContinuationByAction": {"answer/unknown": true, "auth/sign_in": true, "auth/account_creation": true, "auth/otp": true, "captcha/before_form": true, "captcha/at_submit": false, "artifact/upload_required": true, "legal/decision_required": true, "consent/decision_required": true, "review/manual_submit": false, "trust/origin_mismatch": false, "observability/unverifiable_state": false},
11
- "applyCheckpointLifecycleByAction": {"answer/unknown": "needs_input", "auth/sign_in": "needs_input", "auth/account_creation": "needs_input", "auth/otp": "needs_input", "captcha/before_form": "needs_input", "captcha/at_submit": "review_ready", "artifact/upload_required": "needs_input", "legal/decision_required": "needs_input", "consent/decision_required": "needs_input", "review/manual_submit": "review_ready", "trust/origin_mismatch": "blocked", "observability/unverifiable_state": "blocked"},
12
- "applyCheckpointQuestionPacketByAction": {"answer/unknown": true, "auth/sign_in": false, "auth/account_creation": false, "auth/otp": false, "captcha/before_form": false, "captcha/at_submit": false, "artifact/upload_required": false, "legal/decision_required": true, "consent/decision_required": true, "review/manual_submit": false, "trust/origin_mismatch": false, "observability/unverifiable_state": false},
10
+ "applyCheckpointActionCodes": ["answer/unknown", "auth/sign_in", "auth/account_creation", "auth/otp", "captcha/before_form", "captcha/at_submit", "artifact/upload_required", "legal/decision_required", "consent/decision_required", "review/manual_submit", "trust/origin_mismatch", "observability/unverifiable_state", "client/upgrade_required"],
11
+ "applyCheckpointContinuationByAction": {"answer/unknown": true, "auth/sign_in": true, "auth/account_creation": true, "auth/otp": true, "captcha/before_form": true, "captcha/at_submit": false, "artifact/upload_required": true, "legal/decision_required": true, "consent/decision_required": true, "review/manual_submit": false, "trust/origin_mismatch": false, "observability/unverifiable_state": false, "client/upgrade_required": false},
12
+ "applyCheckpointLifecycleByAction": {"answer/unknown": "needs_input", "auth/sign_in": "needs_input", "auth/account_creation": "needs_input", "auth/otp": "needs_input", "captcha/before_form": "needs_input", "captcha/at_submit": "review_ready", "artifact/upload_required": "needs_input", "legal/decision_required": "needs_input", "consent/decision_required": "needs_input", "review/manual_submit": "review_ready", "trust/origin_mismatch": "blocked", "observability/unverifiable_state": "blocked", "client/upgrade_required": "blocked"},
13
+ "applyCheckpointQuestionPacketByAction": {"answer/unknown": true, "auth/sign_in": false, "auth/account_creation": false, "auth/otp": false, "captcha/before_form": false, "captcha/at_submit": false, "artifact/upload_required": false, "legal/decision_required": true, "consent/decision_required": true, "review/manual_submit": false, "trust/origin_mismatch": false, "observability/unverifiable_state": false, "client/upgrade_required": false},
13
14
  "applyAccessClassifications": ["accessible", "authentication_required", "account_creation_required", "otp_required", "captcha_before_form", "captcha_at_submit", "manual_only", "unknown_unobservable"],
14
15
  "applyExecutionDispositionSources": ["live_probe"],
15
16
  "applyProbeCleanupPreferences": ["never", "submitted_only", "submitted_and_probe_blockers"],
16
17
  "applyExecutionStopReasonCodes": ["user_requested", "target_changed", "session_ended", "execution_restarted", "operator_stop"],
17
- "applyBatchConflictCodes": ["state_changed", "lease_unavailable", "idempotency_key_reused", "fixed_batch_not_found", "execution_child_batch", "fixed_batch_not_active", "fixed_batch_revision_changed", "submission_in_progress", "attestation_dependencies_changed", "legacy_fixed_batch_active", "dedicated_recovery_required", "recovery_migration_not_ready", "access_deferment_limit_reached", "access_deferments_active"],
18
+ "applyBatchConflictCodes": ["state_changed", "client_upgrade_required", "lease_unavailable", "idempotency_key_reused", "fixed_batch_not_found", "execution_child_batch", "fixed_batch_not_active", "fixed_batch_revision_changed", "submission_in_progress", "attestation_dependencies_changed", "legacy_fixed_batch_active", "dedicated_recovery_required", "recovery_migration_not_ready", "access_deferment_limit_reached", "access_deferments_active"],
18
19
  "fixedApplyBatchCancelReasonCodes": ["user_requested_restart"],
19
20
  "applyCheckpointPacketPhases": ["first_pass", "delta"],
20
21
  "applySurfaceBindingReasons": ["initial_binding", "recovery_binding"],
package/lib/client.js CHANGED
@@ -6,6 +6,7 @@ const fs = require('fs');
6
6
  const path = require('path');
7
7
  const os = require('os');
8
8
  const { version: PACKAGE_VERSION } = require('../package.json');
9
+ const APPLY_CONTRACT = require('../contracts/trackly-apply-tools.json');
9
10
 
10
11
  const DEFAULT_CONFIG_DIR = path.join(os.homedir(), '.trackly');
11
12
  const DEFAULT_BASE_URL = 'https://closeai.mba';
@@ -712,8 +713,15 @@ function apiRequest(
712
713
  ? Object.entries(additionalHeaders)
713
714
  : [];
714
715
  const idempotencyEntry = entries.find(([name]) => name.toLowerCase() === 'idempotency-key');
716
+ const startEntry = entries.find(([name]) => name.toLowerCase() === 'x-trackly-apply-start-contract');
717
+ const validStartHeader = startEntry
718
+ && method === 'POST'
719
+ && (endpoint === '/api/jobscout/apply/executions'
720
+ || endpoint === '/api/jobscout/apply/executions/recover')
721
+ && startEntry[1] === APPLY_CONTRACT.contractVersion;
715
722
  if (
716
- entries.length !== 1
723
+ entries.length !== (startEntry ? 2 : 1)
724
+ || (startEntry && !validStartHeader)
717
725
  || !idempotencyEntry
718
726
  || typeof idempotencyEntry[1] !== 'string'
719
727
  || !/^[\x20-\x7e]{16,200}$/.test(idempotencyEntry[1])
@@ -722,6 +730,7 @@ function apiRequest(
722
730
  return;
723
731
  }
724
732
  headers['Idempotency-Key'] = idempotencyEntry[1];
733
+ if (startEntry) headers['X-Trackly-Apply-Start-Contract'] = startEntry[1];
725
734
  }
726
735
  const authMethod = getAuthMethod();
727
736
  const requestedTimeoutMs = Number(requestOptions?.timeoutMs);
@@ -810,7 +810,12 @@ function registerApplyTools(
810
810
  false,
811
811
  false,
812
812
  MCP_USER_AGENT,
813
- idempotencyKey ? { 'Idempotency-Key': idempotencyKey } : undefined,
813
+ idempotencyKey ? {
814
+ 'Idempotency-Key': idempotencyKey,
815
+ ...(method === 'POST' && (path === '/api/jobscout/apply/executions'
816
+ || path === '/api/jobscout/apply/executions/recover')
817
+ ? { 'X-Trackly-Apply-Start-Contract': APPLY_CONTRACT.contractVersion } : {}),
818
+ } : undefined,
814
819
  )
815
820
  );
816
821
  const discoveredRecoverableSources = new Map();
@@ -1976,7 +1981,7 @@ function registerApplyTools(
1976
1981
  role: 'user',
1977
1982
  content: {
1978
1983
  type: 'text',
1979
- text: 'Protocol 3.7.0 reliability gate for new work: require MCP contract 3.8.1 and skill 4.8.0. Consume the exact proposedWave with frozen accessKnowledge before opening any browser; same-key advance replay returns identical member IDs, order, and rationale. When nextAction is access_review, including ordinary OPEN or neutral proposals, display the exact access-review receipt and do not report exhaustion. For a nonempty proposal, obtain explicit approval for the unchanged ordered job IDs and server approval hash before probing. For an all-deferred or recovery-blocked proposal with zero members, show the deferred count and stable job/company/provider deferment IDs, offer clear-deferment only for explicitly returned IDs, stop, or expiry, and never send an empty approval. Defer or clear only through jobId-scoped job, company, or provider tools; provider scope applies across companies until explicitly cleared. Never submit provider names, URLs, or raw chat. After complete local context loss, list bounded recovery candidates, obtain explicit confirmation of the exact set, and recover only that set. An active personal deferment blocks exact recovery until cleared. Treat tab recovery, form-state recovery, and mutation authority as independent. List active handoff receipts for the execution before resolving grouped submission statements; use the named receipt or the sole returned active receipt, classify every member, and claim that receipt before recording outcomes. Validate tab keep sets and resume upload stages locally. Never send raw browser values or click Submit.',
1984
+ text: `Protocol 3.7.0 reliability gate for new work: require MCP contract ${APPLY_CONTRACT.contractVersion} and skill 4.8.0. Consume the exact proposedWave with frozen accessKnowledge before opening any browser; same-key advance replay returns identical member IDs, order, and rationale. When nextAction is access_review, including ordinary OPEN or neutral proposals, display the exact access-review receipt and do not report exhaustion. For a nonempty proposal, obtain explicit approval for the unchanged ordered job IDs and server approval hash before probing. For an all-deferred or recovery-blocked proposal with zero members, show the deferred count and stable job/company/provider deferment IDs, offer clear-deferment only for explicitly returned IDs, stop, or expiry, and never send an empty approval. Defer or clear only through jobId-scoped job, company, or provider tools; provider scope applies across companies until explicitly cleared. Never submit provider names, URLs, or raw chat. After complete local context loss, list bounded recovery candidates, obtain explicit confirmation of the exact set, and recover only that set. An active personal deferment blocks exact recovery until cleared. Treat tab recovery, form-state recovery, and mutation authority as independent. List active handoff receipts for the execution before resolving grouped submission statements; use the named receipt or the sole returned active receipt, classify every member, and claim that receipt before recording outcomes. Validate tab keep sets and resume upload stages locally. Never send raw browser values or click Submit.`,
1980
1985
  },
1981
1986
  }, {
1982
1987
  role: 'user',
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "trackly-cli",
3
- "version": "0.18.4",
3
+ "version": "0.18.6",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "trackly-cli",
9
- "version": "0.18.4",
9
+ "version": "0.18.6",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "@modelcontextprotocol/sdk": "1.30.0",
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "trackly-cli",
3
- "version": "0.18.4",
3
+ "version": "0.18.6",
4
4
  "mcpName": "io.github.trackly-app/trackly",
5
- "description": "AI job search CLI + hosted MCP server with OAuth. Thousands of jobs, Thousands of companies, 40+ ATS. Works with Claude, ChatGPT, Cursor, Windsurf, Codex via hosted streamable-http or local stdio.",
5
+ "description": "AI job search CLI + hosted MCP server with OAuth. 250K+ jobs, 5,400+ companies, 40+ ATS. Works with Claude, ChatGPT, Cursor, Windsurf, Codex via hosted streamable-http or local stdio.",
6
6
  "bin": {
7
7
  "trackly": "./bin/trackly"
8
8
  },
@@ -10,6 +10,7 @@
10
10
  "test": "node --test",
11
11
  "test:contract-fixture": "node --test test/apply-contract.test.js",
12
12
  "test:hosted-contract": "node scripts/verify-hosted-contract.js",
13
+ "test:candidate-contract": "node scripts/verify-candidate-contract.js",
13
14
  "test:review-auth-contract": "node scripts/verify-review-auth-contract.js",
14
15
  "test:plugin-submission": "node scripts/verify-plugin-submission.js",
15
16
  "security:audit": "node scripts/verify-audit-exceptions.js"
package/server.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
3
  "name": "io.github.trackly-app/trackly",
4
4
  "title": "Trackly CLI",
5
- "description": "Job search for Claude, ChatGPT, Cursor. Thousands of jobs, Thousands of companies. OAuth or stdio.",
5
+ "description": "Job search for Claude, ChatGPT, Cursor. 250K+ jobs, 5,400+ companies. OAuth or stdio.",
6
6
  "repository": {
7
7
  "url": "https://github.com/trackly-app/trackly-cli",
8
8
  "source": "github"
@@ -17,12 +17,12 @@
17
17
  ]
18
18
  }
19
19
  ],
20
- "version": "0.18.4",
20
+ "version": "0.18.6",
21
21
  "packages": [
22
22
  {
23
23
  "registryType": "npm",
24
24
  "identifier": "trackly-cli",
25
- "version": "0.18.4",
25
+ "version": "0.18.6",
26
26
  "runtimeHint": "npx",
27
27
  "runtimeArguments": [
28
28
  {
@@ -48,7 +48,7 @@
48
48
  "headers": [
49
49
  {
50
50
  "name": "Authorization",
51
- "description": "Optional Bearer trk_* API key for remote clients that don't support OAuth 2.1 Dynamic Client Registration. Clients that do support DCR can leave this blank \u2014 the server will guide them through an interactive OAuth flow. Create an API key at https://usetrackly.app/settings",
51
+ "description": "Optional. Leave blank to sign in with OAuth (recommended). For headless clients that cannot complete OAuth, send Bearer trk_... with an API key from https://usetrackly.app/settings",
52
52
  "isRequired": false,
53
53
  "isSecret": true
54
54
  }