hacklab 0.9.0 → 0.10.0-staging.17.1

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
@@ -6,26 +6,27 @@ your profile with GitHub.
6
6
 
7
7
  ## Install & join
8
8
 
9
- One command:
9
+ Install, then join:
10
10
 
11
11
  ```bash
12
12
  curl -fsSL https://hacklab.so/install | sh
13
+ hacklab join
13
14
  ```
14
15
 
15
- It checks for Node 20+, installs the CLI globally (`npm install -g
16
- hacklab@latest`), then runs `hacklab join`. After that `hacklab` is a real
17
- command on your PATH. If you already have Node (incl. via a version manager),
18
- you can skip the script and do the same two steps yourself:
16
+ The script checks for Node 20+ and installs the CLI globally. After that
17
+ `hacklab` is a real command on your PATH. If you already have Node (including
18
+ through a version manager), you can skip the script:
19
19
 
20
20
  ```bash
21
- npm install -g hacklab@latest
21
+ npm i -g hacklab@latest
22
22
  hacklab join
23
23
  ```
24
24
 
25
25
  ### Windows
26
26
 
27
- On native Windows (PowerShell), use the `.ps1` installer instead — it does the
28
- same thing (Node 20+ check, global install, `hacklab join`):
27
+ On native Windows (PowerShell), use the `.ps1` installer instead — it checks
28
+ for Node 20+, installs the CLI globally, and (unlike the sh installer) also
29
+ runs `hacklab join` for you:
29
30
 
30
31
  ```powershell
31
32
  irm https://hacklab.so/install.ps1 | iex
@@ -42,11 +43,12 @@ runs. If you install manually instead (`npm i -g hacklab@latest`) and PowerShell
42
43
  says *"running scripts is disabled on this system"*, run that one line yourself,
43
44
  or call `hacklab.cmd …` (which no execution policy blocks).
44
45
 
45
- If this machine is already set up with a finished profile, both the installer
46
- and `hacklab join` stop early: they print who you're signed in as and how to
47
- switch (`hacklab logout` then `hacklab login`) instead of reinstalling or
48
- re-registering. A half-finished signup that authenticated but never claimed a
49
- username still falls through, so you can re-run and complete it.
46
+ If this machine is already set up with a finished profile, `hacklab join` stops
47
+ early: it prints who you're signed in as and how to switch (`hacklab logout`
48
+ then `hacklab login`) instead of re-registering. A half-finished signup that
49
+ authenticated but never claimed a username still falls through, so you can
50
+ re-run and complete it. The `curl | sh` installer itself only installs — it
51
+ never touches your session.
50
52
 
51
53
  The CLI prints a one-line nudge when a newer version is published (checked at
52
54
  most once a day); update with `npm i -g hacklab@latest`.
@@ -54,7 +56,7 @@ most once a day); update with `npm i -g hacklab@latest`.
54
56
  ## The join ritual
55
57
 
56
58
  ```
57
- scan local AI usage → see your rank → pick a username → sign in with GitHub → claim → chat
59
+ scan local AI usage → see your rank → sign in with GitHub → claim a username → card → optional X share
58
60
  ```
59
61
 
60
62
  1. **Scan** — reads your local AI token usage from Claude Code, Codex, Cursor,
@@ -67,14 +69,15 @@ scan local AI usage → see your rank → pick a username → sign in with GitHu
67
69
  asked.
68
70
  3. **Rank** — shows the rank that usage would hold (`you'd be #15 of N`), with no
69
71
  account required.
70
- 4. **Username** — pick your Hacklab handle (checked for availability live).
71
- 5. **GitHub** — sign in to authenticate and link your profile + repos.
72
- 6. **Claim** — your profile goes live at `hacklab.so/<username>`. Your usage
73
- uploads in the background while you get a shareable stats card.
74
- 7. **Share** — a stats thumbnail (belt, level, rank, token breakdown) is rendered
75
- locally, copied to your clipboard, and you can post it to X in one keystroke.
76
- 8. **Chat** — finally, you're offered the live channel (default yes). Decline and
77
- you can jump in anytime with `hacklab chat`.
72
+ 4. **GitHub** — sign in to authenticate and link your profile + repos.
73
+ 5. **Username** — pick your Hacklab handle (checked for availability live).
74
+ 6. **Claim** — saves your usage, syncs pinned GitHub projects, and claims
75
+ `hacklab.so/<username>`. Bio and the first drop finish activation in the web
76
+ onboarding flow.
77
+ 7. **Card** — renders the belt, level, rank, and token breakdown directly in the
78
+ terminal. Terminals without inline images get a text version.
79
+ 8. **Share** — one optional X prompt. Saying yes saves the image to
80
+ `~/hacklab-card.png`, copies it, and opens a prefilled X post; saying no exits.
78
81
 
79
82
  ## Commands
80
83
 
@@ -84,7 +87,9 @@ scan local AI usage → see your rank → pick a username → sign in with GitHu
84
87
  `hacklab login` to switch accounts.
85
88
  - `hacklab sync` — re-scan local AI usage and sync it to your profile.
86
89
  - `hacklab whoami` — show who you're logged in as.
87
- - `hacklab drop "message"` — post a drop to your feed (`-u <url>` to attach a link).
90
+ - `hacklab drop "message"` — post a drop to your feed (`-u <url>` to attach a
91
+ link). Human output prints its profile URL; `--json` returns a stable envelope
92
+ (`schemaVersion`, `id`, `path`, full `url`).
88
93
  - `hacklab chat` — open the live channel (typing posts; this is the default, so
89
94
  bare `hacklab chat` and `hacklab chat live` are the same). Other subcommands:
90
95
  `tail`, `post`, `history`, `dms`, `dm <handle>`, `flag`. Author handles are
@@ -94,15 +99,31 @@ scan local AI usage → see your rank → pick a username → sign in with GitHu
94
99
  - `hacklab logout` — clear your saved session on this machine.
95
100
  - `hacklab config <key> <value>` — set config (`cursor-api-key`, `cursor-email`).
96
101
  Bare `hacklab config` prints the effective values and where each came from.
97
- - `hacklab project` — publish the repo you're standing in as a project. No
98
- manifest: it reads the git remote, README, and package.json, shows a preview,
99
- and publishes on confirm (`--yes` to skip, `--json` for agents). Re-running
100
- refreshes the same project (slug derives from the repo name) without losing
101
- its publish date or screenshots; if the live site (package.json `homepage` or
102
- `--live <url>`) has an `og:image`, that becomes the screenshot. Override any
103
- inferred field with `--title`, `--description`, `--live`, `--tags a,b,c`,
104
- `--slug`. Manage the set with `hacklab project list` and
105
- `hacklab project delete <slug>`.
102
+ - `hacklab project` — publish the repo you're standing in as a project. It reads
103
+ the git remote, README, and package.json, shows a preview, and publishes on
104
+ confirm (`--yes` to skip, `--json` for agents). Publish a project with no repo
105
+ using `project add --no-repo --title "…"`, and set the long-form page content
106
+ with `--content <md>` or `--content-file <file>`. Agents can publish every
107
+ field at once from a manifest with `project apply project.yaml --yes --json`,
108
+ including up to five remote PNG, JPEG, or WebP screenshots (max 3MB each) that
109
+ Hacklab downloads and hosts. Re-running `add`/`apply` refreshes the same slug
110
+ without losing its publish date. Manage the set with `hacklab project list`,
111
+ `project view <slug>`, `project edit <slug> --title/--desc/--url/--tags`, and
112
+ `project delete <slug>`.
113
+
114
+ ```yaml
115
+ title: My project
116
+ repoUrl: https://github.com/me/my-project
117
+ liveUrl: https://my-project.dev
118
+ description: The short profile-card summary.
119
+ content: |
120
+ ## Why I built it
121
+ Long-form markdown for the project page.
122
+ tags: [ai, typescript]
123
+ screenshots:
124
+ - url: https://my-project.dev/thumbnail.webp
125
+ caption: Main screen
126
+ ```
106
127
  - `hacklab org` — hub for company management. If you already own a company, pick
107
128
  a field, type the new value, and it saves as you go. If you don't own one yet,
108
129
  it offers to claim or create. Subcommands: `hacklab org claim` (take ownership
@@ -111,10 +132,14 @@ scan local AI usage → see your rank → pick a username → sign in with GitHu
111
132
  - `hacklab profile` — view and edit your own profile. Bare `profile` (or
112
133
  `profile view`) shows it; `profile edit` is an org-style autosave editor;
113
134
  `profile set <field> <value>` writes one field (`--clear` unsets, handles like
114
- `x mattbratos` become full links); `profile apply profile.yaml` writes many
115
- fields in one shot — handy for agents setting up your profile. Fields: `name`,
116
- `bio`, `website`, `blog`, `x`, `youtube`, `instagram`, `rss`, `open-to-work`.
135
+ `x mattbratos` become full links); `profile set readme --file profile.md`
136
+ writes a long Markdown README without shell quoting; `profile apply
137
+ profile.yaml` writes many fields in one shot. Fields: `name`, `bio`, `readme`,
138
+ `website`, `blog`, `x`, `youtube`, `instagram`, `rss`, `open-to-work`.
117
139
  Add `--json` to `view`/`set`/`apply` for machine-readable output.
140
+ - `hacklab hacker view [handle] --json` — read the rich agent profile including
141
+ links, counts, skills, recent projects, essays, and drops. Use
142
+ `hacklab hacker list --newest --json` to discover recently activated members.
118
143
  - `hacklab --version` / `hacklab --help`.
119
144
 
120
145
  ## Cursor usage
@@ -6,6 +6,7 @@
6
6
  export declare function parseDropArgs(args: string[]): {
7
7
  text: string;
8
8
  url?: string;
9
+ json: boolean;
9
10
  };
10
- export declare function drop(content: string, url?: string): Promise<void>;
11
+ export declare function drop(content: string, url?: string, json?: boolean): Promise<void>;
11
12
  //# sourceMappingURL=drop.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"drop.d.ts","sourceRoot":"","sources":["../../src/commands/drop.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CAyB5E;AAED,wBAAsB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,iBAmCvD"}
1
+ {"version":3,"file":"drop.d.ts","sourceRoot":"","sources":["../../src/commands/drop.ts"],"names":[],"mappings":"AAKA;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG;IAC7C,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,OAAO,CAAA;CACd,CA4BA;AAED,wBAAsB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,IAAI,UAAQ,iBAgFrE"}
@@ -1,3 +1,4 @@
1
+ import { emitJsonError } from '../api-client.js';
1
2
  import { captureEvent } from '../posthog.js';
2
3
  import { loadSession, resolveAppUrl } from '../session.js';
3
4
  import { dim, error, info, success } from '../ui.js';
@@ -8,6 +9,7 @@ import { dim, error, info, success } from '../ui.js';
8
9
  */
9
10
  export function parseDropArgs(args) {
10
11
  let url;
12
+ let json = false;
11
13
  const words = [];
12
14
  for (let i = 0; i < args.length; i++) {
13
15
  const arg = args[i];
@@ -15,6 +17,9 @@ export function parseDropArgs(args) {
15
17
  url = args[i + 1];
16
18
  i++;
17
19
  }
20
+ else if (arg === '--json') {
21
+ json = true;
22
+ }
18
23
  else if (arg.startsWith('-')) {
19
24
  console.error(`unknown flag: ${arg}`);
20
25
  process.exit(1);
@@ -28,33 +33,68 @@ export function parseDropArgs(args) {
28
33
  console.error('usage: hacklab drop your message here');
29
34
  process.exit(1);
30
35
  }
31
- return { text, url };
36
+ return { text, url, json };
32
37
  }
33
- export async function drop(content, url) {
38
+ export async function drop(content, url, json = false) {
34
39
  const session = await loadSession();
35
40
  if (!session) {
41
+ if (json)
42
+ emitJsonError('unauthorized', 'not logged in');
36
43
  error('not logged in');
37
44
  info(`run ${dim('hacklab login')} first`);
38
45
  process.exit(1);
39
46
  }
40
47
  if (content.length > 1000) {
48
+ if (json)
49
+ emitJsonError('invalid_fields', `too long — ${content.length}/1000 chars`);
41
50
  error(`too long — ${content.length}/1000 chars`);
42
51
  process.exit(1);
43
52
  }
44
- const res = await fetch(`${resolveAppUrl(session)}/api/drops`, {
45
- method: 'POST',
46
- headers: {
47
- 'Content-Type': 'application/json',
48
- Authorization: `Bearer ${session.token}`,
49
- },
50
- body: JSON.stringify({ content, url }),
51
- });
53
+ let res;
54
+ try {
55
+ res = await fetch(`${resolveAppUrl(session)}/api/drops`, {
56
+ method: 'POST',
57
+ headers: {
58
+ 'Content-Type': 'application/json',
59
+ Authorization: `Bearer ${session.token}`,
60
+ },
61
+ body: JSON.stringify({ content, url }),
62
+ });
63
+ }
64
+ catch (err) {
65
+ const message = err instanceof Error ? err.message : String(err);
66
+ if (json)
67
+ emitJsonError('network', `couldn't reach hacklab: ${message}`);
68
+ error(`couldn't reach hacklab: ${message}`);
69
+ process.exit(1);
70
+ }
52
71
  if (!res.ok) {
53
72
  const data = await res.json().catch(() => null);
73
+ if (json)
74
+ emitJsonError('request_failed', data?.error ?? `failed (${res.status})`);
54
75
  error(data?.error ?? `failed (${res.status})`);
55
76
  process.exit(1);
56
77
  }
57
- success('dropped.');
78
+ const result = (await res.json().catch(() => null));
79
+ if (!result?.id) {
80
+ if (json)
81
+ emitJsonError('bad_response', 'got a malformed response from hacklab');
82
+ error('got a malformed response from hacklab');
83
+ process.exit(1);
84
+ }
85
+ // Only `id` is load-bearing. Older servers respond without path/url —
86
+ // during a CLI-publish/deploy skew the drop still succeeded, so degrade
87
+ // gracefully instead of reporting a false failure (agents would retry and
88
+ // post duplicates).
89
+ const dropPath = result.path ?? `/${session.handle}?tab=drops#drop-${result.id}`;
90
+ const dropUrl = result.url ?? `${resolveAppUrl(session).replace(/\/$/, '')}${dropPath}`;
91
+ if (json) {
92
+ console.log(JSON.stringify({ schemaVersion: 1, id: result.id, path: dropPath, url: dropUrl }, null, 2));
93
+ }
94
+ else {
95
+ success('dropped.');
96
+ info(dropUrl);
97
+ }
58
98
  await captureEvent(session.handle, 'cli_drop_posted', {
59
99
  content_length: content.length,
60
100
  has_url: url !== undefined,
@@ -1 +1 @@
1
- {"version":3,"file":"drop.js","sourceRoot":"","sources":["../../src/commands/drop.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"drop.js","sourceRoot":"","sources":["../../src/commands/drop.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"hacker.d.ts","sourceRoot":"","sources":["../../src/commands/hacker.ts"],"names":[],"mappings":"AAyBA,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAe1D"}
1
+ {"version":3,"file":"hacker.d.ts","sourceRoot":"","sources":["../../src/commands/hacker.ts"],"names":[],"mappings":"AA4BA,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB1D"}
@@ -2,16 +2,19 @@ import { apiErrorMessage, emitJsonError, requireSession, } from '../api-client.j
2
2
  import { renderCard } from '../card.js';
3
3
  import { resolveCommand } from '../resolve-command.js';
4
4
  import { fetchApi } from '../sync.js';
5
- import { dim, error, info } from '../ui.js';
6
- // `hacklab hacker view [handle]` — the auth-gated terminal card, `--json` for
7
- // agents. With no handle it views your own profile (the authenticated user);
5
+ import { bold, dim, error, info } from '../ui.js';
6
+ // `hacklab hacker view [handle]` — an auth-gated terminal card for humans and
7
+ // a rich agent profile in JSON. `list --newest` provides bounded discovery.
8
+ // With no handle it views your own profile (the authenticated user);
8
9
  // managing that profile is `hacklab profile`'s job — this command is the
9
10
  // window, that one is the mirror. Noun-verb so an identifier never sits in a
10
11
  // verb slot (a handle can be any word). Subcommands resolve by shortest
11
12
  // unambiguous prefix, so `hacklab h v isomiki` works via resolveCommand.
12
- const SUBCOMMANDS = ['view'];
13
+ const SUBCOMMANDS = ['view', 'list'];
13
14
  function usage() {
14
- error('usage: hacklab hacker view [handle]');
15
+ error('usage: hacklab hacker [view|list]');
16
+ info(` hacklab hacker ${dim('view [handle] [--json]')}`);
17
+ info(` hacklab hacker ${dim('list --newest [--limit 20] [--json]')}`);
15
18
  process.exit(1);
16
19
  }
17
20
  export async function hacker(args) {
@@ -29,6 +32,64 @@ export async function hacker(args) {
29
32
  }
30
33
  if (resolved.name === 'view')
31
34
  return hackerView(rest);
35
+ if (resolved.name === 'list')
36
+ return hackerList(rest);
37
+ }
38
+ async function hackerList(args) {
39
+ const json = args.includes('--json');
40
+ if (!args.includes('--newest')) {
41
+ if (json)
42
+ return emitJsonError('invalid_fields', 'pass --newest');
43
+ error('pass --newest');
44
+ usage();
45
+ }
46
+ const limitIndex = args.indexOf('--limit');
47
+ const rawLimit = limitIndex === -1 ? undefined : args[limitIndex + 1];
48
+ const limit = rawLimit === undefined ? 20 : Number(rawLimit);
49
+ if ((limitIndex !== -1 && rawLimit === undefined) ||
50
+ !Number.isInteger(limit) ||
51
+ limit < 1 ||
52
+ limit > 50) {
53
+ if (json)
54
+ return emitJsonError('invalid_fields', '--limit must be 1-50');
55
+ error('--limit must be 1-50');
56
+ process.exit(1);
57
+ }
58
+ const session = await requireSession(json);
59
+ let res;
60
+ try {
61
+ res = await fetchApi(session, `/api/hackers/newest?src=cli&limit=${limit}`, { headers: { Authorization: `Bearer ${session.token}` } });
62
+ }
63
+ catch (err) {
64
+ const message = err instanceof Error ? err.message : String(err);
65
+ if (json)
66
+ return emitJsonError('network', message);
67
+ error(message);
68
+ process.exit(1);
69
+ }
70
+ if (!res.ok)
71
+ return handleError(res, 'newest hackers', json, session);
72
+ const body = (await res.json().catch(() => null));
73
+ if (!body?.hackers) {
74
+ if (json)
75
+ return emitJsonError('bad_response', 'malformed response');
76
+ error('got a malformed response from hacklab');
77
+ process.exit(1);
78
+ }
79
+ if (json) {
80
+ console.log(JSON.stringify(body, null, 2));
81
+ return;
82
+ }
83
+ if (!body.hackers.length) {
84
+ info('no new hackers yet');
85
+ return;
86
+ }
87
+ for (const hacker of body.hackers) {
88
+ const name = hacker.displayName ? ` ${hacker.displayName}` : '';
89
+ console.log(` ${bold(hacker.handle)}${dim(name)}`);
90
+ if (hacker.bio)
91
+ console.log(` ${dim(hacker.bio)}`);
92
+ }
32
93
  }
33
94
  async function hackerView(args) {
34
95
  const json = args.includes('--json');
@@ -47,7 +108,8 @@ async function hackerView(args) {
47
108
  }
48
109
  let res;
49
110
  try {
50
- res = await fetchApi(session, `/api/hackers/${encodeURIComponent(handle)}?src=cli`, { headers: { Authorization: `Bearer ${session.token}` } });
111
+ const format = json ? '&format=agent' : '';
112
+ res = await fetchApi(session, `/api/hackers/${encodeURIComponent(handle)}?src=cli${format}`, { headers: { Authorization: `Bearer ${session.token}` } });
51
113
  }
52
114
  catch (err) {
53
115
  // fetchApi rethrows a friendly "couldn't reach hacklab" message.
@@ -1 +1 @@
1
- {"version":3,"file":"hacker.js","sourceRoot":"","sources":["../../src/commands/hacker.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hacker.js","sourceRoot":"","sources":["../../src/commands/hacker.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * The hero command: the guided join ritual.
3
3
  *
4
- * scan → anonymous rank → GitHub OAuth → pick username + fields → claim
4
+ * scan → anonymous rank → GitHub OAuth → pick username → claim → card
5
5
  *
6
6
  * Value (rank) is shown before any account exists. GitHub auth comes right
7
7
  * after the rank and before the username, so we know whether the account
@@ -1 +1 @@
1
- {"version":3,"file":"join.d.ts","sourceRoot":"","sources":["../../src/commands/join.ts"],"names":[],"mappings":"AA2CA;;;;;;;;;;GAUG;AACH,wBAAsB,IAAI,CAAC,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,iBA6Y1D"}
1
+ {"version":3,"file":"join.d.ts","sourceRoot":"","sources":["../../src/commands/join.ts"],"names":[],"mappings":"AA0CA;;;;;;;;;;GAUG;AACH,wBAAsB,IAAI,CAAC,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,iBA+U1D"}