@agentcred-ai/cli 0.1.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/LICENSE +21 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +273 -0
- package/package.json +55 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 AgentCred Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/commands/init.ts
|
|
4
|
+
import { parseArgs } from "util";
|
|
5
|
+
import { createIdentity, FileSystemKeyStorage } from "@agentcred-ai/sdk";
|
|
6
|
+
var HELP = `agentcred init \u2014 Initialize identity with GitHub token
|
|
7
|
+
|
|
8
|
+
Usage: agentcred init --token <github_token>
|
|
9
|
+
|
|
10
|
+
Options:
|
|
11
|
+
--token <token> GitHub personal access token (required)
|
|
12
|
+
--help, -h Show this help message`;
|
|
13
|
+
async function initCommand(args) {
|
|
14
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
15
|
+
console.log(HELP);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const { values } = parseArgs({
|
|
19
|
+
args,
|
|
20
|
+
options: {
|
|
21
|
+
token: { type: "string" }
|
|
22
|
+
},
|
|
23
|
+
strict: false
|
|
24
|
+
});
|
|
25
|
+
const token = values.token ?? process.env["AGENTCRED_GITHUB_TOKEN"];
|
|
26
|
+
if (!token) {
|
|
27
|
+
throw new Error("GitHub token required. Use --token <token> or set AGENTCRED_GITHUB_TOKEN");
|
|
28
|
+
}
|
|
29
|
+
if (typeof token !== "string") {
|
|
30
|
+
throw new Error("Invalid token: --token flag must be provided with a value");
|
|
31
|
+
}
|
|
32
|
+
const storage = new FileSystemKeyStorage();
|
|
33
|
+
const identity = await createIdentity(token, { storage });
|
|
34
|
+
console.log(`\u2713 Identity created for @${identity.github.username}`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// src/commands/sign.ts
|
|
38
|
+
import { parseArgs as parseArgs2 } from "util";
|
|
39
|
+
import * as fs from "fs/promises";
|
|
40
|
+
import { loadIdentity, sign, FileSystemKeyStorage as FileSystemKeyStorage2 } from "@agentcred-ai/sdk";
|
|
41
|
+
var HELP2 = `agentcred sign \u2014 Sign content with your AgentCred identity
|
|
42
|
+
|
|
43
|
+
Usage: agentcred sign [file] [options]
|
|
44
|
+
cat file.txt | agentcred sign
|
|
45
|
+
|
|
46
|
+
Options:
|
|
47
|
+
--agent <name> Agent name (default: "default")
|
|
48
|
+
--help, -h Show this help message
|
|
49
|
+
|
|
50
|
+
If no file is given, reads from stdin.`;
|
|
51
|
+
async function readStdin() {
|
|
52
|
+
const chunks = [];
|
|
53
|
+
for await (const chunk of process.stdin) {
|
|
54
|
+
chunks.push(chunk);
|
|
55
|
+
}
|
|
56
|
+
return Buffer.concat(chunks).toString("utf-8");
|
|
57
|
+
}
|
|
58
|
+
async function signCommand(args) {
|
|
59
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
60
|
+
console.log(HELP2);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const { values, positionals } = parseArgs2({
|
|
64
|
+
args,
|
|
65
|
+
options: {
|
|
66
|
+
agent: { type: "string" }
|
|
67
|
+
},
|
|
68
|
+
allowPositionals: true,
|
|
69
|
+
strict: false
|
|
70
|
+
});
|
|
71
|
+
const filePath = positionals[0];
|
|
72
|
+
let content;
|
|
73
|
+
if (filePath) {
|
|
74
|
+
content = await fs.readFile(filePath, "utf-8");
|
|
75
|
+
} else if (!process.stdin.isTTY) {
|
|
76
|
+
content = await readStdin();
|
|
77
|
+
} else {
|
|
78
|
+
throw new Error("No input provided. Pass a file argument or pipe content via stdin.");
|
|
79
|
+
}
|
|
80
|
+
const storage = new FileSystemKeyStorage2();
|
|
81
|
+
const usernames = await storage.list();
|
|
82
|
+
if (usernames.length === 0) {
|
|
83
|
+
throw new Error("No identity found. Run 'agentcred init' first.");
|
|
84
|
+
}
|
|
85
|
+
const username = usernames[0];
|
|
86
|
+
const loaded = await loadIdentity(username, { storage });
|
|
87
|
+
if (!loaded) {
|
|
88
|
+
throw new Error("No identity found. Run 'agentcred init' first.");
|
|
89
|
+
}
|
|
90
|
+
const envelope = await sign(content, {
|
|
91
|
+
privateKey: loaded.privateKey,
|
|
92
|
+
github: username
|
|
93
|
+
}, { agent: values.agent });
|
|
94
|
+
console.log(JSON.stringify(envelope, null, 2));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// src/commands/verify.ts
|
|
98
|
+
import { parseArgs as parseArgs3 } from "util";
|
|
99
|
+
import * as fs2 from "fs/promises";
|
|
100
|
+
import { verify, verifyOffline } from "@agentcred-ai/sdk";
|
|
101
|
+
import { importJWK } from "jose";
|
|
102
|
+
var HELP3 = `agentcred verify \u2014 Verify an AgentCred envelope
|
|
103
|
+
|
|
104
|
+
Usage: agentcred verify [file] [options]
|
|
105
|
+
cat envelope.json | agentcred verify
|
|
106
|
+
|
|
107
|
+
Options:
|
|
108
|
+
--offline Verify offline using a local public key
|
|
109
|
+
--key <path> Path to public key JWK file (used with --offline)
|
|
110
|
+
--help, -h Show this help message
|
|
111
|
+
|
|
112
|
+
If no file is given, reads from stdin.`;
|
|
113
|
+
async function readStdin2() {
|
|
114
|
+
const chunks = [];
|
|
115
|
+
for await (const chunk of process.stdin) {
|
|
116
|
+
chunks.push(chunk);
|
|
117
|
+
}
|
|
118
|
+
return Buffer.concat(chunks).toString("utf-8");
|
|
119
|
+
}
|
|
120
|
+
async function verifyCommand(args) {
|
|
121
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
122
|
+
console.log(HELP3);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const { values, positionals } = parseArgs3({
|
|
126
|
+
args,
|
|
127
|
+
options: {
|
|
128
|
+
offline: { type: "boolean", default: false },
|
|
129
|
+
key: { type: "string" }
|
|
130
|
+
},
|
|
131
|
+
allowPositionals: true,
|
|
132
|
+
strict: false
|
|
133
|
+
});
|
|
134
|
+
const filePath = positionals[0];
|
|
135
|
+
let input;
|
|
136
|
+
if (filePath) {
|
|
137
|
+
input = await fs2.readFile(filePath, "utf-8");
|
|
138
|
+
} else if (!process.stdin.isTTY) {
|
|
139
|
+
input = await readStdin2();
|
|
140
|
+
} else {
|
|
141
|
+
throw new Error("No input provided. Pass a file argument or pipe content via stdin.");
|
|
142
|
+
}
|
|
143
|
+
let envelope;
|
|
144
|
+
try {
|
|
145
|
+
envelope = JSON.parse(input);
|
|
146
|
+
} catch {
|
|
147
|
+
throw new Error("Invalid JSON input. Expected an AgentCred envelope.");
|
|
148
|
+
}
|
|
149
|
+
if (!envelope.agentcred?.jws) {
|
|
150
|
+
throw new Error("Invalid envelope: missing agentcred.jws field.");
|
|
151
|
+
}
|
|
152
|
+
if (values.offline) {
|
|
153
|
+
if (!values.key) {
|
|
154
|
+
throw new Error("--key <path> is required when using --offline");
|
|
155
|
+
}
|
|
156
|
+
if (typeof values.key !== "string") {
|
|
157
|
+
throw new Error("Invalid key: --key flag must be provided with a file path");
|
|
158
|
+
}
|
|
159
|
+
const keyData = await fs2.readFile(values.key, "utf-8");
|
|
160
|
+
const publicJWK = JSON.parse(keyData);
|
|
161
|
+
const publicKey = await importJWK(publicJWK, "EdDSA");
|
|
162
|
+
const result = await verifyOffline(envelope, publicKey);
|
|
163
|
+
if (result.verified) {
|
|
164
|
+
console.log(`\u2713 Verified: @${result.github?.username} (${result.agent}) at ${result.signedAt}`);
|
|
165
|
+
} else {
|
|
166
|
+
console.error(`\u2717 Verification failed: ${result.error}`);
|
|
167
|
+
process.exit(1);
|
|
168
|
+
}
|
|
169
|
+
} else {
|
|
170
|
+
const result = await verify(envelope);
|
|
171
|
+
if (result.verified) {
|
|
172
|
+
console.log(`\u2713 Verified: @${result.github?.username} (${result.agent}) at ${result.signedAt}`);
|
|
173
|
+
} else {
|
|
174
|
+
console.error(`\u2717 Verification failed: ${result.error}`);
|
|
175
|
+
process.exit(1);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// src/commands/whoami.ts
|
|
181
|
+
import { FileSystemKeyStorage as FileSystemKeyStorage3 } from "@agentcred-ai/sdk";
|
|
182
|
+
import { createHash } from "crypto";
|
|
183
|
+
import * as fs3 from "fs/promises";
|
|
184
|
+
import * as path from "path";
|
|
185
|
+
import * as os from "os";
|
|
186
|
+
var HELP4 = `agentcred whoami \u2014 Show current identity
|
|
187
|
+
|
|
188
|
+
Usage: agentcred whoami
|
|
189
|
+
|
|
190
|
+
Options:
|
|
191
|
+
--help, -h Show this help message`;
|
|
192
|
+
async function whoamiCommand(args) {
|
|
193
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
194
|
+
console.log(HELP4);
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
const storage = new FileSystemKeyStorage3();
|
|
198
|
+
const usernames = await storage.list();
|
|
199
|
+
if (usernames.length === 0) {
|
|
200
|
+
throw new Error("No identity configured. Run 'agentcred init' first.");
|
|
201
|
+
}
|
|
202
|
+
const username = usernames[0];
|
|
203
|
+
const keyDir = path.join(os.homedir(), ".agentcred", "keys");
|
|
204
|
+
const keyPath = path.join(keyDir, `${username}.jwk`);
|
|
205
|
+
try {
|
|
206
|
+
const keyData = await fs3.readFile(keyPath, "utf-8");
|
|
207
|
+
const privateJWK = JSON.parse(keyData);
|
|
208
|
+
const { d: _d, ...publicPortion } = privateJWK;
|
|
209
|
+
const fingerprint = createHash("sha256").update(JSON.stringify(publicPortion)).digest("hex").slice(0, 16);
|
|
210
|
+
console.log(`You are @${username} (fingerprint: ${fingerprint})`);
|
|
211
|
+
} catch {
|
|
212
|
+
throw new Error("No identity configured. Run 'agentcred init' first.");
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// src/index.ts
|
|
217
|
+
var version = "0.0.1";
|
|
218
|
+
var HELP5 = `agentcred v${version} \u2014 Human accountability badge for AI agents
|
|
219
|
+
|
|
220
|
+
Usage: agentcred <command> [options]
|
|
221
|
+
|
|
222
|
+
Commands:
|
|
223
|
+
init Initialize identity with GitHub token
|
|
224
|
+
sign Sign content (file or stdin)
|
|
225
|
+
verify Verify an AgentCred envelope (file or stdin)
|
|
226
|
+
whoami Show current identity
|
|
227
|
+
|
|
228
|
+
Options:
|
|
229
|
+
--help, -h Show this help message
|
|
230
|
+
--version, -v Show version
|
|
231
|
+
|
|
232
|
+
Run 'agentcred <command> --help' for command-specific help.`;
|
|
233
|
+
var commands = {
|
|
234
|
+
init: initCommand,
|
|
235
|
+
sign: signCommand,
|
|
236
|
+
verify: verifyCommand,
|
|
237
|
+
whoami: whoamiCommand
|
|
238
|
+
};
|
|
239
|
+
async function main() {
|
|
240
|
+
const args = process.argv.slice(2);
|
|
241
|
+
if (args.length === 0 || args.includes("--help") || args.includes("-h")) {
|
|
242
|
+
if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
|
|
243
|
+
console.log(HELP5);
|
|
244
|
+
process.exit(0);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
if (args.includes("--version") || args.includes("-v")) {
|
|
248
|
+
console.log(version);
|
|
249
|
+
process.exit(0);
|
|
250
|
+
}
|
|
251
|
+
const commandName = args[0];
|
|
252
|
+
const commandArgs = args.slice(1);
|
|
253
|
+
const command = commands[commandName];
|
|
254
|
+
if (!command) {
|
|
255
|
+
console.error(`Unknown command: ${commandName}`);
|
|
256
|
+
console.error(`Run 'agentcred --help' for available commands.`);
|
|
257
|
+
process.exit(1);
|
|
258
|
+
}
|
|
259
|
+
try {
|
|
260
|
+
await command(commandArgs);
|
|
261
|
+
} catch (error) {
|
|
262
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
263
|
+
console.error(`\u2717 ${message}`);
|
|
264
|
+
process.exit(1);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
if (!process.env["VITEST"]) {
|
|
268
|
+
main();
|
|
269
|
+
}
|
|
270
|
+
export {
|
|
271
|
+
main,
|
|
272
|
+
version
|
|
273
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agentcred-ai/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "CLI tool for AgentCred developer workflows",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"agentcred": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"main": "./dist/index.js",
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"files": [
|
|
18
|
+
"dist"
|
|
19
|
+
],
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"jose": "^6.1.3",
|
|
22
|
+
"@agentcred-ai/sdk": "0.1.0"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@types/node": "^25.1.0",
|
|
26
|
+
"tsup": "^8.0.0",
|
|
27
|
+
"typescript": "^5.8.0",
|
|
28
|
+
"vitest": "^3.0.0"
|
|
29
|
+
},
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "https://github.com/agentcred-ai/agentcred",
|
|
34
|
+
"directory": "packages/cli"
|
|
35
|
+
},
|
|
36
|
+
"homepage": "https://agentcred.dev",
|
|
37
|
+
"bugs": {
|
|
38
|
+
"url": "https://github.com/agentcred-ai/agentcred/issues"
|
|
39
|
+
},
|
|
40
|
+
"keywords": [
|
|
41
|
+
"agentcred",
|
|
42
|
+
"ai-agent",
|
|
43
|
+
"mcp",
|
|
44
|
+
"cryptography",
|
|
45
|
+
"ed25519",
|
|
46
|
+
"identity",
|
|
47
|
+
"signature"
|
|
48
|
+
],
|
|
49
|
+
"author": "AgentCred Contributors",
|
|
50
|
+
"scripts": {
|
|
51
|
+
"build": "tsup",
|
|
52
|
+
"test": "vitest run",
|
|
53
|
+
"typecheck": "tsc --noEmit"
|
|
54
|
+
}
|
|
55
|
+
}
|