sella-cli 0.6.6 → 0.7.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/README.md CHANGED
@@ -33,7 +33,7 @@ npx sella-cli
33
33
 
34
34
  That one command is the whole setup. The wizard:
35
35
 
36
- 1. **Detects your agent clients**: Claude Code, Claude Desktop, Cursor, Windsurf, VS Code, Cline.
36
+ 1. **Detects your agent clients**: Claude Code, Claude Desktop, Cursor, Windsurf, VS Code, Cline, Codex, Antigravity, OpenClaw.
37
37
  2. **Installs the Sella MCP server** into each one. Writes are idempotent and your other MCP servers are preserved.
38
38
  3. **Pairs the machine**: paste a setup code from the dashboard, or use your email and a 6-digit code.
39
39
  4. **Proves it works** with a live `sella doctor` run at the end.
@@ -77,7 +77,8 @@ What's in there: a catalogue of 1,100+ machine-payable API providers, plus first
77
77
 
78
78
  - **One-command onboarding**, so you never hand-edit an MCP config again.
79
79
  - **Pay-per-call in USDC**: fractions of a cent for most calls, multi-chain, with budgets you set and keys you can revoke.
80
- - **A marketplace built for agents**: every listing is discoverable and payable over MCP + x402, so your agent buys mid-task instead of stalling.
80
+ - **One search across everything**: datasets, APIs, workflows, and Sella Native products are all discoverable in a single MCP call, ranked by computed quality, so your agent buys mid-task instead of stalling.
81
+ - **Policy-aware buying**: your agent can preview a quote and check it against your budget before paying, and every purchase leaves a decision receipt it can explain.
81
82
  - **Publishing from a CSV**, so you can sell your own data without opening a browser.
82
83
  - **Agent-grade output**: every command supports `--json`, `--yes`, and env vars, with meaningful exit codes. Your CI can run it. Your agent can run it.
83
84
 
@@ -118,7 +119,7 @@ Then ask your agent:
118
119
 
119
120
  > Search Sella for a web search API and tell me what it costs per call.
120
121
 
121
- The agent answers using the Sella MCP tools (`search_datasets`, `list_market_apis`, `try_dataset`, and friends) with the key this CLI stored for it. When you fund the agent wallet, it can buy what it found.
122
+ The agent answers using Sella's MCP tools, starting with `search_catalog` (one search across datasets, APIs, workflows, and Sella Native products) and `get_listing` for the details, with the key this CLI stored for it. When you fund the agent wallet, it can preview the price with `purchase_preview` and buy what it found.
122
123
 
123
124
  ### Real-world: publish a CSV and get paid in USDC
124
125
 
@@ -209,10 +210,11 @@ Sella has two other ways in: your agent can onboard itself over MCP with your em
209
210
  | Agent task ideas | https://sellag.vercel.app/rfi |
210
211
  | npm | https://www.npmjs.com/package/sella-cli |
211
212
  | Issues | https://github.com/010100100100011101010100/ogsella/issues |
213
+ | Email | rasesh@buildifi.ai |
212
214
 
213
215
  ## Found a bug?
214
216
 
215
- Found a bug? Have an idea? [Mail us](rasesh@buildifi.ai). We read every one.
217
+ Found a bug? Have an idea? [Open an issue](https://github.com/010100100100011101010100/ogsella/issues) or [email us](mailto:rasesh@buildifi.ai). We read every one.
216
218
 
217
219
  ## License
218
220
 
package/dist/clients.js CHANGED
@@ -27,6 +27,27 @@ function stdioBridgeEntry(mcpUrl, apiKey) {
27
27
  args: ['-y', 'mcp-remote', mcpUrl, ...(apiKey ? ['--header', `Authorization: Bearer ${apiKey}`] : [])],
28
28
  };
29
29
  }
30
+ /**
31
+ * Codex keeps MCP servers in ~/.codex/config.toml. We do a targeted section upsert instead of a
32
+ * TOML parse/serialize round-trip so user comments and formatting survive. The `url` key selects
33
+ * streamable HTTP; `http_headers` carries static auth headers (both per the Codex config docs).
34
+ * Only the standard `[mcp_servers.sella]` table form is recognized; exotic spellings (dotted keys,
35
+ * inline tables) are left alone and would shadow ours — the backup covers that case.
36
+ */
37
+ export function upsertCodexToml(raw, mcpUrl, apiKey) {
38
+ const lines = [`[mcp_servers.sella]`, `url = "${mcpUrl}"`];
39
+ if (apiKey)
40
+ lines.push(`http_headers = { "Authorization" = "Bearer ${apiKey}" }`);
41
+ const section = lines.join('\n');
42
+ // Our table (plus any of its sub-tables) up to the next unrelated header or end of file.
43
+ const existing = /(^|\n)\[mcp_servers\.sella\][\s\S]*?(?=\n\[(?!mcp_servers\.sella[.\]])|$)/;
44
+ if (existing.test(raw)) {
45
+ const next = raw.replace(existing, (_match, lead) => `${lead}${section}`);
46
+ return next.endsWith('\n') ? next : `${next}\n`;
47
+ }
48
+ const head = raw.trimEnd();
49
+ return `${head ? `${head}\n\n` : ''}${section}\n`;
50
+ }
30
51
  const CLIENTS = [
31
52
  {
32
53
  id: 'claude-code',
@@ -91,6 +112,43 @@ const CLIENTS = [
91
112
  doc.mcpServers.sella = stdioBridgeEntry(mcpUrl, apiKey);
92
113
  },
93
114
  },
115
+ {
116
+ id: 'codex',
117
+ name: 'Codex',
118
+ marker: (env) => path.join(env.home, '.codex'),
119
+ configPath: (env) => path.join(env.home, '.codex', 'config.toml'),
120
+ applyRaw: upsertCodexToml,
121
+ },
122
+ {
123
+ // Antigravity IDE + CLI share one MCP config at ~/.gemini/config/mcp_config.json.
124
+ // Remote servers use `serverUrl` (`httpUrl` is deprecated).
125
+ id: 'antigravity',
126
+ name: 'Antigravity',
127
+ marker: (env) => appSupport(env, 'Antigravity'),
128
+ configPath: (env) => path.join(env.home, '.gemini', 'config', 'mcp_config.json'),
129
+ apply: (doc, mcpUrl, apiKey) => {
130
+ doc.mcpServers = doc.mcpServers || {};
131
+ const entry = { serverUrl: mcpUrl };
132
+ if (apiKey)
133
+ entry.headers = { Authorization: `Bearer ${apiKey}` };
134
+ doc.mcpServers.sella = entry;
135
+ },
136
+ },
137
+ {
138
+ // OpenClaw stores MCP servers under mcp.servers in ~/.openclaw/openclaw.json.
139
+ id: 'openclaw',
140
+ name: 'OpenClaw',
141
+ marker: (env) => path.join(env.home, '.openclaw'),
142
+ configPath: (env) => path.join(env.home, '.openclaw', 'openclaw.json'),
143
+ apply: (doc, mcpUrl, apiKey) => {
144
+ doc.mcp = doc.mcp || {};
145
+ doc.mcp.servers = doc.mcp.servers || {};
146
+ const entry = { url: mcpUrl, transport: 'streamable-http' };
147
+ if (apiKey)
148
+ entry.headers = { Authorization: `Bearer ${apiKey}` };
149
+ doc.mcp.servers.sella = entry;
150
+ },
151
+ },
94
152
  ];
95
153
  export function detectClients(env = defaultEnv()) {
96
154
  return CLIENTS.map((spec) => ({
@@ -108,6 +166,25 @@ export function installSellaIntoClient(id, opts) {
108
166
  throw new Error(`Unknown client: ${id}`);
109
167
  const configPath = spec.configPath(env);
110
168
  const exists = fs.existsSync(configPath);
169
+ // Raw-text configs (Codex's TOML): targeted rewrite, byte-compare for idempotency.
170
+ if (spec.applyRaw) {
171
+ const raw = exists ? fs.readFileSync(configPath, 'utf8') : '';
172
+ const next = spec.applyRaw(raw, opts.mcpUrl, opts.apiKey);
173
+ if (exists && raw === next) {
174
+ return { id, configPath, action: 'unchanged' };
175
+ }
176
+ let backupPath;
177
+ if (!opts.dryRun) {
178
+ fs.mkdirSync(path.dirname(configPath), { recursive: true });
179
+ if (exists && raw.trim()) {
180
+ backupPath = `${configPath}.sella-backup`;
181
+ if (!fs.existsSync(backupPath))
182
+ fs.writeFileSync(backupPath, raw);
183
+ }
184
+ fs.writeFileSync(configPath, next);
185
+ }
186
+ return { id, configPath, action: exists ? 'updated' : 'created', backupPath };
187
+ }
111
188
  let doc = {};
112
189
  if (exists) {
113
190
  const raw = fs.readFileSync(configPath, 'utf8').trim();
@@ -121,6 +198,8 @@ export function installSellaIntoClient(id, opts) {
121
198
  }
122
199
  }
123
200
  const before = JSON.stringify(doc);
201
+ if (!spec.apply)
202
+ throw new Error(`Client ${id} has no config writer`);
124
203
  spec.apply(doc, opts.mcpUrl, opts.apiKey);
125
204
  const after = JSON.stringify(doc, null, 2);
126
205
  if (exists && JSON.stringify(JSON.parse(before)) === JSON.stringify(JSON.parse(after))) {
package/dist/index.js CHANGED
@@ -13,7 +13,7 @@ import { defaultIo, Printer } from './output.js';
13
13
  import { Ui } from './ui.js';
14
14
  import { recordCliEvent, saveTelemetryDecision, shouldPromptTelemetry } from './telemetry.js';
15
15
  const DEFAULT_MCP_URL = 'https://sellag.vercel.app/api/mcp';
16
- const VERSION = '0.6.6';
16
+ const VERSION = '0.7.0';
17
17
  function parseFlags(argv) {
18
18
  const flags = {
19
19
  json: false, yes: false, noColor: false, dryRun: false, noKeychain: false,
@@ -70,7 +70,7 @@ Options:
70
70
  --setup-code <code> Pair with a dashboard setup code (also: SELLA_SETUP_CODE env)
71
71
  --email <address> Pair with email + OTP (interactive)
72
72
  --card <path> Dataset card for 'publish push' (default ./sella-dataset.json)
73
- --client <ids> Comma-separated subset (claude-code,claude-desktop,cursor,windsurf,vscode,cline)
73
+ --client <ids> Comma-separated subset (claude-code,claude-desktop,cursor,windsurf,vscode,cline,codex,antigravity,openclaw)
74
74
  --no-keychain Skip the OS keychain; store the key in a 0600 file (also: SELLA_NO_KEYCHAIN)
75
75
  --dry-run Show what would change without writing
76
76
  --json Machine-readable output (one JSON document on stdout)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sella-cli",
3
- "version": "0.6.6",
3
+ "version": "0.7.0",
4
4
  "description": "Connect your AI agent to Sella, the marketplace where agents buy data and APIs, in one command: npx sella-cli. Installs the Sella MCP server into Claude Code, Cursor and more, then pairs, verifies, funds, and publishes.",
5
5
  "keywords": [
6
6
  "cli",