Skip to content

Commit e1f1d5c

Browse files
committed
feat: add /share command
1 parent 55f8d42 commit e1f1d5c

9 files changed

Lines changed: 1004 additions & 5 deletions

File tree

README.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,12 @@ It's fast, it's memory-efficient, it's yours to run however you want, and there'
2828
2929
> [!NOTE]
3030
> **Recent Updates:**
31-
> - **Free Mode:** Try out Free in '/connect' to get a great agentic coding experience in Claurst for absolutely free (or as good as free gets you :P). `[EXPERIMENTAL]`
3231
>
33-
> - **/goal support:** Try out `/goal <objective>` to see claurst keep working an objective, spanning multiple turns instead of stopping after one normal turn. `[EXPERIMENTAL]`
32+
> - **/share support:** Use `/share` to share chat sessions with others via unlisted GitHub Gists. `[EXPERIMENTAL]`
3433
>
35-
> - **Managed Agents Preview:** Run `/managed-agents` to create a better agentic loop with a Manager-Executor relation and dramatically improved performance for fractions of the cost from running a larger model. Choose from 6 pre-built templates or build your own.`[EXPERIMENTAL]`
34+
> - **Free Mode:** Try out Free in '/connect' to get a great agentic coding experience in Claurst for absolutely free (or as good as free gets you :P). `[EXPERIMENTAL]`
3635
>
37-
> - Speech modes: Try `/rocky` and `/caveman` to hear the difference! `/normal` to go back.
36+
> - **/goal support:** Try out `/goal <objective>` to see claurst keep working an objective, spanning multiple turns instead of stopping after one normal turn. `[EXPERIMENTAL]`
3837
3938
---
4039

public/session/index.html

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Claurst Session Viewer</title>
7+
<style>
8+
:root { color-scheme: dark; }
9+
html, body { margin: 0; padding: 0; height: 100%; }
10+
body {
11+
background: #1a1a1f;
12+
color: #e6e6ea;
13+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
14+
}
15+
#status {
16+
display: flex;
17+
align-items: center;
18+
justify-content: center;
19+
height: 100%;
20+
padding: 24px;
21+
text-align: center;
22+
box-sizing: border-box;
23+
}
24+
#status .inner { max-width: 520px; }
25+
#status h1 { font-size: 18px; margin: 0 0 8px 0; font-weight: 600; }
26+
#status p { color: #8a8a96; margin: 6px 0; line-height: 1.5; }
27+
#status a, #status code { color: #6b9bff; }
28+
#status code {
29+
background: #23232b;
30+
padding: 1px 6px;
31+
border-radius: 3px;
32+
font-family: ui-monospace, "SF Mono", Menlo, monospace;
33+
font-size: 13px;
34+
}
35+
iframe#viewer {
36+
display: none;
37+
border: 0;
38+
width: 100%;
39+
height: 100vh;
40+
}
41+
</style>
42+
</head>
43+
<body>
44+
<div id="status" role="status" aria-live="polite">
45+
<div class="inner">
46+
<h1 id="status-title">Loading session…</h1>
47+
<p id="status-detail">Fetching gist contents from GitHub.</p>
48+
</div>
49+
</div>
50+
<iframe id="viewer" title="Claurst session" sandbox="allow-scripts allow-popups allow-same-origin"></iframe>
51+
<script>
52+
(async function () {
53+
var status = document.getElementById('status');
54+
var titleEl = document.getElementById('status-title');
55+
var detailEl = document.getElementById('status-detail');
56+
var viewer = document.getElementById('viewer');
57+
58+
function fail(title, html) {
59+
titleEl.textContent = title;
60+
detailEl.innerHTML = html;
61+
}
62+
63+
var id = (location.hash || '').replace(/^#/, '').trim();
64+
if (!id) {
65+
fail(
66+
'No session selected',
67+
'Append a gist id to the URL, e.g. <code>/session/#&lt;gist-id&gt;</code>.'
68+
);
69+
return;
70+
}
71+
if (!/^[a-f0-9]{6,}$/i.test(id)) {
72+
fail('Invalid gist id', 'The fragment after <code>#</code> does not look like a GitHub gist id.');
73+
return;
74+
}
75+
76+
try {
77+
var res = await fetch('https://api.github.com/gists/' + encodeURIComponent(id), {
78+
headers: { 'Accept': 'application/vnd.github+json' }
79+
});
80+
if (res.status === 404) {
81+
fail('Gist not found', 'The link may be wrong, or the gist may have been deleted.');
82+
return;
83+
}
84+
if (res.status === 403) {
85+
fail(
86+
'Rate-limited by GitHub',
87+
'Wait a minute and refresh — anonymous GitHub API calls are rate-limited.'
88+
);
89+
return;
90+
}
91+
if (!res.ok) {
92+
fail('Unable to load gist', 'GitHub returned status ' + res.status + '.');
93+
return;
94+
}
95+
var gist = await res.json();
96+
var files = gist.files || {};
97+
var htmlFile = null;
98+
var names = Object.keys(files);
99+
for (var i = 0; i < names.length; i++) {
100+
var f = files[names[i]];
101+
if (f && f.filename && /\.html?$/i.test(f.filename)) { htmlFile = f; break; }
102+
}
103+
if (!htmlFile) {
104+
fail('Not a Claurst session', 'No HTML file was found in this gist.');
105+
return;
106+
}
107+
var content = htmlFile.content || '';
108+
if (htmlFile.truncated && htmlFile.raw_url) {
109+
var r2 = await fetch(htmlFile.raw_url);
110+
if (r2.ok) content = await r2.text();
111+
}
112+
viewer.srcdoc = content;
113+
viewer.style.display = 'block';
114+
status.style.display = 'none';
115+
} catch (e) {
116+
fail('Network error', String(e && e.message ? e.message : e));
117+
}
118+
})();
119+
</script>
120+
</body>
121+
</html>

0 commit comments

Comments
 (0)