@sage-protocol/cli 0.8.15 → 0.8.16

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.

Potentially problematic release.


This version of @sage-protocol/cli might be problematic. Click here for more details.

package/README.md CHANGED
@@ -1,295 +1,185 @@
1
1
  # Sage CLI
2
2
 
3
- Command-line interface for the Sage Protocol. Create, manage, and publish AI prompt libraries with on-chain governance or as personal collections.
3
+ CLI for the Sage Protocol. Install AI prompts and skills, create prompt libraries, and publish with on-chain governance.
4
4
 
5
5
  ```bash
6
6
  npm i -g @sage-protocol/cli
7
- sage --help
8
7
  ```
9
8
 
10
- ## Quick Start
9
+ ## Zero-Config Start (Privy Default)
11
10
 
12
- ### Personal/Vault Library (No Governance)
13
-
14
- Create a wallet-owned library for your prompts without DAO overhead:
11
+ **Privy wallet is the default** - no local keystore or seed phrase needed. Just install and go:
15
12
 
16
13
  ```bash
17
- # 1. Connect your wallet
18
- # Privy is the default for npm installs (no local keystore required)
19
- # App ID is baked in; no secret is required when using the web relay (default)
20
- sage wallet connect
21
-
22
- # 2. Create a personal library
23
- sage library vault create --name "My Prompts"
14
+ # Install a skill immediately
15
+ sage install build-web3
24
16
 
25
- # 3. Push prompts to your library
26
- sage library vault push <libraryId> --dir ./prompts
17
+ # Or connect your wallet first (opens browser)
18
+ sage wallet connect
27
19
 
28
- # 4. List your libraries
29
- sage library vault list
20
+ # Get testnet tokens
21
+ sage sxxx faucet
30
22
  ```
31
23
 
32
- ### DAO Library (With Governance)
33
-
34
- Create a governed library with token-based voting:
24
+ ## Install Skills & Prompts
35
25
 
36
26
  ```bash
37
- # 1. Quick setup: scan prompts, upload, create DAO, register
38
- sage library quickstart --name "My DAO Library" --from-dir ./prompts
39
-
40
- # 2. Or step-by-step:
41
- sage prompts init # Initialize workspace
42
- sage prompts new my-prompt # Create a prompt
43
- sage prompts publish # Upload and propose update
44
- ```
45
-
46
- ### Install Prompts from Others
27
+ # From the Sage platform
28
+ sage install build-web3
29
+ sage install solidity-audit
47
30
 
48
- ```bash
49
- # From a DAO
31
+ # From a DAO library
50
32
  sage install 0x1234...abcd
51
- sage install my-library
52
33
 
53
34
  # From IPFS
54
- sage install QmXyz...
35
+ sage install bafkrei...
55
36
 
56
37
  # From GitHub
57
38
  sage install github:user/repo
58
- ```
59
39
 
60
- Note: autonomous agents use the A2A JSON‑RPC surface (`/a2a/dao/:subdao`) for paid, trust‑ranked discovery. The CLI continues to use public discovery/content endpoints.
61
-
62
- ## Command Reference
63
-
64
- ### Library Management
65
-
66
- | Command | Description |
67
- |---------|-------------|
68
- | `sage library quickstart` | Create library + DAO in one command |
69
- | `sage library info` | Show library info for a DAO |
70
- | `sage library fork <source>` | Fork an existing library |
71
- | `sage library personal create` | Create a personal (wallet-owned) library |
72
- | `sage library personal list` | List your personal libraries |
73
- | `sage library personal push` | Push files to a personal library |
74
- | `sage library personal delete` | Delete a personal library |
75
- | `sage library vault ...` | Alias for personal libraries (clearer SIWE vault naming) |
76
-
77
- ### Prompt Workspace
78
-
79
- | Command | Description |
80
- |---------|-------------|
81
- | `sage prompts init` | Initialize a prompt workspace |
82
- | `sage prompts new <key>` | Create a new prompt/skill |
83
- | `sage prompts list` | List all prompts in workspace |
84
- | `sage prompts publish` | Build manifest and propose update |
85
- | `sage prompts sync` | Sync with on-chain state |
86
- | `sage prompts import <source>` | Import from GitHub/on-chain |
87
- | `sage prompts search <query>` | Search prompts |
88
-
89
- ### Personal Prompts
90
-
91
- | Command | Description |
92
- |---------|-------------|
93
- | `sage personal create` | Create a personal registry |
94
- | `sage personal publish <key>` | Publish a free prompt |
95
- | `sage personal list` | List personal prompts |
96
- | `sage personal premium publish` | Publish paid content |
97
- | `sage personal premium buy` | Purchase a license |
98
- | `sage personal premium access` | Decrypt purchased content |
99
- | `sage personal my-licenses` | View owned licenses |
100
-
101
- ### Wallet & Config
102
-
103
- | Command | Description |
104
- |---------|-------------|
105
- | `sage wallet connect` | Connect a wallet (Cast, Privy, WalletConnect) |
106
- | `sage wallet balance` | Show wallet balance |
107
- | `sage config show` | Show current configuration |
108
- | `sage config ipfs onboard` | Configure IPFS/pinning |
109
- | `sage secret set <name>` | Store a secret in keychain |
40
+ # List what you have installed
41
+ sage list
42
+ ```
110
43
 
111
- ### NPM Install Setup (Privy)
44
+ ## Create a Personal Library
112
45
 
113
- For npm installs (running outside a repo), put Privy credentials in a global env file:
46
+ No governance overhead - just publish under your wallet:
114
47
 
115
48
  ```bash
116
- mkdir -p ~/.sage
117
- cat >> ~/.sage/.env << 'EOF'
118
- PRIVY_APP_ID=your_app_id
119
- PRIVY_APP_SECRET=your_app_secret
120
- EOF
121
- ```
49
+ # Create library
50
+ sage library personal create --name "My Prompts"
122
51
 
123
- Then:
52
+ # Push your prompts
53
+ sage library personal push <libraryId> --from-dir ./prompts
124
54
 
125
- ```bash
126
- SAGE_WALLET_TYPE=privy sage wallet connect
55
+ # List your libraries
56
+ sage library personal list
127
57
  ```
128
58
 
129
- ### Governance
59
+ ## Create a Governed DAO Library
130
60
 
131
- | Command | Description |
132
- |---------|-------------|
133
- | `sage gov propose` | Create a governance proposal |
134
- | `sage gov vote <proposalId>` | Vote on a proposal |
135
- | `sage gov queue <proposalId>` | Queue a passed proposal |
136
- | `sage gov execute <proposalId>` | Execute a queued proposal |
137
- | `sage proposals list` | List proposals for current DAO |
138
-
139
- ### Reputation
140
-
141
- | Command | Description |
142
- |---------|-------------|
143
- | `sage reputation check <address>` | Check trust signals (badges, contributions) |
144
- | `sage reputation status <address>` | Author metrics (revenue, purchases, consumers) |
145
- | `sage reputation leaderboard` | Top authors by revenue |
146
- | `sage reputation achievements <address>` | Achievement badges earned |
147
-
148
- ## Personal/Vault Libraries
149
-
150
- Personal libraries are wallet-owned collections that don't require DAO governance. They're ideal for:
151
-
152
- - **Individual creators** who want to publish prompts under their own identity
153
- - **Quick iteration** without governance delays
154
- - **Premium content** with on-chain licensing via Lit Protocol
155
-
156
- ### Create and Manage
61
+ For team/community libraries with on-chain voting:
157
62
 
158
63
  ```bash
159
- # Create a new vault library (alias of personal)
160
- sage library vault create --name "My AI Prompts" --description "Curated prompts for development"
161
-
162
- # View your libraries
163
- sage library vault list
64
+ # One command: scan prompts, upload, create DAO, register
65
+ sage library quickstart --name "Team Library" --from-dir ./prompts
164
66
 
165
- # Push content from a directory
166
- sage library vault push lib_abc123 --dir ./my-prompts
167
-
168
- # Get library details
169
- sage library vault info lib_abc123
170
-
171
- # Delete a library
172
- sage library vault delete lib_abc123
67
+ # Or step-by-step
68
+ sage prompts init
69
+ sage prompts new my-prompt
70
+ sage prompts publish
173
71
  ```
174
72
 
175
- ### Premium Content
73
+ ## First-Time Setup (Optional)
176
74
 
177
- Sell encrypted prompts with on-chain licensing:
75
+ Privy handles auth automatically. For advanced setup:
178
76
 
179
77
  ```bash
180
- # Publish premium content (encrypted via Lit Protocol)
181
- sage personal premium publish my-prompt \
182
- --file prompts/valuable-prompt.md \
183
- --price 100 \
184
- --name "Advanced Prompt" \
185
- --description "High-value prompt template"
186
-
187
- # Check pricing
188
- sage personal premium price <creator> <key>
189
-
190
- # Buy a license
191
- sage personal premium buy <creator> <key> --auto-approve
192
-
193
- # Access purchased content
194
- sage personal premium access <creator> <key> --out decrypted.md
195
-
196
- # View your licenses
197
- sage personal my-licenses
78
+ sage init # Interactive setup wizard
79
+ sage doctor # Check your environment
80
+ sage wizard # Guided tutorial
198
81
  ```
199
82
 
200
- ## IPFS & Pinning
201
-
202
- The CLI uses the Sage IPFS worker by default:
203
-
204
- - **Gateway**: `https://ipfs.dev.sageprotocol.io/ipfs`
205
- - **Worker**: `https://api.sageprotocol.io`
83
+ ## Claude Code Integration
206
84
 
207
85
  ```bash
208
- # Configure IPFS
209
- sage config ipfs onboard
210
-
211
- # Upload content
212
- sage ipfs upload ./my-file.md
213
-
214
- # Pin existing content
215
- sage ipfs pin <cid>
86
+ # Init with skill support
87
+ sage init --with-skill
216
88
 
217
- # Check credits
218
- sage ipfs credits
89
+ # Install skills for Claude Code
90
+ sage install build-web3
91
+ sage prompts import-skill solidity-audit
219
92
  ```
220
93
 
221
- ### Credits
94
+ ---
222
95
 
223
- ```bash
224
- # Show credit balance
225
- sage ipfs credits
96
+ ## Command Reference
226
97
 
227
- # Buy credits (opens checkout)
228
- sage ipfs buy-credits
98
+ ### Installation & Skills
229
99
 
230
- # Pin with credits
231
- sage ipfs pin <cid>
232
- ```
100
+ | Command | Description |
101
+ |---------|-------------|
102
+ | `sage install <source>` | Install from DAO, IPFS, or GitHub |
103
+ | `sage list` | List installed prompts/skills |
104
+ | `sage update [key]` | Update installed content |
105
+ | `sage skill add <path>` | Add local skill to Claude Code |
233
106
 
234
- ## Configuration
107
+ ### Wallet & Tokens
235
108
 
236
- Configuration is stored in `.sage/config.json` (project) or `~/.config/sage` (global).
109
+ | Command | Description |
110
+ |---------|-------------|
111
+ | `sage wallet` | Show wallet info (Privy default) |
112
+ | `sage wallet connect` | Connect wallet (opens browser) |
113
+ | `sage sxxx faucet` | Get testnet SXXX tokens |
114
+ | `sage sxxx balance` | Check SXXX balance |
115
+ | `sage sxxx delegate-self` | Enable voting power |
237
116
 
238
- ```bash
239
- # Show all config
240
- sage config show --all
117
+ ### Libraries
241
118
 
242
- # Set RPC endpoint
243
- sage config set-rpc https://base-sepolia.publicnode.com --chain-id 84532
119
+ | Command | Description |
120
+ |---------|-------------|
121
+ | `sage library personal create` | Create wallet-owned library |
122
+ | `sage library personal push` | Push content to library |
123
+ | `sage library personal list` | List your libraries |
124
+ | `sage library quickstart` | Create DAO library in one command |
244
125
 
245
- # Manage profiles
246
- sage config profile list
247
- sage config profile use <name>
248
- ```
126
+ ### Prompts
249
127
 
250
- ### Secrets
128
+ | Command | Description |
129
+ |---------|-------------|
130
+ | `sage prompts init` | Initialize workspace |
131
+ | `sage prompts new <key>` | Create new prompt |
132
+ | `sage prompts publish` | Publish to DAO |
133
+ | `sage prompts sync` | Sync with on-chain state |
251
134
 
252
- Secrets are stored in your OS keychain:
135
+ ### DAO & Governance
253
136
 
254
- ```bash
255
- sage secret set pinata.jwt
256
- sage secret get pinata.jwt
257
- sage secret list
258
- sage secret delete <name>
259
- ```
137
+ | Command | Description |
138
+ |---------|-------------|
139
+ | `sage dao list` | List DAOs |
140
+ | `sage dao info <addr>` | Show DAO details |
141
+ | `sage proposals inbox` | Active proposals |
142
+ | `sage gov vote <id>` | Vote on proposal |
260
143
 
261
- In CI, set `SAGE_SECRETS_BACKEND=env` and use environment variables.
144
+ ### IPFS
262
145
 
263
- ## Claude Code Integration
146
+ | Command | Description |
147
+ |---------|-------------|
148
+ | `sage ipfs upload <file>` | Upload to IPFS |
149
+ | `sage ipfs download <cid>` | Download (prompts, skills, raw) |
150
+ | `sage ipfs pins` | List pinned content |
264
151
 
265
- Initialize a project with Claude Code skill support:
152
+ ### Config
266
153
 
267
- ```bash
268
- sage init --with-skill
269
- ```
154
+ | Command | Description |
155
+ |---------|-------------|
156
+ | `sage config show` | Show configuration |
157
+ | `sage context` | Show DAO context |
158
+ | `sage doctor` | Diagnose environment |
270
159
 
271
- This creates:
272
- ```
273
- .claude/
274
- ├── skills/build-web3/
275
- │ ├── SKILL.md
276
- │ └── workflows/
277
- └── commands/build-web3.md
160
+ ## Aliases
278
161
 
279
- CLAUDE.md
280
- ```
162
+ | Full | Short |
163
+ |------|-------|
164
+ | `sage library` | `sage l` |
165
+ | `sage governance` | `sage gov` |
166
+ | `sage wallet` | `sage w` |
167
+ | `sage sxxx` | `sage token` |
168
+
169
+ ## Premium Content
281
170
 
282
- Import skills from the platform:
171
+ Sell encrypted prompts with Lit Protocol licensing:
283
172
 
284
173
  ```bash
285
- sage prompts import-skill <name>
286
- sage install build-web3
174
+ sage personal premium publish my-prompt --file ./prompt.md --price 100
175
+ sage personal premium buy <creator> <key>
176
+ sage personal premium access <creator> <key> --out decrypted.md
287
177
  ```
288
178
 
289
- ## Documentation
179
+ ## Links
290
180
 
291
- - [Development Guide](docs/DEVELOPMENT.md) - Setup, testing, and contributing
292
- - [Full Docs](https://docs.sageprotocol.io) - Complete documentation
181
+ - [Documentation](https://docs.sageprotocol.io)
182
+ - [GitHub](https://github.com/sage-protocol/cli)
293
183
 
294
184
  ## License
295
185
 
@@ -321,7 +321,7 @@ function register(program) {
321
321
  )
322
322
  .addCommand(
323
323
  new Command('download')
324
- .description('Download prompt from IPFS')
324
+ .description('Download content from IPFS (prompts, skills, libraries, or raw files)')
325
325
  .argument('<cid>', 'IPFS CID to download')
326
326
  .option('-o, --output <file>', 'Output file path')
327
327
  .option('-g, --gateway <url>', 'Preferred IPFS gateway (reads)', process.env.SAGE_IPFS_GATEWAY)
@@ -533,32 +533,138 @@ class IPFSManager {
533
533
 
534
534
  async downloadPrompt(cid, outputPath) {
535
535
  try {
536
- const downloaded = await withSpinner('Downloading prompt from IPFS', async () => {
536
+ const downloaded = await withSpinner('Downloading content from IPFS', async () => {
537
537
  let prompt = this.prompts.get(cid);
538
+ let contentType = 'prompt';
539
+
538
540
  if (!prompt) {
541
+ // First try to fetch as JSON (prompt/skill format)
539
542
  const data = await this.#withBackoff(() => this.client.downloadJson({ cid }).catch(() => null), { retries: Number(process.env.SAGE_IPFS_FETCH_RETRIES || 2), baseMs: Number(process.env.SAGE_IPFS_FETCH_BACKOFF_MS || 400) });
543
+
540
544
  if (data) {
541
- prompt = {
542
- name: data.name || 'Downloaded Prompt',
543
- description: data.description || 'Downloaded from IPFS',
544
- content: data.content || JSON.stringify(data),
545
- timestamp: data.timestamp || Date.now(),
546
- filePath: 'ipfs-download',
547
- };
545
+ // Detect content type based on structure
546
+ if (data.skills && Array.isArray(data.skills)) {
547
+ // Library manifest with skills
548
+ contentType = 'library';
549
+ prompt = {
550
+ name: data.name || 'Downloaded Library',
551
+ description: data.description || 'Library manifest from IPFS',
552
+ content: JSON.stringify(data, null, 2),
553
+ timestamp: data.timestamp || Date.now(),
554
+ filePath: 'ipfs-download',
555
+ metadata: { type: 'library', skillCount: data.skills.length, promptCount: data.prompts?.length || 0 }
556
+ };
557
+ } else if (data.content && (data.content.includes('# ') || data.content.includes('```'))) {
558
+ // Skill format (markdown content)
559
+ contentType = 'skill';
560
+ prompt = {
561
+ name: data.name || data.key || 'Downloaded Skill',
562
+ description: data.description || 'Skill from IPFS',
563
+ content: data.content,
564
+ timestamp: data.timestamp || Date.now(),
565
+ filePath: 'ipfs-download',
566
+ metadata: { type: 'skill', tags: data.tags }
567
+ };
568
+ } else if (data.name && data.content) {
569
+ // Standard prompt format
570
+ contentType = 'prompt';
571
+ prompt = {
572
+ name: data.name,
573
+ description: data.description || 'Downloaded from IPFS',
574
+ content: data.content,
575
+ timestamp: data.timestamp || Date.now(),
576
+ filePath: 'ipfs-download',
577
+ };
578
+ } else {
579
+ // Unknown JSON structure - save as raw JSON
580
+ contentType = 'json';
581
+ prompt = {
582
+ name: 'Downloaded Content',
583
+ description: 'Raw JSON from IPFS',
584
+ content: JSON.stringify(data, null, 2),
585
+ timestamp: Date.now(),
586
+ filePath: 'ipfs-download',
587
+ metadata: { type: 'json', keys: Object.keys(data) }
588
+ };
589
+ }
548
590
  this.prompts.set(cid, prompt);
591
+ } else {
592
+ // Try to fetch as raw text via gateway
593
+ const gatewayUrls = this.buildGatewayUrls(cid);
594
+ let rawContent = null;
595
+
596
+ for (const url of gatewayUrls) {
597
+ try {
598
+ const axios = require('axios');
599
+ const response = await axios.get(url, { timeout: 15000, responseType: 'text' });
600
+ if (response.data) {
601
+ rawContent = typeof response.data === 'string' ? response.data : JSON.stringify(response.data);
602
+ break;
603
+ }
604
+ } catch (_) {
605
+ // Try next gateway
606
+ }
607
+ }
608
+
609
+ if (rawContent) {
610
+ contentType = 'raw';
611
+ prompt = {
612
+ name: 'Downloaded Content',
613
+ description: 'Raw content from IPFS',
614
+ content: rawContent,
615
+ timestamp: Date.now(),
616
+ filePath: 'ipfs-download',
617
+ metadata: { type: 'raw', size: rawContent.length }
618
+ };
619
+ this.prompts.set(cid, prompt);
620
+ }
549
621
  }
550
622
  }
551
- if (!prompt) throw new Error(`Prompt with CID ${cid} not found`);
552
- const finalOutputPath = outputPath || `${prompt.name}.txt`;
623
+
624
+ if (!prompt) {
625
+ throw new Error(`Content with CID ${cid} not found. The CID may be invalid or the content may have expired.`);
626
+ }
627
+
628
+ // Determine file extension based on content type
629
+ let extension = '.txt';
630
+ if (contentType === 'skill') extension = '.md';
631
+ else if (contentType === 'library' || contentType === 'json') extension = '.json';
632
+
633
+ const safeName = prompt.name.replace(/[^a-zA-Z0-9-_]/g, '-').toLowerCase();
634
+ const finalOutputPath = outputPath || `${safeName}${extension}`;
553
635
  fs.writeFileSync(finalOutputPath, prompt.content);
554
- return { prompt, finalOutputPath };
636
+
637
+ return { prompt, finalOutputPath, contentType };
555
638
  }, { successText: () => 'Downloaded' });
556
- this.log('📝 Name:', downloaded.prompt.name);
639
+
640
+ // Show appropriate output based on content type
641
+ const typeLabels = {
642
+ prompt: '📝 Prompt',
643
+ skill: '🛠️ Skill',
644
+ library: '📚 Library',
645
+ json: '📄 JSON',
646
+ raw: '📦 Raw Content'
647
+ };
648
+
649
+ this.log(`${typeLabels[downloaded.contentType] || '📄 Content'}: ${downloaded.prompt.name}`);
557
650
  this.log('📄 Description:', downloaded.prompt.description);
558
651
  this.log('📁 Saved to:', downloaded.finalOutputPath);
652
+
653
+ // Show helpful hints based on content type
654
+ if (downloaded.contentType === 'skill') {
655
+ this.log(colors.yellow('\n💡 Tip: To install this skill, run:'));
656
+ this.log(` sage skill add ${downloaded.finalOutputPath}`);
657
+ } else if (downloaded.contentType === 'library') {
658
+ const meta = downloaded.prompt.metadata || {};
659
+ this.log(`📊 Contains: ${meta.promptCount || 0} prompts, ${meta.skillCount || 0} skills`);
660
+ } else if (downloaded.contentType === 'raw') {
661
+ this.log(colors.yellow('\n⚠️ Note: This content is not in Sage prompt/skill format.'));
662
+ this.log(' It has been saved as raw text.');
663
+ }
664
+
559
665
  return downloaded.finalOutputPath;
560
666
  } catch (error) {
561
- console.error('❌ Failed to download prompt:', error.message);
667
+ console.error('❌ Failed to download content:', error.message);
562
668
  throw error;
563
669
  }
564
670
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sage-protocol/cli",
3
- "version": "0.8.15",
3
+ "version": "0.8.16",
4
4
  "description": "Sage Protocol CLI for managing AI prompt libraries",
5
5
  "bin": {
6
6
  "sage": "./bin/sage.js"