@hardfin/cli 0.1.1-dev.59 → 0.1.1-dev.60
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 +16 -10
- package/dist/cli.js +4 -4
- package/dist/completion-tree.json +4 -0
- package/dist/{program-DJuADiEQ.js → program-BP83nk1M.js} +92 -30
- package/package.json +1 -1
- package/templates/AGENTS.md +1 -3
package/README.md
CHANGED
|
@@ -446,6 +446,7 @@ types are stale.
|
|
|
446
446
|
```sh
|
|
447
447
|
hardfin init # the working directory
|
|
448
448
|
hardfin init --dry-run # what it would write, writing nothing
|
|
449
|
+
hardfin init --local # set up the server this CLI runs, in place of the hosted one
|
|
449
450
|
```
|
|
450
451
|
|
|
451
452
|
`hardfin init` gets a project ready for a coding agent to use Hardfin, the way EmDash's starter
|
|
@@ -465,6 +466,11 @@ by default. [Serving an agent](#serving-an-agent) says how it differs from the l
|
|
|
465
466
|
this CLI runs. Every other server in an MCP config, and everything in `AGENTS.md` outside the
|
|
466
467
|
markers, is left as it was. A config that does not hold JSON is skipped, never overwritten.
|
|
467
468
|
|
|
469
|
+
`hardfin init --local` writes the local server in its place: the command `hardfin mcp`, which
|
|
470
|
+
each client starts by name. It needs `hardfin` on the `PATH` of whoever opens the project, and
|
|
471
|
+
it writes no address, so it works in a folder set up for a local build. Run `init` again
|
|
472
|
+
without `--local` to go back to the hosted server.
|
|
473
|
+
|
|
468
474
|
`init` refuses an address that `config.local.json` or `.env` in the folder chose, because the
|
|
469
475
|
address goes into files every agent in the project reads. Pass `--issuer-url` to use it. The
|
|
470
476
|
address must be https, or this machine.
|
|
@@ -477,16 +483,16 @@ package, so `init` writes the copy that matches the installed CLI.
|
|
|
477
483
|
Hardfin has two MCP servers, and an agent needs only one of them. Hardfin hosts one. The
|
|
478
484
|
other is this CLI, run on your machine. Read this section to choose between them.
|
|
479
485
|
|
|
480
|
-
| | The hosted server | The local server
|
|
481
|
-
| --------------------- | -------------------------------------------------------------------- |
|
|
482
|
-
| Runs | At Hardfin, at `https://api.hardfin.com/mcp` | On your machine, started by the agent's client
|
|
483
|
-
| Needs installed | Nothing | This CLI, and Node 20.12 or later
|
|
484
|
-
| Set up by | `hardfin init` | `claude mcp add hardfin -- hardfin mcp`
|
|
485
|
-
| Signs in as | Whoever signs in to Hardfin from the client | Whoever ran `hardfin login` here, or `HARDFIN_API_KEY`
|
|
486
|
-
| Tools | `hardfin_read`, `hardfin_create`, `hardfin_update`, `hardfin_delete` | `hardfin_read`, `hardfin_write`, `hardfin_delete`
|
|
487
|
-
| A call names | An operation from the API reference, with its parameters and body | A command, as the words typed after `hardfin`
|
|
488
|
-
| Read-only when | The sign in was not granted `hardfin:write` | The same, or it was started with `--read-only`
|
|
489
|
-
| Files on your machine | Out of reach | Uploaded and downloaded, inside the folder it runs in
|
|
486
|
+
| | The hosted server | The local server |
|
|
487
|
+
| --------------------- | -------------------------------------------------------------------- | ------------------------------------------------------------------ |
|
|
488
|
+
| Runs | At Hardfin, at `https://api.hardfin.com/mcp` | On your machine, started by the agent's client |
|
|
489
|
+
| Needs installed | Nothing | This CLI, and Node 20.12 or later |
|
|
490
|
+
| Set up by | `hardfin init` | `hardfin init --local`, or `claude mcp add hardfin -- hardfin mcp` |
|
|
491
|
+
| Signs in as | Whoever signs in to Hardfin from the client | Whoever ran `hardfin login` here, or `HARDFIN_API_KEY` |
|
|
492
|
+
| Tools | `hardfin_read`, `hardfin_create`, `hardfin_update`, `hardfin_delete` | `hardfin_read`, `hardfin_write`, `hardfin_delete` |
|
|
493
|
+
| A call names | An operation from the API reference, with its parameters and body | A command, as the words typed after `hardfin` |
|
|
494
|
+
| Read-only when | The sign in was not granted `hardfin:write` | The same, or it was started with `--read-only` |
|
|
495
|
+
| Files on your machine | Out of reach | Uploaded and downloaded, inside the folder it runs in |
|
|
490
496
|
|
|
491
497
|
Choose the hosted server unless one of these holds.
|
|
492
498
|
|
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
3
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="7b79fe1d-6296-5c3c-a667-7257662abc80")}catch(e){}}();
|
|
4
4
|
import module from "node:module";
|
|
5
5
|
//#region src/cli.ts
|
|
6
6
|
module.enableCompileCache?.();
|
|
@@ -14,7 +14,7 @@ process.on("unhandledRejection", (error) => void toCrash(error));
|
|
|
14
14
|
try {
|
|
15
15
|
const answer = await toQuickAnswer(process.argv.slice(2));
|
|
16
16
|
if (answer === void 0) {
|
|
17
|
-
const { toCli, toParseExitCode, wasReportAttempted } = await import("./program-
|
|
17
|
+
const { toCli, toParseExitCode, wasReportAttempted } = await import("./program-BP83nk1M.js");
|
|
18
18
|
try {
|
|
19
19
|
await toCli().parseAsync(process.argv);
|
|
20
20
|
} catch (error) {
|
|
@@ -33,7 +33,7 @@ async function toCrash(error) {
|
|
|
33
33
|
isCrashing = true;
|
|
34
34
|
const isJSON = process.argv.includes("--json") || !process.stdout.isTTY;
|
|
35
35
|
try {
|
|
36
|
-
const { toReported, writeCrash } = await import("./program-
|
|
36
|
+
const { toReported, writeCrash } = await import("./program-BP83nk1M.js");
|
|
37
37
|
writeCrash(error, isJSON);
|
|
38
38
|
await toReported(error, isJSON, void 0, "fatal");
|
|
39
39
|
} catch {
|
|
@@ -54,4 +54,4 @@ async function toQuickAnswer(args) {
|
|
|
54
54
|
export {};
|
|
55
55
|
|
|
56
56
|
//# sourceMappingURL=cli.js.map
|
|
57
|
-
//# debugId=
|
|
57
|
+
//# debugId=7b79fe1d-6296-5c3c-a667-7257662abc80
|
|
@@ -82,6 +82,10 @@
|
|
|
82
82
|
"summary": "Set up a project so coding agents can use Hardfin",
|
|
83
83
|
"runs": true,
|
|
84
84
|
"flags": [
|
|
85
|
+
{
|
|
86
|
+
"name": "local",
|
|
87
|
+
"description": "Set up the MCP server this CLI runs on this machine, in place of the one Hardfin hosts"
|
|
88
|
+
},
|
|
85
89
|
{
|
|
86
90
|
"name": "dry-run",
|
|
87
91
|
"description": "Say what would be written, and write nothing"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
3
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="5a81163a-f2c4-570b-9451-c1fad66921a0")}catch(e){}}();
|
|
4
4
|
import { a as defineCommand, i as GLOBAL_FLAGS, r as ExitCode, t as toInvocation } from "./scrub-BZ0egWxC.js";
|
|
5
5
|
import { n as toAnswer$1, r as toCompletion, t as PATH_VALUES } from "./completion-tree-DLC6ARLR.js";
|
|
6
6
|
import { createRequire } from "node:module";
|
|
@@ -2795,28 +2795,43 @@ const SKILL_DIRECTORIES = [".agents/skills", ".claude/skills"];
|
|
|
2795
2795
|
const initCommand = defineCommand({
|
|
2796
2796
|
name: "init",
|
|
2797
2797
|
summary: "Set up a project so coding agents can use Hardfin",
|
|
2798
|
-
description: "Writes the hardfin-cli skill, a Hardfin section in AGENTS.md, and the Hardfin MCP server for Claude Code, Cursor and VS Code. Running it again updates what it wrote and leaves everything else alone.",
|
|
2798
|
+
description: "Writes the hardfin-cli skill, a Hardfin section in AGENTS.md, and the Hardfin MCP server for Claude Code, Cursor and VS Code. The server is the one Hardfin hosts, or with --local the one this CLI runs. Running it again updates what it wrote and leaves everything else alone.",
|
|
2799
2799
|
arguments: [{
|
|
2800
2800
|
name: "directory",
|
|
2801
2801
|
description: "The project to set up, which is the working directory when omitted",
|
|
2802
2802
|
required: false
|
|
2803
2803
|
}],
|
|
2804
|
-
flags: [
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2804
|
+
flags: [
|
|
2805
|
+
{
|
|
2806
|
+
name: "local",
|
|
2807
|
+
description: "Set up the MCP server this CLI runs on this machine, in place of the one Hardfin hosts",
|
|
2808
|
+
schema: z.boolean()
|
|
2809
|
+
},
|
|
2810
|
+
{
|
|
2811
|
+
name: "dry-run",
|
|
2812
|
+
description: "Say what would be written, and write nothing",
|
|
2813
|
+
schema: z.boolean()
|
|
2814
|
+
},
|
|
2815
|
+
{
|
|
2816
|
+
name: "json",
|
|
2817
|
+
description: "Print machine-readable output, which is the default when stdout is not a terminal",
|
|
2818
|
+
schema: z.boolean()
|
|
2819
|
+
}
|
|
2820
|
+
],
|
|
2821
|
+
examples: [
|
|
2822
|
+
{
|
|
2823
|
+
description: "Set up the project you are in",
|
|
2824
|
+
command: "hardfin init"
|
|
2825
|
+
},
|
|
2826
|
+
{
|
|
2827
|
+
description: "See what it would write first",
|
|
2828
|
+
command: "hardfin init --dry-run"
|
|
2829
|
+
},
|
|
2830
|
+
{
|
|
2831
|
+
description: "Use the local server, which can upload and download files",
|
|
2832
|
+
command: "hardfin init --local"
|
|
2833
|
+
}
|
|
2834
|
+
],
|
|
2820
2835
|
run: runInit
|
|
2821
2836
|
});
|
|
2822
2837
|
async function runInit(input) {
|
|
@@ -2825,7 +2840,7 @@ async function runInit(input) {
|
|
|
2825
2840
|
writeFailure("invalid_arguments", `${target} is not a folder, so there is nothing to set up`, input.isJSON);
|
|
2826
2841
|
return ExitCode.USAGE;
|
|
2827
2842
|
}
|
|
2828
|
-
const mcpUrl = toMcpUrl(input.resolved);
|
|
2843
|
+
const mcpUrl = input.flags["local"] === true ? void 0 : toMcpUrl(input.resolved);
|
|
2829
2844
|
if (mcpUrl instanceof Error) {
|
|
2830
2845
|
writeFailure("invalid_config", mcpUrl.message, input.isJSON);
|
|
2831
2846
|
return ExitCode.USAGE;
|
|
@@ -2838,7 +2853,8 @@ async function runInit(input) {
|
|
|
2838
2853
|
writeData({
|
|
2839
2854
|
directory: target,
|
|
2840
2855
|
dryRun: isDryRun,
|
|
2841
|
-
mcpUrl,
|
|
2856
|
+
mcp: mcpUrl === void 0 ? "local" : "hosted",
|
|
2857
|
+
mcpUrl: mcpUrl ?? null,
|
|
2842
2858
|
changes
|
|
2843
2859
|
});
|
|
2844
2860
|
return ExitCode.OK;
|
|
@@ -2877,17 +2893,63 @@ function toPlan(target, packageDirectory, mcpUrl) {
|
|
|
2877
2893
|
const content = readFileSync(file, "utf8");
|
|
2878
2894
|
for (const place of SKILL_DIRECTORIES) planned.push(toFilePlan(target, join(place, skill, relative(join(skills, skill), file)), content));
|
|
2879
2895
|
}
|
|
2880
|
-
const section = readFileSync(join(packageDirectory, "templates", "AGENTS.md"), "utf8").replaceAll("{{
|
|
2896
|
+
const section = readFileSync(join(packageDirectory, "templates", "AGENTS.md"), "utf8").replaceAll("{{MCP}}", toMcpParagraph(mcpUrl));
|
|
2881
2897
|
planned.push(toFilePlan(target, "AGENTS.md", toAgentsFile(join(target, "AGENTS.md"), section)));
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2898
|
+
const shapes = mcpUrl === void 0 ? [
|
|
2899
|
+
[
|
|
2900
|
+
".mcp.json",
|
|
2901
|
+
"mcpServers",
|
|
2902
|
+
LOCAL_SERVER
|
|
2903
|
+
],
|
|
2904
|
+
[
|
|
2905
|
+
".cursor/mcp.json",
|
|
2906
|
+
"mcpServers",
|
|
2907
|
+
LOCAL_SERVER
|
|
2908
|
+
],
|
|
2909
|
+
[
|
|
2910
|
+
".vscode/mcp.json",
|
|
2911
|
+
"servers",
|
|
2912
|
+
{
|
|
2913
|
+
type: "stdio",
|
|
2914
|
+
...LOCAL_SERVER
|
|
2915
|
+
}
|
|
2916
|
+
]
|
|
2917
|
+
] : [
|
|
2918
|
+
[
|
|
2919
|
+
".mcp.json",
|
|
2920
|
+
"mcpServers",
|
|
2921
|
+
{
|
|
2922
|
+
type: "http",
|
|
2923
|
+
url: mcpUrl
|
|
2924
|
+
}
|
|
2925
|
+
],
|
|
2926
|
+
[
|
|
2927
|
+
".cursor/mcp.json",
|
|
2928
|
+
"mcpServers",
|
|
2929
|
+
{ url: mcpUrl }
|
|
2930
|
+
],
|
|
2931
|
+
[
|
|
2932
|
+
".vscode/mcp.json",
|
|
2933
|
+
"servers",
|
|
2934
|
+
{
|
|
2935
|
+
type: "http",
|
|
2936
|
+
url: mcpUrl
|
|
2937
|
+
}
|
|
2938
|
+
]
|
|
2939
|
+
];
|
|
2940
|
+
for (const [path, key, server] of shapes) planned.push(toJSONPlan(target, path, (config) => toWithServer(config, key, server)));
|
|
2889
2941
|
return planned;
|
|
2890
2942
|
}
|
|
2943
|
+
/** How a client starts the MCP server this CLI runs, which needs hardfin on the PATH. */
|
|
2944
|
+
const LOCAL_SERVER = {
|
|
2945
|
+
command: "hardfin",
|
|
2946
|
+
args: ["mcp"]
|
|
2947
|
+
};
|
|
2948
|
+
/** toMcpParagraph tells an agent which MCP server the project is set up with, and where. */
|
|
2949
|
+
function toMcpParagraph(mcpUrl) {
|
|
2950
|
+
const where = "is configured for Claude Code in `.mcp.json`, for\nCursor in `.cursor/mcp.json`, and for VS Code in `.vscode/mcp.json`. For Codex, add\n`[mcp_servers.hardfin]` with";
|
|
2951
|
+
return mcpUrl === void 0 ? `The Hardfin MCP server runs on this machine as \`hardfin mcp\`. It ${where} \`command = "hardfin"\` and \`args = ["mcp"]\` to \`~/.codex/config.toml\`.` : `The Hardfin MCP server, \`${mcpUrl}\`, ${where} \`url = "${mcpUrl}"\` to \`~/.codex/config.toml\`.`;
|
|
2952
|
+
}
|
|
2891
2953
|
/** toAgentsFile puts the Hardfin section into AGENTS.md, replacing the one an earlier run wrote. */
|
|
2892
2954
|
function toAgentsFile(path, section) {
|
|
2893
2955
|
const block = `${SECTION_START}\n${section.trimEnd()}\n${SECTION_END}\n`;
|
|
@@ -7358,5 +7420,5 @@ async function toReported(error, isJSON, resolved, level = "error") {
|
|
|
7358
7420
|
//#endregion
|
|
7359
7421
|
export { toCli, toParseExitCode, toReported, wasReportAttempted, writeCrash };
|
|
7360
7422
|
|
|
7361
|
-
//# sourceMappingURL=program-
|
|
7362
|
-
//# debugId=
|
|
7423
|
+
//# sourceMappingURL=program-BP83nk1M.js.map
|
|
7424
|
+
//# debugId=5a81163a-f2c4-570b-9451-c1fad66921a0
|
package/package.json
CHANGED
package/templates/AGENTS.md
CHANGED
|
@@ -13,9 +13,7 @@ This project works with Hardfin data through the Hardfin CLI, `hardfin`.
|
|
|
13
13
|
|
|
14
14
|
Start with the `hardfin-cli` skill in `.agents/skills/hardfin-cli/SKILL.md`.
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
Cursor in `.cursor/mcp.json`, and for VS Code in `.vscode/mcp.json`. For Codex, add
|
|
18
|
-
`[mcp_servers.hardfin]` with `url = "{{MCP_URL}}"` to `~/.codex/config.toml`.
|
|
16
|
+
{{MCP}}
|
|
19
17
|
|
|
20
18
|
Rules:
|
|
21
19
|
|