standout 0.1.0 โ 0.2.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 +2 -1
- package/dist/ai-usage.d.ts +164 -0
- package/dist/ai-usage.js +1302 -0
- package/dist/api.d.ts +10 -0
- package/dist/api.js +86 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +351 -0
- package/dist/cursor.d.ts +54 -0
- package/dist/cursor.js +487 -0
- package/dist/dev-env.d.ts +28 -0
- package/dist/dev-env.js +264 -0
- package/dist/gather.d.ts +81 -0
- package/dist/gather.js +869 -0
- package/dist/mcp.d.ts +1 -0
- package/dist/mcp.js +25 -0
- package/dist/prompt.d.ts +1 -0
- package/dist/prompt.js +247 -0
- package/dist/redact.d.ts +1 -0
- package/dist/redact.js +37 -0
- package/dist/tools.d.ts +4 -0
- package/dist/tools.js +182 -0
- package/dist/twitter-scrape.d.ts +1 -0
- package/dist/twitter-scrape.js +267 -0
- package/dist/wrapped/aggregate.d.ts +6 -0
- package/dist/wrapped/aggregate.js +791 -0
- package/dist/wrapped/chrono-critters.d.ts +8 -0
- package/dist/wrapped/chrono-critters.js +32 -0
- package/dist/wrapped/index.d.ts +3 -0
- package/dist/wrapped/index.js +2 -0
- package/dist/wrapped/mascots.d.ts +2 -0
- package/dist/wrapped/mascots.js +35 -0
- package/dist/wrapped/render.d.ts +13 -0
- package/dist/wrapped/render.js +1003 -0
- package/dist/wrapped/types.d.ts +183 -0
- package/dist/wrapped/types.js +4 -0
- package/dist/wrapped-client.d.ts +10 -0
- package/dist/wrapped-client.js +36 -0
- package/dist/wrapped-share.d.ts +3 -0
- package/dist/wrapped-share.js +27 -0
- package/package.json +34 -8
- package/bin/cli.mjs +0 -30
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
export interface WrappedAggregateView {
|
|
2
|
+
readiness: {
|
|
3
|
+
usage_stats_status: "ready" | "scanning" | "enriching" | "unavailable" | "error";
|
|
4
|
+
profile_basics_status: "ready" | "scanning" | "enriching" | "unavailable" | "error";
|
|
5
|
+
enrichment_status: "ready" | "scanning" | "enriching" | "unavailable" | "error";
|
|
6
|
+
};
|
|
7
|
+
name: string;
|
|
8
|
+
archetype_label: string;
|
|
9
|
+
zinger: string;
|
|
10
|
+
mascot_pose: MascotPose;
|
|
11
|
+
total_hours: number;
|
|
12
|
+
total_sessions: number;
|
|
13
|
+
active_days: number;
|
|
14
|
+
streak_days: number;
|
|
15
|
+
weekend_ratio: number;
|
|
16
|
+
top_tools: {
|
|
17
|
+
name: string;
|
|
18
|
+
count: number;
|
|
19
|
+
}[];
|
|
20
|
+
hour_histogram: number[];
|
|
21
|
+
peak_hour: number | null;
|
|
22
|
+
conductor_workspaces: number;
|
|
23
|
+
top_projects: {
|
|
24
|
+
label: string;
|
|
25
|
+
name: string;
|
|
26
|
+
commits: number;
|
|
27
|
+
sessions: number;
|
|
28
|
+
blurb?: string;
|
|
29
|
+
}[];
|
|
30
|
+
contributions: {
|
|
31
|
+
one_liner: string;
|
|
32
|
+
themes: string[];
|
|
33
|
+
} | null;
|
|
34
|
+
all_time: {
|
|
35
|
+
total_hours: number;
|
|
36
|
+
total_sessions: number;
|
|
37
|
+
active_days: number;
|
|
38
|
+
first_session: string | null;
|
|
39
|
+
last_session: string | null;
|
|
40
|
+
monthly_buckets: {
|
|
41
|
+
month: string;
|
|
42
|
+
sessions: number;
|
|
43
|
+
duration_hours: number;
|
|
44
|
+
}[];
|
|
45
|
+
};
|
|
46
|
+
frameworks: string[];
|
|
47
|
+
prompt_samples: string[];
|
|
48
|
+
top_asks: {
|
|
49
|
+
text: string;
|
|
50
|
+
count: number;
|
|
51
|
+
}[];
|
|
52
|
+
collaboration: CollaborationView | null;
|
|
53
|
+
total_commits: number;
|
|
54
|
+
ai_assisted_commits: number;
|
|
55
|
+
ai_assisted_pct: number;
|
|
56
|
+
code_footprint: {
|
|
57
|
+
lines_added: number;
|
|
58
|
+
lines_deleted: number;
|
|
59
|
+
net: number;
|
|
60
|
+
additive_ratio: number;
|
|
61
|
+
median_commit_size: number;
|
|
62
|
+
biggest_commit_size: number;
|
|
63
|
+
lines_per_commit: number;
|
|
64
|
+
label: "Shipper" | "Refactorer" | "Cleaner";
|
|
65
|
+
line: string | null;
|
|
66
|
+
} | null;
|
|
67
|
+
concurrency: {
|
|
68
|
+
open_tab_avg: number;
|
|
69
|
+
open_tab_peak: number;
|
|
70
|
+
longest_session_hours: number;
|
|
71
|
+
active_juggle_pct: number;
|
|
72
|
+
line: string | null;
|
|
73
|
+
} | null;
|
|
74
|
+
conversation: {
|
|
75
|
+
total_prompts: number;
|
|
76
|
+
question_ratio: number;
|
|
77
|
+
avg_prompt_chars: number;
|
|
78
|
+
line: string | null;
|
|
79
|
+
themes: string[];
|
|
80
|
+
} | null;
|
|
81
|
+
rhythm_comment: string | null;
|
|
82
|
+
stack_comment: string | null;
|
|
83
|
+
early_adopter: boolean;
|
|
84
|
+
cohort_size: number;
|
|
85
|
+
percentile_bands: {
|
|
86
|
+
typescript_shippers: number | null;
|
|
87
|
+
ai_native: number | null;
|
|
88
|
+
open_source: number | null;
|
|
89
|
+
};
|
|
90
|
+
rank_summary: {
|
|
91
|
+
sample_size: number;
|
|
92
|
+
hours_percentile: number | null;
|
|
93
|
+
sessions_percentile: number | null;
|
|
94
|
+
active_days_percentile: number | null;
|
|
95
|
+
tokens_percentile: number | null;
|
|
96
|
+
commit_days_percentile: number | null;
|
|
97
|
+
};
|
|
98
|
+
proficiency: ProficiencyView | null;
|
|
99
|
+
tokens: {
|
|
100
|
+
work_tokens: number;
|
|
101
|
+
cache_tokens: number;
|
|
102
|
+
total_30d: number;
|
|
103
|
+
total_prior_30d: number;
|
|
104
|
+
multiplier_vs_prior: number | null;
|
|
105
|
+
by_tool: {
|
|
106
|
+
tool: string;
|
|
107
|
+
tokens: number;
|
|
108
|
+
}[];
|
|
109
|
+
six_month_buckets: {
|
|
110
|
+
month: string;
|
|
111
|
+
tokens: number;
|
|
112
|
+
}[];
|
|
113
|
+
estimated_retail_cost_usd: number;
|
|
114
|
+
cursor_untracked: boolean;
|
|
115
|
+
};
|
|
116
|
+
tool_relationship: {
|
|
117
|
+
kind: "switch";
|
|
118
|
+
from_tool: string;
|
|
119
|
+
to_tool: string;
|
|
120
|
+
switch_month: string;
|
|
121
|
+
timeline: {
|
|
122
|
+
month: string;
|
|
123
|
+
dominant: string;
|
|
124
|
+
share: number;
|
|
125
|
+
}[];
|
|
126
|
+
} | {
|
|
127
|
+
kind: "loyalist";
|
|
128
|
+
tool: string;
|
|
129
|
+
months_count: number;
|
|
130
|
+
sessions_count: number;
|
|
131
|
+
} | {
|
|
132
|
+
kind: "polyglot";
|
|
133
|
+
tools: {
|
|
134
|
+
tool: string;
|
|
135
|
+
share: number;
|
|
136
|
+
}[];
|
|
137
|
+
} | {
|
|
138
|
+
kind: "insufficient";
|
|
139
|
+
};
|
|
140
|
+
models: {
|
|
141
|
+
by_provider: {
|
|
142
|
+
provider: "anthropic" | "openai" | "other";
|
|
143
|
+
sessions: number;
|
|
144
|
+
share: number;
|
|
145
|
+
models: {
|
|
146
|
+
name: string;
|
|
147
|
+
sessions: number;
|
|
148
|
+
}[];
|
|
149
|
+
}[];
|
|
150
|
+
top_model: {
|
|
151
|
+
name: string;
|
|
152
|
+
sessions: number;
|
|
153
|
+
share: number;
|
|
154
|
+
} | null;
|
|
155
|
+
};
|
|
156
|
+
share_url: string;
|
|
157
|
+
}
|
|
158
|
+
export interface ProficiencyView {
|
|
159
|
+
score: number;
|
|
160
|
+
intensity: number | null;
|
|
161
|
+
consistency: number;
|
|
162
|
+
craft: number | null;
|
|
163
|
+
base: number;
|
|
164
|
+
craft_bonus: number;
|
|
165
|
+
top_dimension: "intensity" | "consistency" | "craft";
|
|
166
|
+
comment: string;
|
|
167
|
+
}
|
|
168
|
+
export interface CollaborationView {
|
|
169
|
+
style_label: string;
|
|
170
|
+
summary: string;
|
|
171
|
+
signals: {
|
|
172
|
+
fact_checking: string;
|
|
173
|
+
depth: string;
|
|
174
|
+
autonomy: string;
|
|
175
|
+
complexity: string;
|
|
176
|
+
};
|
|
177
|
+
fun_facts: {
|
|
178
|
+
most_common_ask: string | null;
|
|
179
|
+
weirdest_prompt: string | null;
|
|
180
|
+
};
|
|
181
|
+
generated_by: "llm" | "heuristic";
|
|
182
|
+
}
|
|
183
|
+
export type MascotPose = "default" | "night" | "caffeinated" | "crown" | "circuit" | "ship";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { WrappedAggregateView } from "./wrapped/types.js";
|
|
2
|
+
export interface WrappedReady {
|
|
3
|
+
id: string;
|
|
4
|
+
share_url: string;
|
|
5
|
+
view: WrappedAggregateView;
|
|
6
|
+
}
|
|
7
|
+
export declare function createWrapped(args: {
|
|
8
|
+
profile: Record<string, unknown>;
|
|
9
|
+
submissionId?: string | null;
|
|
10
|
+
}): Promise<WrappedReady | null>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { STANDOUT_API_URL } from "./api.js";
|
|
2
|
+
import { aggregateView } from "./wrapped/aggregate.js";
|
|
3
|
+
const HEADERS = {
|
|
4
|
+
"Content-Type": "application/json",
|
|
5
|
+
// Vercel BotID flagged Anthropic/JS as bot traffic; same goes for default
|
|
6
|
+
// node-fetch UAs on certain paths. Set a clear identity.
|
|
7
|
+
"User-Agent": "Standout/0.2.0 (node)",
|
|
8
|
+
};
|
|
9
|
+
export async function createWrapped(args) {
|
|
10
|
+
try {
|
|
11
|
+
const res = await fetch(`${STANDOUT_API_URL}/api/public/wrapped`, {
|
|
12
|
+
method: "POST",
|
|
13
|
+
headers: HEADERS,
|
|
14
|
+
body: JSON.stringify({
|
|
15
|
+
profile: args.profile,
|
|
16
|
+
submission_id: args.submissionId ?? undefined,
|
|
17
|
+
}),
|
|
18
|
+
});
|
|
19
|
+
if (!res.ok) {
|
|
20
|
+
const text = await res.text().catch(() => "");
|
|
21
|
+
process.stderr.write(`[wrapped] backend returned ${res.status}${text ? `: ${text.slice(0, 200)}` : ""}\n`);
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
const data = (await res.json());
|
|
25
|
+
const view = aggregateView({
|
|
26
|
+
profile: args.profile,
|
|
27
|
+
computed: data.computed,
|
|
28
|
+
share_url: data.share_url,
|
|
29
|
+
});
|
|
30
|
+
return { id: data.id, share_url: data.share_url, view };
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
process.stderr.write(`[wrapped] failed to reach backend: ${err instanceof Error ? err.message : err}\n`);
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import open from "open";
|
|
2
|
+
const TWEET_INTENT = "https://x.com/intent/post";
|
|
3
|
+
const PAW = "๐พ";
|
|
4
|
+
export function buildTweetText(view) {
|
|
5
|
+
const peakLine = view.peak_hour !== null
|
|
6
|
+
? `peak ${view.peak_hour.toString().padStart(2, "0")}:00`
|
|
7
|
+
: null;
|
|
8
|
+
const aiLine = view.ai_assisted_pct > 0
|
|
9
|
+
? `${Math.round(view.ai_assisted_pct * 100)}% AI-assisted`
|
|
10
|
+
: null;
|
|
11
|
+
const stack = view.frameworks.length > 0 ? view.frameworks.slice(0, 3).join(" ยท ") : null;
|
|
12
|
+
const stats = [peakLine, aiLine, stack].filter(Boolean).join(" ยท ");
|
|
13
|
+
const lines = [
|
|
14
|
+
`just got my @standoutwork wrapped ${PAW}`,
|
|
15
|
+
stats ||
|
|
16
|
+
`${Math.round(view.total_hours)} hours in claude code last 30 days`,
|
|
17
|
+
view.zinger ? `apparently i'm the kind who ${view.zinger}` : null,
|
|
18
|
+
].filter(Boolean);
|
|
19
|
+
return lines.join("\n");
|
|
20
|
+
}
|
|
21
|
+
export async function openShareToX(view) {
|
|
22
|
+
const text = buildTweetText(view);
|
|
23
|
+
const intent = new URL(TWEET_INTENT);
|
|
24
|
+
intent.searchParams.set("text", text);
|
|
25
|
+
intent.searchParams.set("url", view.share_url);
|
|
26
|
+
await open(intent.toString());
|
|
27
|
+
}
|
package/package.json
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "standout",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Build your developer profile with AI. One command, zero friction.",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"main": "./dist/cli.js",
|
|
6
7
|
"bin": {
|
|
7
|
-
"standout": "./
|
|
8
|
+
"standout": "./dist/cli.js"
|
|
8
9
|
},
|
|
9
|
-
"files": [
|
|
10
|
-
"bin",
|
|
11
|
-
"README.md"
|
|
12
|
-
],
|
|
13
10
|
"homepage": "https://standout.work",
|
|
14
11
|
"repository": {
|
|
15
12
|
"type": "git",
|
|
@@ -19,6 +16,35 @@
|
|
|
19
16
|
"publishConfig": {
|
|
20
17
|
"access": "public"
|
|
21
18
|
},
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc",
|
|
21
|
+
"dev": "tsx src/cli.ts",
|
|
22
|
+
"test": "tsx --test tests/*.test.ts",
|
|
23
|
+
"typecheck": "tsc --noEmit",
|
|
24
|
+
"prepublishOnly": "npm run build"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@anthropic-ai/sdk": "^0.70.0",
|
|
28
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
29
|
+
"boxen": "^8.0.1",
|
|
30
|
+
"chalk": "^5.6.2",
|
|
31
|
+
"gradient-string": "^3.0.0",
|
|
32
|
+
"open": "^11.0.0",
|
|
33
|
+
"playwright-core": "^1.59.1",
|
|
34
|
+
"zod": "^3.24.0"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
38
|
+
"@types/node": "^25.6.0",
|
|
39
|
+
"tsx": "^4.19.0",
|
|
40
|
+
"typescript": "^5.6.0"
|
|
41
|
+
},
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=18"
|
|
44
|
+
},
|
|
45
|
+
"files": [
|
|
46
|
+
"dist"
|
|
47
|
+
],
|
|
22
48
|
"keywords": [
|
|
23
49
|
"developer",
|
|
24
50
|
"profile",
|
|
@@ -27,7 +53,7 @@
|
|
|
27
53
|
"career"
|
|
28
54
|
],
|
|
29
55
|
"license": "MIT",
|
|
30
|
-
"
|
|
31
|
-
"
|
|
56
|
+
"optionalDependencies": {
|
|
57
|
+
"better-sqlite3": "^12.9.0"
|
|
32
58
|
}
|
|
33
59
|
}
|
package/bin/cli.mjs
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// Minimal launch stub: claims the `standout` name on npm and makes `npx standout`
|
|
4
|
-
// live. The full developer-profile CLI is ported in here next. Zero deps, no
|
|
5
|
-
// network, no prompts โ safe to run anywhere, including a non-TTY Claude Code
|
|
6
|
-
// Bash call.
|
|
7
|
-
|
|
8
|
-
const ACCENT = "\x1b[38;2;173;92;255m";
|
|
9
|
-
const DIM = "\x1b[2m";
|
|
10
|
-
const RESET = "\x1b[0m";
|
|
11
|
-
|
|
12
|
-
function box(lines) {
|
|
13
|
-
const inner = Math.max(...lines.map((l) => l.length)) + 4;
|
|
14
|
-
const bar = "โ".repeat(inner);
|
|
15
|
-
const out = [` โ${bar}โ`];
|
|
16
|
-
for (const line of lines) {
|
|
17
|
-
out.push(` โ ${line.padEnd(inner - 4)} โ`);
|
|
18
|
-
}
|
|
19
|
-
out.push(` โ${bar}โ`);
|
|
20
|
-
return out.join("\n");
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const banner = box(["are you really tokenmaxxing?", "Powered by Standout (YC P26)"]);
|
|
24
|
-
|
|
25
|
-
console.log("");
|
|
26
|
-
console.log(`${ACCENT}${banner}${RESET}`);
|
|
27
|
-
console.log("");
|
|
28
|
-
console.log(" Standout is live. The full developer-profile experience lands here shortly.");
|
|
29
|
-
console.log(` ${DIM}Learn more: https://standout.work${RESET}`);
|
|
30
|
-
console.log("");
|