@stainlu/faam-cli 0.2.2 → 0.2.5

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 ADDED
@@ -0,0 +1,36 @@
1
+ # Changelog
2
+
3
+ ## 0.2.5 (2026-02-10)
4
+
5
+ - `faam init` now works with zero arguments — name auto-generates, description optional
6
+ - API no longer requires description for agent profile
7
+
8
+ ## 0.2.4 (2026-02-10)
9
+
10
+ - Fix CI workflow (pin pnpm version)
11
+
12
+ ## 0.2.3 (2026-02-10)
13
+
14
+ - Add npm badges, Security & Safety section, and install-skills docs to README
15
+ - Add SECURITY.md and CHANGELOG.md
16
+ - Add package metadata (homepage, author, bugs, funding, expanded keywords)
17
+ - Set up GitHub Actions for npm provenance attestation
18
+ - Fix license text in README (was incorrectly listed as MIT)
19
+
20
+ ## 0.2.2 (2026-02-09)
21
+
22
+ - Dynamic version display (reads from package.json)
23
+ - Fix `install-skills` authentication (use Bearer token)
24
+ - Rebrand rlp → faam across all CLI output
25
+
26
+ ## 0.2.1 (2026-02-09)
27
+
28
+ - Use Authorization header instead of query params for API requests
29
+
30
+ ## 0.2.0 (2026-02-08)
31
+
32
+ - Add `install-skills` command — download personalized skills from FAAM
33
+ - Add `config` command — manage agent card configuration
34
+ - All-in-one `init` command with auto-discovery and auto-sync
35
+ - Support for multiple agents: Claude Code, Codex, Cursor, OpenCode, Windsurf
36
+ - Auto-migration from `~/.rlp/` to `~/.faam/`
package/README.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # FAAM CLI
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/@stainlu/faam-cli)](https://www.npmjs.com/package/@stainlu/faam-cli)
4
+ [![license](https://img.shields.io/npm/l/@stainlu/faam-cli)](https://github.com/stainlu/faam/blob/main/apps/cli/LICENSE)
5
+ [![downloads](https://img.shields.io/npm/dm/@stainlu/faam-cli)](https://www.npmjs.com/package/@stainlu/faam-cli)
6
+ [![node](https://img.shields.io/node/v/@stainlu/faam-cli)](https://nodejs.org)
7
+
3
8
  **Make your local AI agent discoverable to the world.**
4
9
 
5
10
  Local AI agents like Claude Code, Codex, and Clawdbot have powerful skills but are invisible to others. Google's A2A (Agent-to-Agent) protocol defines `/.well-known/agent-card.json` for agent discovery, but local agents can't host their own files.
@@ -59,24 +64,27 @@ faam logout
59
64
 
60
65
  ### `faam init`
61
66
 
62
- Initialize your agent card with name, description, auto-discover skills, and sync to API.
67
+ Initialize your agent card, auto-discover skills, and sync to API. Works with zero arguments — name auto-generates from your account ID and description is optional.
63
68
 
64
69
  ```bash
65
- # Interactive mode (prompts for values)
70
+ # Zero-config (auto-generates name, no description)
66
71
  faam init
67
72
 
68
- # Non-interactive mode (for AI agents)
73
+ # With custom name
74
+ faam init --name "My AI Agent"
75
+
76
+ # With name and description
69
77
  faam init --name "My AI Agent" --description "What my agent does"
70
78
  ```
71
79
 
72
80
  Options:
73
- - `-n, --name <name>` - Agent name
74
- - `-d, --description <desc>` - Agent description
81
+ - `-n, --name <name>` - Agent name (default: `agent-<account_id>`)
82
+ - `-d, --description <desc>` - Agent description (optional)
75
83
  - `-o, --organization <org>` - Provider organization (optional)
76
84
  - `-f, --force` - Overwrite existing config file
77
85
 
78
86
  **Features:**
79
- - **Interactive mode**: If name/description not provided, prompts for values
87
+ - **Zero-config**: Run `faam init` with no arguments — name auto-generates, description is optional
80
88
  - **Auto-discovery**: Finds skills from `~/.claude/skills/`, `.claude/skills/`, etc.
81
89
  - **Auto-sync**: Immediately syncs to API when logged in
82
90
 
@@ -116,6 +124,31 @@ Options:
116
124
  - `-p, --path <directory>` - Custom skills directory path
117
125
  - `--no-delete` - Don't delete remote skills that are not in local
118
126
 
127
+ ### `faam install-skills`
128
+
129
+ Download your personalized skills from FAAM and save them locally. This is completely optional — it fetches SKILL.md files (plain markdown instructions) based on your profile and saves them to your agent's skills directory. No executable code is downloaded or run.
130
+
131
+ ```bash
132
+ # Install to default agents (Claude Code + Codex)
133
+ faam install-skills
134
+
135
+ # Install to a specific agent
136
+ faam install-skills --agent claude-code
137
+
138
+ # Install to project directory instead of global
139
+ faam install-skills --no-global
140
+
141
+ # Overwrite existing skills
142
+ faam install-skills --force
143
+ ```
144
+
145
+ Options:
146
+ - `--agent <name>` - Target agent (claude-code, codex, cursor, opencode, windsurf)
147
+ - `--no-global` - Install to project directory instead of `~/`
148
+ - `-f, --force` - Overwrite existing skill files
149
+
150
+ Supported agents: `claude-code`, `codex`, `cursor`, `opencode`, `windsurf`
151
+
119
152
  ### `faam status`
120
153
 
121
154
  Show current account and skills sync status.
@@ -206,10 +239,33 @@ Defines your agent card metadata. Create with `faam init` or edit directly:
206
239
 
207
240
  Skills can be defined in agent-card.json OR as SKILL.md files. If a skill ID exists in both, the SKILL.md file takes precedence.
208
241
 
242
+ ## Security & Safety
243
+
244
+ This CLI is fully open source ([Apache-2.0](./LICENSE)). Here's exactly what it does and doesn't do:
245
+
246
+ **Data stored locally** (`~/.faam/`):
247
+ - `config.json` — your account key and API URL
248
+ - `agent-card.json` — your agent card metadata
249
+
250
+ **What each command does**:
251
+ - `sync-skills` — reads SKILL.md files from your local skills directories and uploads their metadata (name, description, tags) to the FAAM API
252
+ - `install-skills` — downloads SKILL.md files (plain markdown, not executable code) from the FAAM API and saves them to your agent's skills directory. This is the same format used by Claude Code, Codex, and other agents for skill discovery. Skill installation is a standard pattern across AI coding agents.
253
+ - `init` / `config` — manage local JSON configuration and sync to the API
254
+ - `login` / `logout` — store or remove your account key locally
255
+
256
+ **What this CLI does NOT do**:
257
+ - Run any downloaded code or scripts
258
+ - Install system packages or dependencies
259
+ - Access files outside of `~/.faam/` and your agent's skills directories
260
+ - Send telemetry or analytics
261
+ - Run background processes or auto-update
262
+
263
+ See [SECURITY.md](./SECURITY.md) for our security policy.
264
+
209
265
  ## Migration from rlp-cli
210
266
 
211
267
  If you were using the previous `@stainlu/rlp-cli` package, the FAAM CLI will automatically migrate your config from `~/.rlp/` to `~/.faam/` on first run. No action required.
212
268
 
213
269
  ## License
214
270
 
215
- MIT
271
+ Apache-2.0
package/SECURITY.md ADDED
@@ -0,0 +1,53 @@
1
+ # Security Policy
2
+
3
+ ## Reporting Vulnerabilities
4
+
5
+ If you discover a security vulnerability, please report it via:
6
+
7
+ - **Email**: stainlu@newtype-ai.org
8
+ - **GitHub Issues**: https://github.com/stainlu/faam/issues (for non-sensitive issues)
9
+
10
+ We will acknowledge reports within 48 hours and aim to release fixes promptly.
11
+
12
+ ## Data Handling
13
+
14
+ ### What is stored locally
15
+
16
+ All data is stored in `~/.faam/` as plain JSON:
17
+
18
+ - `config.json` — account key and API URL
19
+ - `agent-card.json` — agent card metadata (name, description, skills list)
20
+
21
+ ### What is transmitted
22
+
23
+ - `sync-skills` sends skill metadata (name, description, tags) to `api.faam.io` over HTTPS
24
+ - `install-skills` downloads SKILL.md content (plain markdown) from `api.faam.io` over HTTPS
25
+ - All API requests use your account key for authentication via Bearer token
26
+
27
+ ### What is NOT transmitted
28
+
29
+ - File contents outside of SKILL.md files
30
+ - System information, environment variables, or telemetry
31
+ - Any data without explicit user action (no background processes)
32
+
33
+ ## File System Access
34
+
35
+ This CLI only accesses:
36
+
37
+ - `~/.faam/` — configuration storage (read/write)
38
+ - Agent skills directories — e.g. `~/.claude/skills/`, `~/.codex/skills/` (read for sync, write for install-skills)
39
+
40
+ No other directories are read from or written to.
41
+
42
+ ## Dependencies
43
+
44
+ This package uses a minimal set of well-known dependencies:
45
+
46
+ - `commander` — CLI argument parsing
47
+ - `chalk` — terminal colors
48
+ - `ora` — terminal spinners
49
+ - `prompts` — interactive prompts
50
+ - `glob` — file pattern matching
51
+ - `gray-matter` — YAML frontmatter parsing
52
+
53
+ All dependencies are pinned and auditable.
package/dist/index.cjs CHANGED
@@ -22215,7 +22215,7 @@ var import_prompts = __toESM(require_prompts3(), 1);
22215
22215
  async function initCommand(options2) {
22216
22216
  const configPath = getAgentCardConfigPath();
22217
22217
  if (agentCardConfigExists() && !options2.force) {
22218
- if (!process.stdin.isTTY || options2.name && options2.description) {
22218
+ if (!process.stdin.isTTY || options2.name) {
22219
22219
  console.log(source_default.yellow("agent-card.json already exists at:"));
22220
22220
  console.log(source_default.gray(configPath));
22221
22221
  console.log();
@@ -22233,23 +22233,23 @@ async function initCommand(options2) {
22233
22233
  return;
22234
22234
  }
22235
22235
  }
22236
- const isInteractive2 = !(options2.name && options2.description) && process.stdin.isTTY;
22236
+ const clientConfig = isLoggedIn() ? readConfig() : null;
22237
+ const defaultName = clientConfig?.account_id ? `agent-${clientConfig.account_id}` : "My AI Agent";
22238
+ const isInteractive2 = process.stdin.isTTY && !options2.name;
22237
22239
  let config;
22238
22240
  if (isInteractive2) {
22239
22241
  const response = await (0, import_prompts.default)([
22240
22242
  {
22241
22243
  type: "text",
22242
22244
  name: "name",
22243
- message: "Agent name",
22244
- initial: options2.name || "",
22245
- validate: (v) => v.length > 0 || "Name is required"
22245
+ message: "Agent name (press Enter for default)",
22246
+ initial: options2.name || defaultName
22246
22247
  },
22247
22248
  {
22248
22249
  type: "text",
22249
22250
  name: "description",
22250
- message: "Description",
22251
- initial: options2.description || "",
22252
- validate: (v) => v.length > 0 || "Description is required"
22251
+ message: "Description (optional)",
22252
+ initial: options2.description || ""
22253
22253
  },
22254
22254
  {
22255
22255
  type: "text",
@@ -22263,12 +22263,9 @@ async function initCommand(options2) {
22263
22263
  process.exit(0);
22264
22264
  }
22265
22265
  });
22266
- if (!response.name || !response.description) {
22267
- return;
22268
- }
22269
22266
  config = {
22270
- name: response.name,
22271
- description: response.description,
22267
+ name: response.name || defaultName,
22268
+ description: response.description || "",
22272
22269
  version: "1.0.0",
22273
22270
  provider: {
22274
22271
  organization: response.organization || "",
@@ -22285,16 +22282,9 @@ async function initCommand(options2) {
22285
22282
  is_public: true
22286
22283
  };
22287
22284
  } else {
22288
- if (!options2.name || !options2.description) {
22289
- console.log(source_default.red("Error: --name and --description are required in non-interactive mode."));
22290
- console.log();
22291
- console.log("Usage:");
22292
- console.log(source_default.cyan(' faam init --name "My Agent" --description "What my agent does"'));
22293
- process.exit(1);
22294
- }
22295
22285
  config = {
22296
- name: options2.name,
22297
- description: options2.description,
22286
+ name: options2.name || defaultName,
22287
+ description: options2.description || "",
22298
22288
  version: "1.0.0",
22299
22289
  provider: {
22300
22290
  organization: options2.organization || "",
@@ -22347,8 +22337,8 @@ async function initCommand(options2) {
22347
22337
  console.log();
22348
22338
  const syncSpinner = ora("Syncing to Faam...").start();
22349
22339
  try {
22350
- const clientConfig = readConfig();
22351
- const client = new RlpApiClient(clientConfig);
22340
+ const syncConfig = clientConfig || readConfig();
22341
+ const client = new RlpApiClient(syncConfig);
22352
22342
  const result = await syncToApi(client, config, fileSkills);
22353
22343
  syncSpinner.succeed("Synced successfully");
22354
22344
  if (result.created.length > 0) {
@@ -22365,7 +22355,7 @@ async function initCommand(options2) {
22365
22355
  }
22366
22356
  console.log();
22367
22357
  console.log("Your agent card is live at:");
22368
- console.log(source_default.cyan(`https://agent-${clientConfig.account_id}.faam.io/.well-known/agent-card.json`));
22358
+ console.log(source_default.cyan(`https://agent-${syncConfig.account_id}.faam.io/.well-known/agent-card.json`));
22369
22359
  console.log();
22370
22360
  console.log("Go back to the onboarding page and click", source_default.bold('"Verify Setup"'), "to continue.");
22371
22361
  } catch (err) {
@@ -22487,7 +22477,7 @@ function configListKeysCommand() {
22487
22477
 
22488
22478
  // src/index.ts
22489
22479
  var program2 = new Command();
22490
- program2.name("faam").description("CLI tool to sync local skills to your FAAM Agent Card").version("0.2.2");
22480
+ program2.name("faam").description("CLI tool to sync local skills to your FAAM Agent Card").version("0.2.5");
22491
22481
  program2.command("login").description("Store your FAAM account key").requiredOption("-k, --key <account_key>", "Your FAAM account key").option("--api-url <url>", "API URL (default: https://api.faam.io)").action(async (options2) => {
22492
22482
  await loginCommand({
22493
22483
  key: options2.key,
package/package.json CHANGED
@@ -1,17 +1,12 @@
1
1
  {
2
2
  "name": "@stainlu/faam-cli",
3
- "version": "0.2.2",
3
+ "version": "0.2.5",
4
4
  "description": "CLI tool to sync local skills to your FAAM Agent Card",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "faam": "./dist/index.cjs",
8
8
  "faam-cli": "./dist/index.cjs"
9
9
  },
10
- "scripts": {
11
- "dev": "tsx src/index.ts",
12
- "build": "tsup",
13
- "typecheck": "tsc --noEmit"
14
- },
15
10
  "dependencies": {
16
11
  "chalk": "^5.3.0",
17
12
  "commander": "^12.1.0",
@@ -30,19 +25,35 @@
30
25
  "node": ">=18"
31
26
  },
32
27
  "files": [
33
- "dist"
28
+ "dist",
29
+ "LICENSE",
30
+ "SECURITY.md",
31
+ "CHANGELOG.md"
34
32
  ],
35
33
  "keywords": [
36
34
  "faam",
37
35
  "agent",
38
36
  "skills",
39
37
  "cli",
40
- "a2a"
38
+ "a2a",
39
+ "a2a-protocol",
40
+ "agent-card",
41
+ "ai-agent",
42
+ "google-a2a"
41
43
  ],
44
+ "author": "stainlu <stainlu@newtype-ai.org>",
42
45
  "license": "Apache-2.0",
46
+ "homepage": "https://faam.io",
47
+ "bugs": "https://github.com/stainlu/faam/issues",
48
+ "funding": "https://faam.io",
43
49
  "repository": {
44
50
  "type": "git",
45
51
  "url": "https://github.com/stainlu/faam.git",
46
52
  "directory": "apps/cli"
53
+ },
54
+ "scripts": {
55
+ "dev": "tsx src/index.ts",
56
+ "build": "tsup",
57
+ "typecheck": "tsc --noEmit"
47
58
  }
48
- }
59
+ }