atris 2.3.7 → 2.3.8

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.
@@ -1,144 +1,234 @@
1
1
  ---
2
2
  name: x-search
3
3
  description: "X/Twitter search via xAI Grok API. Use when user wants to search tweets, monitor topics, find viral posts, or run social listening. Costs 5 credits per search. Triggers on x search, tweet search, twitter search, social listening, revenue intel, viral tweets."
4
- version: 1.0.0
4
+ version: 2.0.0
5
5
  tags:
6
6
  - x-search
7
7
  - social
8
8
  - research
9
9
  ---
10
10
 
11
- # x-search
11
+ # X Search
12
+
13
+ > Drop this in `~/.claude/skills/x-search/SKILL.md` and Claude Code becomes your X/Twitter intelligence tool.
14
+
15
+ ## Bootstrap (ALWAYS Run First)
16
+
17
+ Before any X search operation, run this bootstrap to ensure everything is set up:
18
+
19
+ ```bash
20
+ #!/bin/bash
21
+ set -e
22
+
23
+ # 1. Check if atris CLI is installed
24
+ if ! command -v atris &> /dev/null; then
25
+ echo "Installing atris CLI..."
26
+ npm install -g atris
27
+ fi
28
+
29
+ # 2. Check if logged in to AtrisOS
30
+ if [ ! -f ~/.atris/credentials.json ]; then
31
+ echo "Not logged in to AtrisOS."
32
+ echo ""
33
+ echo "Option 1 (interactive): Run 'atris login' and follow prompts"
34
+ echo "Option 2 (non-interactive): Get token from https://atris.ai/auth/cli"
35
+ echo " Then run: atris login --token YOUR_TOKEN"
36
+ echo ""
37
+ exit 1
38
+ fi
39
+
40
+ # 3. Extract token
41
+ if command -v node &> /dev/null; then
42
+ TOKEN=$(node -e "console.log(require('$HOME/.atris/credentials.json').token)")
43
+ elif command -v python3 &> /dev/null; then
44
+ TOKEN=$(python3 -c "import json,os; print(json.load(open(os.path.expanduser('~/.atris/credentials.json')))['token'])")
45
+ elif command -v jq &> /dev/null; then
46
+ TOKEN=$(jq -r '.token' ~/.atris/credentials.json)
47
+ else
48
+ echo "Error: Need node, python3, or jq to read credentials"
49
+ exit 1
50
+ fi
51
+
52
+ # 4. Quick auth check
53
+ STATUS=$(curl -s "https://api.atris.ai/api/me" \
54
+ -H "Authorization: Bearer $TOKEN")
55
+
56
+ if echo "$STATUS" | grep -q "Token expired\|Not authenticated\|Unauthorized"; then
57
+ echo "Token expired. Please re-authenticate:"
58
+ echo " Run: atris login --force"
59
+ exit 1
60
+ fi
61
+
62
+ echo "Ready. X Search is available (5 credits per search)."
63
+ export ATRIS_TOKEN="$TOKEN"
64
+ ```
65
+
66
+ ---
12
67
 
13
- Search X/Twitter via xAI's Grok API. 5 credits per search action. Returns tweets with full text, author, engagement metrics, and citations.
68
+ ## API Reference
14
69
 
15
- ## Quick Search
70
+ Base: `https://api.atris.ai/api/x-search`
16
71
 
17
- ```python
18
- cd backend
19
- source ../venv/bin/activate
72
+ All requests require: `-H "Authorization: Bearer $TOKEN"`
73
+
74
+ ### Get Token (after bootstrap)
75
+ ```bash
76
+ TOKEN=$(node -e "console.log(require('$HOME/.atris/credentials.json').token)")
20
77
  ```
21
78
 
22
- ```python
23
- import asyncio
24
- from dotenv import load_dotenv
25
- load_dotenv('.env')
79
+ ### Search X/Twitter
80
+ ```bash
81
+ curl -s -X POST "https://api.atris.ai/api/x-search/search" \
82
+ -H "Authorization: Bearer $TOKEN" \
83
+ -H "Content-Type: application/json" \
84
+ -d '{
85
+ "query": "\"CRM is dead\" OR \"Salesforce alternative\"",
86
+ "limit": 10
87
+ }'
88
+ ```
26
89
 
27
- from clients.xai import XAIClient, bill_xai_action
90
+ **With date filter** (last N days only):
91
+ ```bash
92
+ curl -s -X POST "https://api.atris.ai/api/x-search/search" \
93
+ -H "Authorization: Bearer $TOKEN" \
94
+ -H "Content-Type: application/json" \
95
+ -d '{
96
+ "query": "AI agents replacing SaaS",
97
+ "limit": 10,
98
+ "days_back": 7
99
+ }'
100
+ ```
28
101
 
29
- # 1. Bill the user (5 credits)
30
- bill = await bill_xai_action(USER_ID, "x_search")
31
- if not bill["ok"]:
32
- print(f"Insufficient credits: {bill['error']}")
102
+ **Response:**
103
+ ```json
104
+ {
105
+ "status": "success",
106
+ "credits_used": 5,
107
+ "credits_remaining": 995,
108
+ "data": {
109
+ "content": "1. @levelsio: AI agents are replacing...",
110
+ "citations": ["https://x.com/levelsio/status/..."],
111
+ "usage": {"prompt_tokens": 200, "completion_tokens": 800}
112
+ }
113
+ }
114
+ ```
33
115
 
34
- # 2. Search
35
- client = XAIClient()
36
- result = await client.search_x('"CRM is dead" OR "Salesforce is dead"', limit=10)
37
- print(result["content"])
38
- print(f"Usage: {result['usage']}")
116
+ ### Research a Person
117
+ ```bash
118
+ curl -s -X POST "https://api.atris.ai/api/x-search/research-person" \
119
+ -H "Authorization: Bearer $TOKEN" \
120
+ -H "Content-Type: application/json" \
121
+ -d '{
122
+ "name": "Leah Bonvissuto",
123
+ "handle": "leahbon",
124
+ "company": "Presentr",
125
+ "context": "Interested in revenue intelligence and AI for GTM"
126
+ }'
39
127
  ```
40
128
 
41
- ## Date-Constrained Search (last N days)
129
+ **Response:**
130
+ ```json
131
+ {
132
+ "status": "success",
133
+ "credits_used": 5,
134
+ "credits_remaining": 990,
135
+ "data": {
136
+ "content": "### 1. Profile\n**Name:** Leah Bonvissuto\n...",
137
+ "citations": ["https://x.com/..."],
138
+ "usage": {"prompt_tokens": 300, "completion_tokens": 1200}
139
+ }
140
+ }
141
+ ```
42
142
 
43
- ```python
44
- from xai_sdk.chat import user as xai_user
143
+ ---
45
144
 
46
- client = XAIClient()
47
- tools = client._get_tools()
145
+ ## Workflows
146
+
147
+ ### "Search X for tweets about a topic"
148
+ 1. Run bootstrap
149
+ 2. Search: `POST /x-search/search` with `{query, limit}`
150
+ 3. Display results: tweet text, author, engagement, links
151
+
152
+ ### "Find tweets from the last week about X"
153
+ 1. Run bootstrap
154
+ 2. Search with date filter: `POST /x-search/search` with `{query, limit, days_back: 7}`
155
+ 3. Display results sorted by engagement
156
+
157
+ ### "Research a person before a meeting"
158
+ 1. Run bootstrap
159
+ 2. Research: `POST /x-search/research-person` with `{name, handle, company, context}`
160
+ 3. Display profile, background, talking points
161
+
162
+ ### "Monitor keyword clusters for revenue intel"
163
+ 1. Run bootstrap
164
+ 2. Run multiple searches across keyword clusters:
165
+ - `"CRM is dead" OR "Salesforce is dead" OR "HubSpot sucks"`
166
+ - `"revenue operations" (broken OR frustrated OR replacing)`
167
+ - `(founder OR CEO) "tech stack" (consolidating OR ripping out)`
168
+ 3. Each search costs 5 credits
169
+ 4. Combine results, rank by engagement, draft replies
170
+
171
+ ### "Find viral tweets in my industry"
172
+ 1. Run bootstrap
173
+ 2. Search with engagement filter: `POST /x-search/search` with query including `min_faves:50`
174
+ 3. Display top tweets sorted by likes/retweets
48
175
 
49
- chat = client._get_client().chat.create(
50
- model="grok-4-1-fast",
51
- tools=[tools.x_search()],
52
- )
176
+ ---
53
177
 
54
- chat.append(xai_user(f"""Search X/Twitter for: "your query here"
178
+ ## Query Tips
55
179
 
56
- IMPORTANT: Only return tweets posted within the last 7 days.
57
- Return the 10 most relevant posts with:
58
- - Full tweet text (quoted exactly)
59
- - Author handle
60
- - Exact date/time
61
- - Engagement (likes, retweets, views)
180
+ | Goal | Query Example |
181
+ |------|--------------|
182
+ | Specific phrase | `"revenue operations"` |
183
+ | OR logic | `"CRM is dead" OR "Salesforce alternative"` |
184
+ | From a user | `from:levelsio` |
185
+ | High engagement | `"AI agents" min_faves:50` |
186
+ | Exclude retweets | `"your query" -is:retweet` |
187
+ | Multiple keywords | `(founder OR CEO) ("AI adoption" OR "AI native")` |
62
188
 
63
- Prioritize posts with high engagement (likes > 5, views > 1000)."""))
189
+ ---
64
190
 
65
- content = ""
66
- for response, chunk in chat.stream():
67
- if chunk.content:
68
- content += chunk.content
69
- print(content)
70
- ```
191
+ ## Billing
71
192
 
72
- ## Revenue Intel Digest (multi-cluster)
193
+ - Every search costs **5 credits** (flat)
194
+ - 1 credit = $0.01, so 1 search = $0.05
195
+ - Research person also costs 5 credits
196
+ - Credits are deducted server-side before the search runs
197
+ - If insufficient credits, returns `402 Insufficient credits`
73
198
 
74
- ```python
75
- from atris.team.gtm.skills.revenue_intel import run_digest, format_for_slack
199
+ ---
76
200
 
77
- # Runs 5 keyword clusters, drafts replies for top 5 items
78
- # Cost: 5 credits per cluster = 25 credits total
79
- result = await run_digest(
80
- days_back=1,
81
- user_id=USER_ID,
82
- draft_count=5,
83
- )
201
+ ## Error Handling
84
202
 
85
- print(result["digest"]) # Ranked results by cluster
86
- print(result["drafts"]) # Reply options A/B per item
87
- print(result["credits_used"])
203
+ | Error | Meaning | Solution |
204
+ |-------|---------|----------|
205
+ | `401 Not authenticated` | Invalid/expired token | Run `atris login` |
206
+ | `402 Insufficient credits` | Not enough credits | Purchase credits at atris.ai |
207
+ | `502 Search failed` | xAI API issue | Retry in a few seconds |
88
208
 
89
- # Format for Slack delivery
90
- slack_msg = await format_for_slack(result)
91
- ```
209
+ ---
92
210
 
93
- ## Custom Keyword Clusters
211
+ ## Quick Reference
94
212
 
95
- ```python
96
- my_clusters = {
97
- "competitors": '"Competitor Name" (review OR complaint OR switching OR alternative)',
98
- "industry_pain": '"your industry" (frustrated OR broken OR replacing OR ripping out)',
99
- "thought_leaders": '(founder OR CEO OR CTO) ("your topic" OR "related topic") min_faves:10',
100
- }
213
+ ```bash
214
+ # Setup (one time)
215
+ npm install -g atris && atris login
101
216
 
102
- result = await run_digest(clusters=my_clusters, user_id=USER_ID, days_back=7)
103
- ```
217
+ # Get token
218
+ TOKEN=$(node -e "console.log(require('$HOME/.atris/credentials.json').token)")
104
219
 
105
- ## Billing
220
+ # Search tweets
221
+ curl -s -X POST "https://api.atris.ai/api/x-search/search" \
222
+ -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
223
+ -d '{"query": "AI agents", "limit": 10}'
106
224
 
107
- 1. Every xAI action costs **5 credits** (flat)
108
- 2. 1 credit = $0.01, so 1 search = $0.05
109
- 3. `bill_xai_action(user_id, action_name)` checks balance and deducts before the call
110
- 4. Returns `{"ok": False, "error": "Insufficient credits"}` if balance < 5
111
- 5. Transaction logged as `txn_type="xai_action"` in `credit_transactions`
112
-
113
- | Plan | Monthly Credits | Searches/Month |
114
- |------|----------------|----------------|
115
- | Free | 50 | 10 |
116
- | Pro ($20/mo) | 1,000 | 200 |
117
- | Max ($200/mo) | unlimited | unlimited |
118
- | Credit pack ($10) | 1,000 | 200 |
119
-
120
- ## Cost Breakdown
121
-
122
- | Component | Cost to us | What it does |
123
- |-----------|-----------|--------------|
124
- | xAI x_search tool | $0.005/call | Searches X, returns batch of tweets |
125
- | grok-4-1-fast tokens | ~$0.003/call | Processes and formats results |
126
- | Total per search | ~$0.008 | Raw cost |
127
- | We charge | $0.05 (5 credits) | 84% margin |
128
-
129
- ## Key Files
130
-
131
- | File | What |
132
- |------|------|
133
- | `backend/clients/xai.py` | XAIClient + bill_xai_action() |
134
- | `atris/team/gtm/skills/revenue_intel.py` | Multi-cluster digest pipeline |
135
- | `backend/tools/core/reply_guy_tool.py` | Reply generation tool (bills 5 credits) |
136
- | `backend/tools/integrations/research_tweet_tool.py` | Research + tweet tool (bills 5 credits) |
137
-
138
- ## Rules
139
-
140
- 1. Always bill before searching — never search without `bill_xai_action()`
141
- 2. Date filtering is prompt-based, not API-level — include explicit date cutoff in prompt
142
- 3. Use `min_faves:N` in queries to filter low-engagement noise
143
- 4. Never auto-post tweets — always require user approval
144
- 5. Internal usage (no user_id) skips billing — platform absorbs cost
225
+ # Search last 7 days only
226
+ curl -s -X POST "https://api.atris.ai/api/x-search/search" \
227
+ -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
228
+ -d '{"query": "AI agents", "limit": 10, "days_back": 7}'
229
+
230
+ # Research a person
231
+ curl -s -X POST "https://api.atris.ai/api/x-search/research-person" \
232
+ -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
233
+ -d '{"name": "John Doe", "handle": "johndoe", "company": "Acme"}'
234
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "atris",
3
- "version": "2.3.7",
3
+ "version": "2.3.8",
4
4
  "description": "atrisDev (atris dev) - CLI for AI coding agents. Works with Claude Code, Cursor, Windsurf. Make any codebase AI-navigable.",
5
5
  "main": "bin/atris.js",
6
6
  "bin": {