terminalhire 0.4.6 → 0.6.0
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 +11 -0
- package/dist/bin/jpi-bounties.js +49 -1
- package/dist/bin/jpi-claim.js +249 -10
- package/dist/bin/jpi-dispatch.js +1875 -245
- package/dist/bin/jpi-jobs.js +49 -1
- package/dist/bin/jpi-login.js +49 -1
- package/dist/bin/jpi-refresh.js +49 -1
- package/dist/bin/jpi-trajectory.js +2313 -0
- package/dist/src/trajectory.js +2167 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -45,6 +45,17 @@ terminalhire jobs --limit 20 # show top 20 results (default: 10)
|
|
|
45
45
|
terminalhire jobs --remote-only # filter to remote roles only
|
|
46
46
|
terminalhire jobs --all # show all matches above zero score
|
|
47
47
|
|
|
48
|
+
terminalhire bounties # day-sized paid tasks you can knock out today
|
|
49
|
+
terminalhire bounties --priced # only bounties with a known $ amount
|
|
50
|
+
|
|
51
|
+
terminalhire claim record <id|issueUrl> # claim a bounty locally + print the executor brief
|
|
52
|
+
terminalhire claim list --active # list your active claims + accepted-PR rate
|
|
53
|
+
terminalhire claim status <id> # poll source PR merge state (updates the metric)
|
|
54
|
+
|
|
55
|
+
terminalhire trajectory # trajectory from your local Claude Code corpus
|
|
56
|
+
terminalhire trajectory --export # write a derived score + Markdown to ~/.terminalhire/
|
|
57
|
+
terminalhire trajectory --inward # also show private rework/recovery (never exported)
|
|
58
|
+
|
|
48
59
|
terminalhire profile --show # inspect your encrypted local profile (incl. GitHub fields)
|
|
49
60
|
terminalhire profile --edit # set displayName, contactEmail, prefs
|
|
50
61
|
terminalhire profile --delete # wipe profile and encryption key from disk
|
package/dist/bin/jpi-bounties.js
CHANGED
|
@@ -680,6 +680,52 @@ function githubToFingerprint(p) {
|
|
|
680
680
|
const seniorityBand = inferSeniority(p);
|
|
681
681
|
return { skillTags, seniorityBand };
|
|
682
682
|
}
|
|
683
|
+
async function fetchOwnedRepoTraction(login, token) {
|
|
684
|
+
const computedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
685
|
+
const empty = (status) => ({
|
|
686
|
+
status,
|
|
687
|
+
totalStars: 0,
|
|
688
|
+
totalForks: 0,
|
|
689
|
+
reposWithStars: 0,
|
|
690
|
+
top: [],
|
|
691
|
+
computedAt
|
|
692
|
+
});
|
|
693
|
+
let repos;
|
|
694
|
+
try {
|
|
695
|
+
repos = await ghFetch(
|
|
696
|
+
`/users/${login}/repos?sort=pushed&per_page=100`,
|
|
697
|
+
token
|
|
698
|
+
);
|
|
699
|
+
} catch (err) {
|
|
700
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
701
|
+
const status = /HTTP 403|HTTP 429|rate limit/i.test(msg) ? "rate-limited" : "failed";
|
|
702
|
+
console.warn(`[github] ${login}: traction fetch failed (${status}) \u2014`, msg);
|
|
703
|
+
return empty(status);
|
|
704
|
+
}
|
|
705
|
+
if (!Array.isArray(repos)) return empty("failed");
|
|
706
|
+
const owned = repos.filter((r) => r && !r.fork && !r.archived);
|
|
707
|
+
let totalStars = 0;
|
|
708
|
+
let totalForks = 0;
|
|
709
|
+
let reposWithStars = 0;
|
|
710
|
+
const ranked = [];
|
|
711
|
+
for (const r of owned) {
|
|
712
|
+
const stars = typeof r.stargazers_count === "number" ? r.stargazers_count : 0;
|
|
713
|
+
const forks = typeof r.forks_count === "number" ? r.forks_count : 0;
|
|
714
|
+
totalStars += stars;
|
|
715
|
+
totalForks += forks;
|
|
716
|
+
if (stars >= 1) reposWithStars++;
|
|
717
|
+
ranked.push({ name: r.name, stars, forks });
|
|
718
|
+
}
|
|
719
|
+
ranked.sort((a, b) => b.stars - a.stars || b.forks - a.forks);
|
|
720
|
+
return {
|
|
721
|
+
status: "ok",
|
|
722
|
+
totalStars,
|
|
723
|
+
totalForks,
|
|
724
|
+
reposWithStars,
|
|
725
|
+
top: ranked.slice(0, TRACTION_TOP_N),
|
|
726
|
+
computedAt
|
|
727
|
+
};
|
|
728
|
+
}
|
|
683
729
|
async function ghFetchRaw(path, token) {
|
|
684
730
|
return fetch(`https://api.github.com${path}`, { headers: ghHeaders(token) });
|
|
685
731
|
}
|
|
@@ -888,11 +934,12 @@ function deriveResumeTrend(cred, repoRecency, now = Date.now()) {
|
|
|
888
934
|
}
|
|
889
935
|
return scored.sort((a, b) => b.weight - a.weight).slice(0, 12).map((s) => s.t);
|
|
890
936
|
}
|
|
891
|
-
var MIN_STARS, MIN_CONTRIBUTORS, CANDIDATE_PR_PAGE, TRIVIAL_PR_TITLE, RESUME_DECAY_HALF_LIFE_MS, RESUME_MIN_SCORE;
|
|
937
|
+
var TRACTION_TOP_N, MIN_STARS, MIN_CONTRIBUTORS, CANDIDATE_PR_PAGE, TRIVIAL_PR_TITLE, RESUME_DECAY_HALF_LIFE_MS, RESUME_MIN_SCORE;
|
|
892
938
|
var init_github = __esm({
|
|
893
939
|
"../../packages/core/src/github.ts"() {
|
|
894
940
|
"use strict";
|
|
895
941
|
init_vocabulary();
|
|
942
|
+
TRACTION_TOP_N = 6;
|
|
896
943
|
MIN_STARS = 50;
|
|
897
944
|
MIN_CONTRIBUTORS = 10;
|
|
898
945
|
CANDIDATE_PR_PAGE = 50;
|
|
@@ -2571,6 +2618,7 @@ __export(src_exports, {
|
|
|
2571
2618
|
expandWeighted: () => expandWeighted,
|
|
2572
2619
|
extractSkillTags: () => extractSkillTags,
|
|
2573
2620
|
fetchGitHubProfile: () => fetchGitHubProfile,
|
|
2621
|
+
fetchOwnedRepoTraction: () => fetchOwnedRepoTraction,
|
|
2574
2622
|
fetchRepoRecency: () => fetchRepoRecency,
|
|
2575
2623
|
flattenTiers: () => flattenTiers,
|
|
2576
2624
|
getBuyer: () => getBuyer,
|
package/dist/bin/jpi-claim.js
CHANGED
|
@@ -106,10 +106,56 @@ var init_claims = __esm({
|
|
|
106
106
|
import { readFileSync as readFileSync2, existsSync as existsSync2 } from "fs";
|
|
107
107
|
import { join as join2 } from "path";
|
|
108
108
|
import { homedir as homedir2 } from "os";
|
|
109
|
+
import { execFile } from "child_process";
|
|
110
|
+
import { promisify } from "util";
|
|
111
|
+
import { createInterface } from "readline";
|
|
109
112
|
var TERMINALHIRE_DIR2 = join2(homedir2(), ".terminalhire");
|
|
110
113
|
var INDEX_CACHE_FILE = join2(TERMINALHIRE_DIR2, "index-cache.json");
|
|
111
114
|
var GH_API = "https://api.github.com";
|
|
112
115
|
var GH_HEADERS = { "User-Agent": "terminalhire-claim", Accept: "application/vnd.github+json" };
|
|
116
|
+
var pExecFile = promisify(execFile);
|
|
117
|
+
async function sh(cmd, args, opts = {}) {
|
|
118
|
+
const { stdout } = await pExecFile(cmd, args, { ...opts, shell: false, maxBuffer: 16 * 1024 * 1024 });
|
|
119
|
+
return String(stdout).trim();
|
|
120
|
+
}
|
|
121
|
+
async function confirm(question) {
|
|
122
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
123
|
+
try {
|
|
124
|
+
const ans = await new Promise((resolve) => rl.question(question, resolve));
|
|
125
|
+
return /^y(es)?$/i.test(String(ans).trim());
|
|
126
|
+
} finally {
|
|
127
|
+
rl.close();
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
var VALUE_FLAGS = /* @__PURE__ */ new Set(["worktree", "branch"]);
|
|
131
|
+
function parseArgs(argv) {
|
|
132
|
+
const flags = {};
|
|
133
|
+
const positional = [];
|
|
134
|
+
for (let i = 0; i < argv.length; i++) {
|
|
135
|
+
const a = argv[i];
|
|
136
|
+
if (a.startsWith("--")) {
|
|
137
|
+
const key = a.slice(2);
|
|
138
|
+
if (VALUE_FLAGS.has(key)) {
|
|
139
|
+
const val = argv[i + 1];
|
|
140
|
+
if (val === void 0 || val.startsWith("--")) {
|
|
141
|
+
console.error(`terminalhire claim: --${key} requires a value.`);
|
|
142
|
+
process.exit(1);
|
|
143
|
+
}
|
|
144
|
+
flags[key] = val;
|
|
145
|
+
i++;
|
|
146
|
+
} else {
|
|
147
|
+
flags[key] = true;
|
|
148
|
+
}
|
|
149
|
+
} else {
|
|
150
|
+
positional.push(a);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return { flags, positional };
|
|
154
|
+
}
|
|
155
|
+
function parseRepoFromRemote(url) {
|
|
156
|
+
const m = String(url ?? "").trim().match(/github\.com[:/]+([^/]+)\/([^/]+?)(?:\.git)?\/?$/);
|
|
157
|
+
return m ? `${m[1]}/${m[2]}` : null;
|
|
158
|
+
}
|
|
113
159
|
function findBountyInCache(bountyId) {
|
|
114
160
|
try {
|
|
115
161
|
if (!existsSync2(INDEX_CACHE_FILE)) return null;
|
|
@@ -264,7 +310,10 @@ async function cmdRecord(arg) {
|
|
|
264
310
|
console.log(" \u2022 MUST NOT `git push` or `gh pr` \u2014 pushing happens only via `terminalhire submit`");
|
|
265
311
|
console.log(" \u2022 clone + static analysis + patch only; NO test/build execution without explicit approval");
|
|
266
312
|
console.log(" \u2022 no access to ~/.terminalhire (the executor never needs your profile)");
|
|
267
|
-
console.log("\n Next:
|
|
313
|
+
console.log("\n Next:");
|
|
314
|
+
console.log(" 1. record the worktree: terminalhire claim attach " + claim.id + " --worktree <path> --branch <branch>");
|
|
315
|
+
console.log(" 2. do the work + review, then mark it cleared: terminalhire claim update " + claim.id + " ready");
|
|
316
|
+
console.log(" 3. publish (pushes to your fork + opens the PR): terminalhire claim submit " + claim.id);
|
|
268
317
|
}
|
|
269
318
|
async function cmdPreview(arg, { json } = {}) {
|
|
270
319
|
if (!arg) {
|
|
@@ -390,33 +439,223 @@ async function cmdRelease(id) {
|
|
|
390
439
|
console.log(removed ? `Released claim: ${id}` : `terminalhire claim: no claim with id '${id}'.`);
|
|
391
440
|
if (!removed) process.exit(1);
|
|
392
441
|
}
|
|
442
|
+
async function cmdAttach(id, worktree, branch) {
|
|
443
|
+
const claims = await Promise.resolve().then(() => (init_claims(), claims_exports));
|
|
444
|
+
if (!id || !worktree || !branch) {
|
|
445
|
+
console.error("Usage: terminalhire claim attach <id> --worktree <path> --branch <branchName>");
|
|
446
|
+
console.error(" Records the worktree + branch so `terminalhire claim submit` can verify identity before pushing.");
|
|
447
|
+
process.exit(1);
|
|
448
|
+
}
|
|
449
|
+
if (!claims.findClaim(id)) {
|
|
450
|
+
console.error(`terminalhire claim: no claim with id '${id}'.`);
|
|
451
|
+
process.exit(1);
|
|
452
|
+
}
|
|
453
|
+
let toplevel;
|
|
454
|
+
try {
|
|
455
|
+
toplevel = await sh("git", ["-C", worktree, "rev-parse", "--show-toplevel"]);
|
|
456
|
+
} catch {
|
|
457
|
+
console.error(`terminalhire claim: '${worktree}' is not a git work tree.`);
|
|
458
|
+
process.exit(1);
|
|
459
|
+
}
|
|
460
|
+
claims.updateClaim(id, { worktreePath: toplevel, branch });
|
|
461
|
+
console.log(`Attached ${id}: worktree=${toplevel} branch=${branch}`);
|
|
462
|
+
}
|
|
463
|
+
async function cmdSubmit(id, worktreeOverride) {
|
|
464
|
+
const claims = await Promise.resolve().then(() => (init_claims(), claims_exports));
|
|
465
|
+
if (!id) {
|
|
466
|
+
console.error("Usage: terminalhire claim submit <id> [--worktree <path>]");
|
|
467
|
+
process.exit(1);
|
|
468
|
+
}
|
|
469
|
+
const claim = claims.findClaim(id);
|
|
470
|
+
if (!claim) {
|
|
471
|
+
console.error(`terminalhire claim: no claim with id '${id}'.`);
|
|
472
|
+
process.exit(1);
|
|
473
|
+
}
|
|
474
|
+
if (claim.state !== "ready") {
|
|
475
|
+
console.error(
|
|
476
|
+
`terminalhire claim: ${id} is '${claim.state}', not 'ready'. Submit only runs after the review gate clears it:
|
|
477
|
+
terminalhire claim update ${id} ready`
|
|
478
|
+
);
|
|
479
|
+
process.exit(1);
|
|
480
|
+
}
|
|
481
|
+
if (claim.review && claim.review.verdict === "revise") {
|
|
482
|
+
console.error(`terminalhire claim: ${id} review verdict is 'revise' \u2014 the gate said do not submit. Resolve blockers and re-review first.`);
|
|
483
|
+
process.exit(1);
|
|
484
|
+
}
|
|
485
|
+
if (!claim.worktreePath || !claim.branch) {
|
|
486
|
+
console.error(
|
|
487
|
+
`terminalhire claim: ${id} has no recorded worktree/branch \u2014 cannot verify what to push. Run:
|
|
488
|
+
terminalhire claim attach ${id} --worktree <path> --branch <branch>`
|
|
489
|
+
);
|
|
490
|
+
process.exit(1);
|
|
491
|
+
}
|
|
492
|
+
const inspectDir = worktreeOverride || process.cwd();
|
|
493
|
+
let toplevel;
|
|
494
|
+
try {
|
|
495
|
+
toplevel = await sh("git", ["-C", inspectDir, "rev-parse", "--show-toplevel"]);
|
|
496
|
+
} catch {
|
|
497
|
+
console.error(
|
|
498
|
+
`terminalhire claim: '${inspectDir}' is not a git work tree.
|
|
499
|
+
Run submit from inside the claim's worktree (or pass --worktree <path>).`
|
|
500
|
+
);
|
|
501
|
+
process.exit(1);
|
|
502
|
+
}
|
|
503
|
+
if (toplevel !== claim.worktreePath) {
|
|
504
|
+
console.error(
|
|
505
|
+
`terminalhire claim: worktree mismatch \u2014 refusing to push.
|
|
506
|
+
expected: ${claim.worktreePath}
|
|
507
|
+
found: ${toplevel}
|
|
508
|
+
Run submit from inside the claim's worktree (or pass --worktree <path>).`
|
|
509
|
+
);
|
|
510
|
+
process.exit(1);
|
|
511
|
+
}
|
|
512
|
+
const wt = toplevel;
|
|
513
|
+
const curBranch = await sh("git", ["-C", wt, "rev-parse", "--abbrev-ref", "HEAD"]);
|
|
514
|
+
if (curBranch !== claim.branch) {
|
|
515
|
+
console.error(
|
|
516
|
+
`terminalhire claim: branch mismatch \u2014 refusing to push.
|
|
517
|
+
expected: ${claim.branch}
|
|
518
|
+
found: ${curBranch}
|
|
519
|
+
Check out the claim's branch first.`
|
|
520
|
+
);
|
|
521
|
+
process.exit(1);
|
|
522
|
+
}
|
|
523
|
+
let defaultBranch = null;
|
|
524
|
+
try {
|
|
525
|
+
defaultBranch = (await sh("git", ["-C", wt, "symbolic-ref", "--short", "refs/remotes/origin/HEAD"])).replace(/^origin\//, "");
|
|
526
|
+
} catch {
|
|
527
|
+
}
|
|
528
|
+
if (defaultBranch && claim.branch === defaultBranch) {
|
|
529
|
+
console.error(`terminalhire claim: '${claim.branch}' is the default branch \u2014 open the PR from a feature branch.`);
|
|
530
|
+
process.exit(1);
|
|
531
|
+
}
|
|
532
|
+
if (defaultBranch) {
|
|
533
|
+
let ahead = "0";
|
|
534
|
+
try {
|
|
535
|
+
ahead = await sh("git", ["-C", wt, "rev-list", "--count", `origin/${defaultBranch}..HEAD`]);
|
|
536
|
+
} catch {
|
|
537
|
+
ahead = "1";
|
|
538
|
+
}
|
|
539
|
+
if (ahead === "0") {
|
|
540
|
+
console.error(`terminalhire claim: branch has no commits ahead of origin/${defaultBranch} \u2014 nothing to submit.`);
|
|
541
|
+
process.exit(1);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
const dirty = await sh("git", ["-C", wt, "status", "--porcelain"]);
|
|
545
|
+
if (dirty) {
|
|
546
|
+
console.error("terminalhire claim: working tree is not clean \u2014 commit or stash before submitting (submit pushes what was reviewed).");
|
|
547
|
+
process.exit(1);
|
|
548
|
+
}
|
|
549
|
+
let originUrl;
|
|
550
|
+
try {
|
|
551
|
+
originUrl = await sh("git", ["-C", wt, "remote", "get-url", "origin"]);
|
|
552
|
+
} catch {
|
|
553
|
+
console.error("terminalhire claim: no 'origin' remote in the worktree.");
|
|
554
|
+
process.exit(1);
|
|
555
|
+
}
|
|
556
|
+
const originRepo = parseRepoFromRemote(originUrl);
|
|
557
|
+
if (!originRepo) {
|
|
558
|
+
console.error(`terminalhire claim: could not parse owner/repo from origin (${originUrl}).`);
|
|
559
|
+
process.exit(1);
|
|
560
|
+
}
|
|
561
|
+
if (originRepo.toLowerCase() === claim.repoFullName.toLowerCase()) {
|
|
562
|
+
console.error(
|
|
563
|
+
`terminalhire claim: origin points at the UPSTREAM bounty repo (${claim.repoFullName}), not a fork.
|
|
564
|
+
Pushing would create a branch directly on the target repo. Fork first:
|
|
565
|
+
gh repo fork ${claim.repoFullName} --clone=false
|
|
566
|
+
set your fork as 'origin' (or push it there), then retry.`
|
|
567
|
+
);
|
|
568
|
+
process.exit(1);
|
|
569
|
+
}
|
|
570
|
+
let ghUser;
|
|
571
|
+
try {
|
|
572
|
+
ghUser = await sh("gh", ["api", "user", "-q", ".login"]);
|
|
573
|
+
} catch {
|
|
574
|
+
console.error("terminalhire claim: 'gh' CLI not available or not authenticated. Run 'gh auth login'.");
|
|
575
|
+
process.exit(1);
|
|
576
|
+
}
|
|
577
|
+
const upstream = claim.repoFullName;
|
|
578
|
+
const head = `${ghUser}:${claim.branch}`;
|
|
579
|
+
console.log(`
|
|
580
|
+
SUBMIT \xB7 ${claim.title}`);
|
|
581
|
+
console.log(` upstream: ${upstream}`);
|
|
582
|
+
console.log(` fork: ${originRepo}`);
|
|
583
|
+
console.log(` branch: ${claim.branch}`);
|
|
584
|
+
console.log(` head: ${head}`);
|
|
585
|
+
console.log(` issue: ${claim.issueUrl}`);
|
|
586
|
+
const ok = await confirm(`
|
|
587
|
+
Push '${claim.branch}' to ${originRepo} and open a PR against ${upstream}? (y/N) `);
|
|
588
|
+
if (!ok) {
|
|
589
|
+
console.log("Aborted \u2014 nothing pushed.");
|
|
590
|
+
return;
|
|
591
|
+
}
|
|
592
|
+
try {
|
|
593
|
+
await sh("git", ["-C", wt, "push", "origin", claim.branch]);
|
|
594
|
+
} catch (err) {
|
|
595
|
+
console.error(`terminalhire claim: git push failed (NOT force-pushed). ${err.stderr || err.message || err}`);
|
|
596
|
+
console.error(` Resolve and retry, or open the PR manually then: terminalhire claim update ${id} submitted <prUrl>`);
|
|
597
|
+
process.exit(1);
|
|
598
|
+
}
|
|
599
|
+
let prUrl = null;
|
|
600
|
+
try {
|
|
601
|
+
const existing = await sh("gh", ["pr", "list", "--repo", upstream, "--head", head, "--state", "open", "--json", "url", "-q", ".[0].url // empty"]);
|
|
602
|
+
if (existing) prUrl = existing;
|
|
603
|
+
} catch {
|
|
604
|
+
}
|
|
605
|
+
if (!prUrl) {
|
|
606
|
+
const issueNum = (parseGitHubUrl(claim.issueUrl) || {}).number;
|
|
607
|
+
const body = issueNum ? `Closes #${issueNum}` : "";
|
|
608
|
+
try {
|
|
609
|
+
const out = await sh("gh", ["pr", "create", "--repo", upstream, "--head", head, "--title", claim.title, "--body", body]);
|
|
610
|
+
prUrl = out.split("\n").map((l) => l.trim()).filter((l) => l.startsWith("https://github.com/")).pop() || null;
|
|
611
|
+
} catch (err) {
|
|
612
|
+
console.error(`terminalhire claim: branch pushed, but 'gh pr create' failed. ${err.stderr || err.message || err}`);
|
|
613
|
+
console.error(` Open the PR manually (gh pr create / web UI), then: terminalhire claim update ${id} submitted <prUrl>`);
|
|
614
|
+
process.exit(1);
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
if (!prUrl || !parseGitHubUrl(prUrl)) {
|
|
618
|
+
console.error(`terminalhire claim: could not determine the PR URL. Set it manually: terminalhire claim update ${id} submitted <prUrl>`);
|
|
619
|
+
process.exit(1);
|
|
620
|
+
}
|
|
621
|
+
claims.updateClaim(id, { state: "submitted", prUrl });
|
|
622
|
+
console.log(`
|
|
623
|
+
\u2713 Submitted ${id} \u2192 ${prUrl}`);
|
|
624
|
+
console.log(` Run 'terminalhire claim status ${id}' after the maintainer acts to fold the merge into your accepted-PR rate.`);
|
|
625
|
+
}
|
|
393
626
|
async function run() {
|
|
394
627
|
const verb = process.argv[2];
|
|
395
|
-
const
|
|
396
|
-
const active =
|
|
397
|
-
const json =
|
|
628
|
+
const { flags, positional } = parseArgs(process.argv.slice(3));
|
|
629
|
+
const active = Boolean(flags.active);
|
|
630
|
+
const json = Boolean(flags.json);
|
|
398
631
|
try {
|
|
399
632
|
switch (verb) {
|
|
400
633
|
case "preview":
|
|
401
|
-
await cmdPreview(
|
|
634
|
+
await cmdPreview(positional[0], { json });
|
|
402
635
|
break;
|
|
403
636
|
case "record":
|
|
404
|
-
await cmdRecord(
|
|
637
|
+
await cmdRecord(positional[0]);
|
|
405
638
|
break;
|
|
406
639
|
case "list":
|
|
407
640
|
await cmdList(active);
|
|
408
641
|
break;
|
|
409
642
|
case "status":
|
|
410
|
-
await cmdStatus(
|
|
643
|
+
await cmdStatus(positional[0]);
|
|
411
644
|
break;
|
|
412
645
|
case "update":
|
|
413
|
-
await cmdUpdate(
|
|
646
|
+
await cmdUpdate(positional[0], positional[1], positional[2]);
|
|
647
|
+
break;
|
|
648
|
+
case "attach":
|
|
649
|
+
await cmdAttach(positional[0], flags.worktree, flags.branch);
|
|
650
|
+
break;
|
|
651
|
+
case "submit":
|
|
652
|
+
await cmdSubmit(positional[0], flags.worktree);
|
|
414
653
|
break;
|
|
415
654
|
case "release":
|
|
416
|
-
await cmdRelease(
|
|
655
|
+
await cmdRelease(positional[0]);
|
|
417
656
|
break;
|
|
418
657
|
default:
|
|
419
|
-
console.error(`terminalhire claim: unknown verb '${verb ?? ""}'. Expected: preview | record | list | status | update | release`);
|
|
658
|
+
console.error(`terminalhire claim: unknown verb '${verb ?? ""}'. Expected: preview | record | attach | list | status | update | submit | release`);
|
|
420
659
|
process.exit(1);
|
|
421
660
|
}
|
|
422
661
|
} catch (err) {
|