argsbarg 4.1.0 → 4.1.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/CHANGELOG.md +48 -1
- package/README.md +90 -84
- package/docs/README.md +6 -6
- package/docs/bundled-docs.md +1 -1
- package/docs/cli-program.md +5 -3
- package/docs/config-schema.md +36 -9
- package/docs/developing.md +7 -7
- package/docs/distribution-homebrew.md +103 -0
- package/docs/install.md +105 -189
- package/docs/mcp.md +2 -3
- package/docs/output-schema.md +1 -1
- package/examples/full-example/Formula/.gitkeep +0 -0
- package/examples/full-example/README.md +98 -0
- package/examples/full-example/biome.json +22 -0
- package/examples/{consumer-app → full-example}/bun.lock +2 -0
- package/examples/full-example/justfile +134 -0
- package/examples/{consumer-app → full-example}/package.json +10 -3
- package/examples/{consumer-app → full-example}/schemas/generated/app-config.json +1 -1
- package/examples/{consumer-app → full-example}/schemas/generated/status.json +1 -1
- package/examples/full-example/scripts/create-identity.ts +11 -0
- package/examples/full-example/scripts/formula-shared.ts +73 -0
- package/examples/full-example/scripts/gen-dev-formula.ts +26 -0
- package/examples/full-example/scripts/print-identity.ts +27 -0
- package/examples/full-example/src/commands/echo/command.ts +21 -0
- package/examples/full-example/src/commands/status/command.test.ts +10 -0
- package/examples/full-example/src/commands/status/command.ts +36 -0
- package/examples/{consumer-app → full-example}/src/commands/status/types.ts +1 -1
- package/examples/full-example/src/index.ts +10 -0
- package/examples/full-example/src/program.ts +57 -0
- package/examples/{consumer-app → full-example}/src/types.ts +1 -1
- package/examples/nested.ts +1 -3
- package/index.d.ts +27 -66
- package/package.json +2 -2
- package/src/builtins/builtins.test.ts +22 -23
- package/src/builtins/completion-group.ts +17 -15
- package/src/builtins/dispatch.ts +25 -1
- package/src/builtins/install.ts +22 -52
- package/src/builtins/registry.ts +2 -0
- package/src/builtins/uninstall.ts +80 -0
- package/src/capabilities.ts +1 -3
- package/src/cli-tool/cli-smoke.test.ts +19 -0
- package/src/cli-tool/create.test.ts +119 -0
- package/src/cli-tool/create.ts +380 -0
- package/{examples/consumer-app/capabilities.test.ts → src/cli-tool/full-example-capabilities.test.ts} +15 -14
- package/src/cli-tool/main.ts +8 -0
- package/src/cli-tool/post-create.ts +111 -0
- package/src/cli-tool/program.ts +82 -0
- package/src/cli-tool/prompt.ts +28 -0
- package/src/cli-tool/run-create.ts +149 -0
- package/src/cli.ts +0 -2
- package/src/config/bootstrap.ts +16 -9
- package/src/config/resolve.test.ts +167 -0
- package/src/config/resolve.ts +50 -6
- package/src/docs/api-guide.test.ts +4 -5
- package/src/docs/docs.test.ts +2 -1
- package/src/docs/mcp-guide.ts +7 -8
- package/src/index.ts +3 -10
- package/src/install/binary-placement.test.ts +101 -0
- package/src/install/binary-placement.ts +47 -0
- package/src/install/index.ts +117 -123
- package/src/install/install.test.ts +89 -105
- package/src/install/normalize-uninstall.ts +11 -0
- package/src/install/normalize.ts +4 -19
- package/src/install/paths.ts +0 -22
- package/src/install/plan.ts +14 -6
- package/src/install/shell.ts +0 -14
- package/src/install/status.test.ts +6 -6
- package/src/install/status.ts +0 -6
- package/src/install/target-effective.ts +0 -2
- package/src/install/target-scope.ts +15 -28
- package/src/install/target-types.ts +0 -16
- package/src/install/targets/app.ts +19 -28
- package/src/install/targets/configure.ts +5 -1
- package/src/install/targets/index.ts +0 -3
- package/src/install/targets.test.ts +24 -42
- package/src/mcp/env.test.ts +92 -0
- package/src/mcp/env.ts +15 -14
- package/src/parse.test.ts +3 -2
- package/src/prompt.ts +10 -0
- package/src/schema.ts +9 -1
- package/src/types.ts +27 -9
- package/src/validate.ts +5 -11
- package/docs/templates/cursor/rules/cli-program.mdc +0 -31
- package/examples/config-app/main.ts +0 -20
- package/examples/config-app/program.ts +0 -78
- package/examples/config-app/schema.ts +0 -37
- package/examples/config-app/types.ts +0 -19
- package/examples/consumer-app/README.md +0 -56
- package/examples/consumer-app/src/main.ts +0 -15
- package/examples/consumer-app/src/program.ts +0 -108
- package/src/install/app.ts +0 -94
- package/src/install/bootstrap.ts +0 -22
- package/src/install/completions.ts +0 -56
- package/src/install/targets/completions.ts +0 -133
- package/src/install/update.test.ts +0 -123
- package/src/install/update.ts +0 -54
- /package/examples/{consumer-app → full-example}/schemas/configSchemas.ts +0 -0
- /package/examples/{consumer-app → full-example}/schemas/outputSchemas.ts +0 -0
- /package/examples/{consumer-app → full-example}/scripts/schemagen/discover-schema-roots.test.ts +0 -0
- /package/examples/{consumer-app → full-example}/scripts/schemagen/discover-schema-roots.ts +0 -0
- /package/examples/{consumer-app → full-example}/scripts/schemagen/naming.ts +0 -0
- /package/examples/{consumer-app → full-example}/scripts/schemagen.ts +0 -0
- /package/examples/{consumer-app → full-example}/tsconfig.json +0 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
set shell := ["bash", "-eu", "-o", "pipefail", "-c"]
|
|
2
|
+
|
|
3
|
+
HOMEBREW_NO_AUTO_UPDATE := "1"
|
|
4
|
+
HOMEBREW_NO_INSTALL_CLEANUP := "1"
|
|
5
|
+
HOMEBREW_NO_ENV_HINTS := "1"
|
|
6
|
+
|
|
7
|
+
cli_key := `bun scripts/print-identity.ts key`
|
|
8
|
+
tap_org := `bun scripts/print-identity.ts tapOrg`
|
|
9
|
+
tap_repo := `bun scripts/print-identity.ts tapRepo`
|
|
10
|
+
tap := `bun scripts/print-identity.ts tap`
|
|
11
|
+
brew_prefix := `brew --prefix`
|
|
12
|
+
tap_parent := brew_prefix + "/Library/Taps/" + tap_org
|
|
13
|
+
tap_path := tap_parent + "/homebrew-" + tap_repo
|
|
14
|
+
|
|
15
|
+
# List available recipes (default)
|
|
16
|
+
_:
|
|
17
|
+
@just --list
|
|
18
|
+
|
|
19
|
+
# Compile the CLI binary to dist/full-example
|
|
20
|
+
build:
|
|
21
|
+
bun build ./src/index.ts --compile --outfile=dist/{{cli_key}}
|
|
22
|
+
@rm -f .*.bun-build
|
|
23
|
+
|
|
24
|
+
# Run schemagen, git diff check, typecheck, and format
|
|
25
|
+
check: schemagen
|
|
26
|
+
git diff --exit-code schemas/
|
|
27
|
+
just typecheck
|
|
28
|
+
just format
|
|
29
|
+
|
|
30
|
+
# Run the CLI from source with optional args; restarts on file changes
|
|
31
|
+
dev *ARGS:
|
|
32
|
+
bun --watch ./src/index.ts {{ARGS}}
|
|
33
|
+
|
|
34
|
+
# Regenerate docs/schema.json and docs/skill.md
|
|
35
|
+
docgen: schemagen
|
|
36
|
+
@just run docs schema --save
|
|
37
|
+
@just run docs skill --save
|
|
38
|
+
|
|
39
|
+
alias fmt := format
|
|
40
|
+
|
|
41
|
+
# Format and lint sources (auto-fix)
|
|
42
|
+
format:
|
|
43
|
+
bun run biome check ./src ./scripts --write
|
|
44
|
+
|
|
45
|
+
# Alias for backward compatibility
|
|
46
|
+
install: install-local
|
|
47
|
+
|
|
48
|
+
# Refresh skills and MCP without reinstalling the formula
|
|
49
|
+
install-artifacts:
|
|
50
|
+
{{cli_key}} install --reinstall --yes
|
|
51
|
+
|
|
52
|
+
# Dev install: build, write dev formula, symlink tap, brew install
|
|
53
|
+
install-local: build
|
|
54
|
+
@bun scripts/gen-dev-formula.ts
|
|
55
|
+
@brew untap {{tap}} 2>/dev/null || true
|
|
56
|
+
mkdir -p {{tap_parent}}
|
|
57
|
+
ln -sfn '{{justfile_directory()}}' {{tap_path}}
|
|
58
|
+
brew install --formula {{tap}}/{{cli_key}}
|
|
59
|
+
@echo ""
|
|
60
|
+
@echo "Next: {{cli_key}} install --configure"
|
|
61
|
+
|
|
62
|
+
# Remove local dev install, then install from GitHub tap
|
|
63
|
+
install-production: uninstall
|
|
64
|
+
brew tap {{tap}}
|
|
65
|
+
brew install --formula {{tap}}/{{cli_key}}
|
|
66
|
+
@echo ""
|
|
67
|
+
@echo "Next: {{cli_key}} install --configure"
|
|
68
|
+
|
|
69
|
+
# Alias for backward compatibility
|
|
70
|
+
reinstall: reinstall-local
|
|
71
|
+
|
|
72
|
+
# Rebuild binary and swap into Cellar (run install-local first)
|
|
73
|
+
reinstall-local: build
|
|
74
|
+
install -m 755 dist/{{cli_key}} "$(brew --prefix {{cli_key}})/bin/{{cli_key}}"
|
|
75
|
+
|
|
76
|
+
# Lint sources without writing
|
|
77
|
+
lint:
|
|
78
|
+
bun run biome check ./src ./scripts
|
|
79
|
+
|
|
80
|
+
# Run the CLI from source once
|
|
81
|
+
run *ARGS:
|
|
82
|
+
bun ./src/index.ts {{ARGS}}
|
|
83
|
+
|
|
84
|
+
# Generate JSON Schema artifacts from TypeScript types
|
|
85
|
+
schemagen:
|
|
86
|
+
bun run schemagen
|
|
87
|
+
just format
|
|
88
|
+
|
|
89
|
+
# Install bun/npm dependencies
|
|
90
|
+
setup:
|
|
91
|
+
bun install
|
|
92
|
+
|
|
93
|
+
# Run unit tests (after check)
|
|
94
|
+
test: check
|
|
95
|
+
bun test .
|
|
96
|
+
|
|
97
|
+
# Install release formula from tap and run formula test
|
|
98
|
+
test-release:
|
|
99
|
+
@brew untap {{tap}} 2>/dev/null || true
|
|
100
|
+
mkdir -p {{tap_parent}}
|
|
101
|
+
ln -sfn '{{justfile_directory()}}' {{tap_path}}
|
|
102
|
+
@brew uninstall --formula {{tap}}/{{cli_key}} 2>/dev/null || true
|
|
103
|
+
brew install --formula {{tap}}/{{cli_key}}
|
|
104
|
+
brew test {{cli_key}}
|
|
105
|
+
|
|
106
|
+
# Typecheck without emitting build artifacts
|
|
107
|
+
typecheck:
|
|
108
|
+
bun run tsc --noEmit
|
|
109
|
+
|
|
110
|
+
# Undo just install-local: agent artifacts first, then formula
|
|
111
|
+
uninstall: uninstall-artifacts uninstall-formula
|
|
112
|
+
|
|
113
|
+
# Remove agent artifacts only (skills, MCP)
|
|
114
|
+
uninstall-artifacts:
|
|
115
|
+
{{cli_key}} uninstall --yes
|
|
116
|
+
|
|
117
|
+
# Remove app config file only
|
|
118
|
+
uninstall-config:
|
|
119
|
+
{{cli_key}} uninstall --configure --yes
|
|
120
|
+
|
|
121
|
+
# Remove formula and untap
|
|
122
|
+
uninstall-formula:
|
|
123
|
+
@brew uninstall --formula {{tap}}/{{cli_key}} 2>/dev/null || true
|
|
124
|
+
@brew uninstall --formula {{tap}}/{{cli_key}}-local 2>/dev/null || true
|
|
125
|
+
@brew untap {{tap}} 2>/dev/null || true
|
|
126
|
+
|
|
127
|
+
# Remove release formula (does not untap)
|
|
128
|
+
uninstall-release:
|
|
129
|
+
@brew uninstall --formula {{tap}}/{{cli_key}} 2>/dev/null || true
|
|
130
|
+
|
|
131
|
+
# Remove release formula and untap
|
|
132
|
+
uninstall-release-tap:
|
|
133
|
+
@brew uninstall --formula {{tap}}/{{cli_key}} 2>/dev/null || true
|
|
134
|
+
@brew untap {{tap}} 2>/dev/null || true
|
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "
|
|
2
|
+
"name": "full-example",
|
|
3
3
|
"private": true,
|
|
4
4
|
"type": "module",
|
|
5
|
-
"
|
|
5
|
+
"module": "src/index.ts",
|
|
6
|
+
"description": "Argsbarg full example reference app (copy template; not published to npm).",
|
|
7
|
+
"engines": {
|
|
8
|
+
"bun": ">=1.3"
|
|
9
|
+
},
|
|
6
10
|
"scripts": {
|
|
11
|
+
"biome": "biome",
|
|
7
12
|
"schemagen": "bun run scripts/schemagen.ts",
|
|
8
|
-
"start": "bun run src/
|
|
13
|
+
"start": "bun run src/index.ts"
|
|
9
14
|
},
|
|
10
15
|
"dependencies": {
|
|
11
16
|
"argsbarg": "file:../.."
|
|
12
17
|
},
|
|
13
18
|
"devDependencies": {
|
|
19
|
+
"@biomejs/biome": "^2.5.0",
|
|
20
|
+
"@types/bun": "^1.3.12",
|
|
14
21
|
"ts-json-schema-generator": "^2.3.0",
|
|
15
22
|
"typescript": "^5.9.3"
|
|
16
23
|
}
|
|
@@ -35,6 +35,6 @@
|
|
|
35
35
|
"maxRetries"
|
|
36
36
|
],
|
|
37
37
|
"additionalProperties": false,
|
|
38
|
-
"description": "Config schema\n\nApplication settings for `
|
|
38
|
+
"description": "Config schema\n\nApplication settings for `full-example` (`program.appConfig`).",
|
|
39
39
|
"definitions": {}
|
|
40
40
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** CLI identity — substituted by `argsbarg create`. */
|
|
2
|
+
|
|
3
|
+
export const createIdentity = {
|
|
4
|
+
key: "full-example",
|
|
5
|
+
className: "FullExample",
|
|
6
|
+
tap: "local/full-example",
|
|
7
|
+
homepage: "https://github.com/bdombro/bun-argsbarg",
|
|
8
|
+
releaseRepo: "bdombro/bun-argsbarg",
|
|
9
|
+
desc: "Argsbarg full example reference app",
|
|
10
|
+
envPrefix: "FULL_EXAMPLE",
|
|
11
|
+
} as const;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/** Shared Ruby fragments embedded in Homebrew formulae. */
|
|
2
|
+
|
|
3
|
+
import { createIdentity } from "./create-identity.ts";
|
|
4
|
+
|
|
5
|
+
const { key, className, desc, homepage, releaseRepo } = createIdentity;
|
|
6
|
+
|
|
7
|
+
export const formulaInstallRuby = `def install
|
|
8
|
+
bin.install "${key}"
|
|
9
|
+
chmod 0755, bin/"${key}"
|
|
10
|
+
generate_completions_from_executable(bin/"${key}", "completion", base_name: "${key}")
|
|
11
|
+
end`;
|
|
12
|
+
|
|
13
|
+
export const formulaPostInstallRuby = `def post_install
|
|
14
|
+
system bin/"${key}", "install", "--reinstall", "--yes"
|
|
15
|
+
end`;
|
|
16
|
+
|
|
17
|
+
export const formulaCaveatsRuby = `def caveats
|
|
18
|
+
<<~EOS
|
|
19
|
+
Run \`${key} install --configure\` to set up app config (interactive).
|
|
20
|
+
EOS
|
|
21
|
+
end`;
|
|
22
|
+
|
|
23
|
+
export const formulaTestRuby = `test do
|
|
24
|
+
assert_match version.to_s, shell_output("#{bin}/${key} version")
|
|
25
|
+
assert_predicate bash_completion/"${key}", :exist?
|
|
26
|
+
assert_predicate zsh_completion/"_${key}", :exist?
|
|
27
|
+
assert_predicate fish_completion/"${key}.fish", :exist?
|
|
28
|
+
end`;
|
|
29
|
+
|
|
30
|
+
export interface FormulaCoords {
|
|
31
|
+
url: string;
|
|
32
|
+
version: string;
|
|
33
|
+
sha256: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function releaseFormulaUrl(version: string): string {
|
|
37
|
+
return `https://github.com/${releaseRepo}/releases/download/v${version}/${key}`;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function renderFormula(coords: FormulaCoords): string {
|
|
41
|
+
return `class ${className} < Formula
|
|
42
|
+
desc "${desc}"
|
|
43
|
+
homepage "${homepage}"
|
|
44
|
+
url "${coords.url}"
|
|
45
|
+
version "${coords.version}"
|
|
46
|
+
sha256 "${coords.sha256}"
|
|
47
|
+
{dependsOnBlock}
|
|
48
|
+
${formulaInstallRuby}
|
|
49
|
+
|
|
50
|
+
${formulaPostInstallRuby}
|
|
51
|
+
|
|
52
|
+
${formulaCaveatsRuby}
|
|
53
|
+
|
|
54
|
+
${formulaTestRuby}
|
|
55
|
+
end
|
|
56
|
+
`;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function renderReleaseFormula(version: string, sha256: string): string {
|
|
60
|
+
return renderFormula({
|
|
61
|
+
url: releaseFormulaUrl(version),
|
|
62
|
+
version,
|
|
63
|
+
sha256,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function renderDevFormula(stagingPath: string, version: string, sha256: string): string {
|
|
68
|
+
return renderFormula({
|
|
69
|
+
url: `file://${stagingPath}`,
|
|
70
|
+
version,
|
|
71
|
+
sha256,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/** Generate Formula/full-example.rb for local dev install (same formula as release; file:// URL only). */
|
|
3
|
+
|
|
4
|
+
import { createHash } from "node:crypto";
|
|
5
|
+
import { chmodSync, copyFileSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
6
|
+
import { join } from "node:path";
|
|
7
|
+
import { createIdentity } from "./create-identity.ts";
|
|
8
|
+
import { renderDevFormula } from "./formula-shared.ts";
|
|
9
|
+
|
|
10
|
+
const { key } = createIdentity;
|
|
11
|
+
const root = join(import.meta.dir, "..");
|
|
12
|
+
const distPath = join(root, "dist", key);
|
|
13
|
+
const stagingDir = join(root, "Formula", ".staging");
|
|
14
|
+
const stagingPath = join(stagingDir, key);
|
|
15
|
+
|
|
16
|
+
mkdirSync(stagingDir, { recursive: true });
|
|
17
|
+
copyFileSync(distPath, stagingPath);
|
|
18
|
+
chmodSync(stagingPath, 0o755);
|
|
19
|
+
|
|
20
|
+
const binary = readFileSync(stagingPath);
|
|
21
|
+
const sha256 = createHash("sha256").update(binary).digest("hex");
|
|
22
|
+
const version = JSON.parse(readFileSync(join(root, "package.json"), "utf8")).version as string;
|
|
23
|
+
|
|
24
|
+
const out = join(root, "Formula", `${key}.rb`);
|
|
25
|
+
writeFileSync(out, renderDevFormula(stagingPath, version, sha256), "utf8");
|
|
26
|
+
console.log(`Wrote ${out}`);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/** Print a field from scripts/create-identity.ts for justfile backticks. */
|
|
3
|
+
|
|
4
|
+
import { createIdentity } from "./create-identity.ts";
|
|
5
|
+
|
|
6
|
+
const field = process.argv[2];
|
|
7
|
+
if (!field) {
|
|
8
|
+
console.error("Usage: bun scripts/print-identity.ts <key|className|tap|tapOrg|tapRepo|envPrefix>");
|
|
9
|
+
process.exit(1);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const [tapOrg, tapRepo] = createIdentity.tap.split("/");
|
|
13
|
+
const values: Record<string, string> = {
|
|
14
|
+
key: createIdentity.key,
|
|
15
|
+
className: createIdentity.className,
|
|
16
|
+
tap: createIdentity.tap,
|
|
17
|
+
tapOrg: tapOrg ?? "",
|
|
18
|
+
tapRepo: tapRepo ?? "",
|
|
19
|
+
envPrefix: createIdentity.envPrefix,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const value = values[field];
|
|
23
|
+
if (value === undefined) {
|
|
24
|
+
console.error(`Unknown field: ${field}`);
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
process.stdout.write(value);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Echo leaf — minimal MCP-friendly command.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { type CliLeaf, CliOptionKind } from "argsbarg";
|
|
6
|
+
|
|
7
|
+
export const echoCommand = {
|
|
8
|
+
key: "echo",
|
|
9
|
+
description: "Echo a message (MCP-friendly leaf).",
|
|
10
|
+
options: [
|
|
11
|
+
{
|
|
12
|
+
name: "message",
|
|
13
|
+
description: "Text to print.",
|
|
14
|
+
kind: CliOptionKind.String,
|
|
15
|
+
required: true,
|
|
16
|
+
},
|
|
17
|
+
],
|
|
18
|
+
handler: (ctx) => {
|
|
19
|
+
console.log(ctx.stringOpt("message") ?? "");
|
|
20
|
+
},
|
|
21
|
+
} satisfies CliLeaf;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { statusCommand } from "./command.ts";
|
|
3
|
+
|
|
4
|
+
describe("status command", () => {
|
|
5
|
+
test("exports outputSchema and json option", () => {
|
|
6
|
+
expect(statusCommand.key).toBe("status");
|
|
7
|
+
expect(statusCommand.outputSchema).toBeDefined();
|
|
8
|
+
expect(statusCommand.options?.some((o) => o.name === "json")).toBe(true);
|
|
9
|
+
});
|
|
10
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Status leaf — demonstrates outputSchema and ctx.appConfig.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { type CliLeaf, CliOptionKind } from "argsbarg";
|
|
6
|
+
import { STATUS_JSON_OUTPUT_SCHEMA } from "../../../schemas/outputSchemas.ts";
|
|
7
|
+
import type { StatusJsonOutput } from "./types.ts";
|
|
8
|
+
|
|
9
|
+
export const statusCommand = {
|
|
10
|
+
key: "status",
|
|
11
|
+
description: "Show resolved config and app version.",
|
|
12
|
+
options: [
|
|
13
|
+
{
|
|
14
|
+
name: "json",
|
|
15
|
+
description: "Emit JSON.",
|
|
16
|
+
kind: CliOptionKind.Presence,
|
|
17
|
+
},
|
|
18
|
+
],
|
|
19
|
+
outputSchema: STATUS_JSON_OUTPUT_SCHEMA,
|
|
20
|
+
handler: (ctx) => {
|
|
21
|
+
const out: StatusJsonOutput = {
|
|
22
|
+
defaultRegion: ctx.appConfig.get("defaultRegion") as string | undefined,
|
|
23
|
+
maxRetries: ctx.appConfig.get("maxRetries") as number | undefined,
|
|
24
|
+
apiTokenSet: ctx.appConfig.get("apiToken") !== undefined,
|
|
25
|
+
version: ctx.program.version,
|
|
26
|
+
};
|
|
27
|
+
if (ctx.hasFlag("json")) {
|
|
28
|
+
console.log(JSON.stringify(out, null, 2));
|
|
29
|
+
} else {
|
|
30
|
+
console.log(`version=${out.version}`);
|
|
31
|
+
console.log(`region=${out.defaultRegion ?? "(not set)"}`);
|
|
32
|
+
console.log(`maxRetries=${out.maxRetries ?? "(not set)"}`);
|
|
33
|
+
console.log(`apiToken=${out.apiTokenSet ? "set" : "missing"}`);
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
} satisfies CliLeaf;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Kitchen-sink CliProgram — every argsbarg builtin enabled; command registration only.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { CliAppConfig, CliAppConfigEntry, CliProgram } from "argsbarg";
|
|
6
|
+
import readmeText from "../README.md" with { type: "text" };
|
|
7
|
+
import { APP_CONFIG_JSON_SCHEMA } from "../schemas/configSchemas.ts";
|
|
8
|
+
import { createIdentity } from "../scripts/create-identity.ts";
|
|
9
|
+
import { echoCommand } from "./commands/echo/command.ts";
|
|
10
|
+
import { statusCommand } from "./commands/status/command.ts";
|
|
11
|
+
|
|
12
|
+
const configSchema = {
|
|
13
|
+
apiToken: {
|
|
14
|
+
description: "Create at https://example.com/settings/tokens",
|
|
15
|
+
env: `${createIdentity.envPrefix}_API_TOKEN`,
|
|
16
|
+
sensitive: true,
|
|
17
|
+
},
|
|
18
|
+
defaultRegion: {
|
|
19
|
+
description: "AWS region for API calls.",
|
|
20
|
+
required: false,
|
|
21
|
+
},
|
|
22
|
+
maxRetries: {
|
|
23
|
+
description: "HTTP retry count (0–10).",
|
|
24
|
+
required: false,
|
|
25
|
+
},
|
|
26
|
+
prefs: {
|
|
27
|
+
description: "Local cache preferences (not exported to env).",
|
|
28
|
+
required: false,
|
|
29
|
+
},
|
|
30
|
+
} as const satisfies Record<string, CliAppConfigEntry>;
|
|
31
|
+
|
|
32
|
+
export const program = {
|
|
33
|
+
key: createIdentity.key,
|
|
34
|
+
version: "1.0.0",
|
|
35
|
+
description: "Argsbarg full example — all builtins, schemagen, ctx.appConfig.",
|
|
36
|
+
appConfig: {
|
|
37
|
+
jsonSchema: APP_CONFIG_JSON_SCHEMA,
|
|
38
|
+
entries: configSchema,
|
|
39
|
+
} satisfies CliAppConfig,
|
|
40
|
+
docs: {
|
|
41
|
+
enabled: true,
|
|
42
|
+
topics: {
|
|
43
|
+
readme: {
|
|
44
|
+
text: readmeText,
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
mcpServer: {
|
|
49
|
+
enabled: true,
|
|
50
|
+
mcpd: true,
|
|
51
|
+
claudePlugin: true,
|
|
52
|
+
},
|
|
53
|
+
install: {
|
|
54
|
+
// Defaults: agentIntegration picks skill vs MCP for --all; configure is opt-in.
|
|
55
|
+
},
|
|
56
|
+
commands: [echoCommand, statusCommand],
|
|
57
|
+
} satisfies CliProgram;
|
package/examples/nested.ts
CHANGED
package/index.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
// Generated by dts-bundle-generator v9.5.1
|
|
2
2
|
|
|
3
|
+
/** Resolved absolute path to the app JSON config file (`~/.local/lib/<key>/config.json`). */
|
|
4
|
+
export declare function resolveAppConfigPath(program: CliProgram): string;
|
|
5
|
+
/** Human-readable config path for error messages (`~/…` when under home). */
|
|
6
|
+
export declare function displayAppConfigPath(program: CliProgram): string;
|
|
3
7
|
export type ResolvedConfig = Record<string, unknown>;
|
|
4
8
|
declare class EmptyAppConfigSnapshot {
|
|
5
9
|
private readonly program;
|
|
@@ -245,21 +249,24 @@ export interface CliMcpToolConfig {
|
|
|
245
249
|
*/
|
|
246
250
|
outputSchema?: Record<string, unknown>;
|
|
247
251
|
}
|
|
252
|
+
/** Context passed to {@link CliAppConfigEntry.resolve} for one config key. */
|
|
253
|
+
export interface CliAppConfigResolveContext {
|
|
254
|
+
/** Schema key being resolved. */
|
|
255
|
+
key: string;
|
|
256
|
+
/** Entry metadata for this key. */
|
|
257
|
+
entry: CliAppConfigEntry;
|
|
258
|
+
/** Program root (read-only). */
|
|
259
|
+
program: CliProgram;
|
|
260
|
+
/** Raw value from the config file, if any. */
|
|
261
|
+
fileValue: unknown;
|
|
262
|
+
/** Non-empty host env string when `entry.env` is set; otherwise `undefined`. */
|
|
263
|
+
envValue: string | undefined;
|
|
264
|
+
}
|
|
248
265
|
/**
|
|
249
|
-
*
|
|
266
|
+
* Optional fallback resolver for one config key (e.g. `gh auth token` when `GH_TOKEN` is unset).
|
|
267
|
+
* Return `undefined` to continue resolution (env, then default).
|
|
250
268
|
*/
|
|
251
|
-
export
|
|
252
|
-
/** Path to an executable binary to copy into the install location. */
|
|
253
|
-
path: string;
|
|
254
|
-
/** Release version of `path` (used for already-current checks and success messages). */
|
|
255
|
-
version?: string;
|
|
256
|
-
/** Called after reinstall completes (e.g. remove a temp download directory). */
|
|
257
|
-
cleanup?: () => void | Promise<void>;
|
|
258
|
-
}
|
|
259
|
-
/** Fetches the latest release binary for `install --update`. */
|
|
260
|
-
export type CliUpdateGetLatest = (ctx: {
|
|
261
|
-
version: string;
|
|
262
|
-
}) => Promise<CliUpdateArtifact>;
|
|
269
|
+
export type CliAppConfigResolveFn = (ctx: CliAppConfigResolveContext) => unknown;
|
|
263
270
|
/**
|
|
264
271
|
* Metadata overlay for one key in {@link CliAppConfig.entries}.
|
|
265
272
|
* Types and validation come from {@link CliAppConfig.jsonSchema} when set; otherwise all values are strings.
|
|
@@ -280,6 +287,11 @@ export interface CliAppConfigEntry {
|
|
|
280
287
|
sensitive?: boolean;
|
|
281
288
|
/** When set: non-empty `process.env[env]` overrides file; value exported after resolve. */
|
|
282
289
|
env?: string;
|
|
290
|
+
/**
|
|
291
|
+
* Optional fallback after file when env is empty.
|
|
292
|
+
* Return `undefined` to fall back to `env` (if set) and schema defaults.
|
|
293
|
+
*/
|
|
294
|
+
resolve?: CliAppConfigResolveFn;
|
|
283
295
|
}
|
|
284
296
|
/**
|
|
285
297
|
* App configuration block on the program root ({@link CliProgram.appConfig}).
|
|
@@ -307,11 +319,6 @@ export interface CliInstallConfig {
|
|
|
307
319
|
agentIntegration?: InstallAgentIntegration;
|
|
308
320
|
/** Per-artifact gates for full install/uninstall. See {@link resolveEffectiveInstallTargets}. */
|
|
309
321
|
targets?: CliInstallTargets;
|
|
310
|
-
/**
|
|
311
|
-
* When set, enables `install --update` on the program root.
|
|
312
|
-
* Should download or locate the latest release binary and return its path.
|
|
313
|
-
*/
|
|
314
|
-
updateGetLatest?: CliUpdateGetLatest;
|
|
315
322
|
}
|
|
316
323
|
/** Agent integration mode for install — MCP vs shell skill per host. */
|
|
317
324
|
export type InstallAgentIntegration = "mcp" | "skill" | "both";
|
|
@@ -328,7 +335,7 @@ export interface ResolvedInstallTarget {
|
|
|
328
335
|
}
|
|
329
336
|
/** Per-artifact gates for full install/uninstall. See {@link resolveEffectiveInstallTargets}. */
|
|
330
337
|
export interface CliInstallTargets {
|
|
331
|
-
/**
|
|
338
|
+
/** App binary status only (Homebrew PATH); no self-install. */
|
|
332
339
|
app?: InstallTargetSpec;
|
|
333
340
|
/** ChatGPT desktop MCP. Default false. */
|
|
334
341
|
chatgptMcp?: InstallTargetSpec;
|
|
@@ -342,9 +349,7 @@ export interface CliInstallTargets {
|
|
|
342
349
|
codexMcp?: InstallTargetSpec;
|
|
343
350
|
/** Codex skill. Default false. */
|
|
344
351
|
codexSkill?: InstallTargetSpec;
|
|
345
|
-
/**
|
|
346
|
-
completions?: InstallTargetSpec;
|
|
347
|
-
/** App config: wizard on install, file removal on uninstall. Default includedInAll true. */
|
|
352
|
+
/** App config: wizard via install --configure only. Default not in --all. */
|
|
348
353
|
configure?: InstallTargetSpec;
|
|
349
354
|
/** Cursor MCP. Default false. */
|
|
350
355
|
cursorMcp?: InstallTargetSpec;
|
|
@@ -465,7 +470,6 @@ export interface CliCapabilities {
|
|
|
465
470
|
mcp: boolean;
|
|
466
471
|
install: boolean;
|
|
467
472
|
docs: boolean;
|
|
468
|
-
update: boolean;
|
|
469
473
|
configCommands: boolean;
|
|
470
474
|
}
|
|
471
475
|
/** JSON-safe command node (no handlers). */
|
|
@@ -547,49 +551,6 @@ export declare function shouldRunHeadlessWithYes(ctx: HeadlessContext, opts: {
|
|
|
547
551
|
export declare function requireYesInNonTty(yes: boolean, hint: string, dryRun?: boolean, interactive?: boolean): void;
|
|
548
552
|
/** Prefixes a success message when running in dry-run mode. */
|
|
549
553
|
export declare function formatDryRunMessage(message: string, dryRun: boolean): string;
|
|
550
|
-
/** Config for {@link ghReleaseUpdateGetLatest}. */
|
|
551
|
-
export interface GhReleaseUpdateConfig {
|
|
552
|
-
/** GitHub `owner/repo` slug. */
|
|
553
|
-
repo: string;
|
|
554
|
-
/** Release asset filename (e.g. `myapp`). */
|
|
555
|
-
asset: string;
|
|
556
|
-
/** Temp directory name prefix for downloads. */
|
|
557
|
-
tempPrefix: string;
|
|
558
|
-
/** Path to the on-disk version-check cache JSON file. */
|
|
559
|
-
cachePath: string;
|
|
560
|
-
/** Optional hint when `gh auth` fails or no releases exist. */
|
|
561
|
-
repoEnvHint?: string;
|
|
562
|
-
}
|
|
563
|
-
/** Config for {@link createGhVersionCheck}. */
|
|
564
|
-
export interface GhVersionCheckConfig {
|
|
565
|
-
/** Installed semver string. */
|
|
566
|
-
currentVersion: string;
|
|
567
|
-
/** CLI command name for update notices (e.g. `qa`). */
|
|
568
|
-
commandName: string;
|
|
569
|
-
/** Path to the on-disk version-check cache JSON file. */
|
|
570
|
-
cachePath: string;
|
|
571
|
-
/** Cache TTL in milliseconds (default 24h). */
|
|
572
|
-
ttlMs?: number;
|
|
573
|
-
/** When true, skip background refresh (e.g. test subprocess). */
|
|
574
|
-
skipRefresh?: () => boolean;
|
|
575
|
-
/** When true, skip refresh because `gh` is unavailable. */
|
|
576
|
-
ghAvailable?: () => boolean;
|
|
577
|
-
/** Fetches latest release version via `gh`. */
|
|
578
|
-
fetchLatest: () => Promise<string>;
|
|
579
|
-
}
|
|
580
|
-
/** Returns whether the installed version matches the latest release. */
|
|
581
|
-
export declare function isAlreadyCurrent(current: string, latest: string): boolean;
|
|
582
|
-
/** Strips a leading `v` from a release tag. */
|
|
583
|
-
export declare function parseReleaseTag(tag: string): string;
|
|
584
|
-
/** Builds a `CliUpdateGetLatest` hook that downloads a release via `gh`. */
|
|
585
|
-
export declare function ghReleaseUpdateGetLatest(config: GhReleaseUpdateConfig): CliUpdateGetLatest;
|
|
586
|
-
/** Version-check cache helpers for summary notices and background refresh. */
|
|
587
|
-
export declare function createGhVersionCheck(config: GhVersionCheckConfig): {
|
|
588
|
-
getUpdateNotice: () => string | null;
|
|
589
|
-
refreshIfStale: () => void;
|
|
590
|
-
};
|
|
591
|
-
/** Shared `gh release view` fetcher for hooks and version-check refresh. */
|
|
592
|
-
export declare function createGhFetchLatest(config: Pick<GhReleaseUpdateConfig, "repo" | "repoEnvHint">): () => Promise<string>;
|
|
593
554
|
/** Resolved paths for `mcp bundle`. */
|
|
594
555
|
export interface McpBundlePaths {
|
|
595
556
|
binaryPath: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "argsbarg",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"engines": {
|
|
6
6
|
"bun": ">=1.3"
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"module": "./src/index.ts",
|
|
13
13
|
"types": "./index.d.ts",
|
|
14
14
|
"bin": {
|
|
15
|
-
"argsbarg": "src/
|
|
15
|
+
"argsbarg": "src/cli-tool/main.ts"
|
|
16
16
|
},
|
|
17
17
|
"exports": {
|
|
18
18
|
".": {
|