[2026.04 Week 4] Five Trending Repos of the Week
TL;DR
Claude Code skill packs still dominated trending. Around 30 of the top 100 repos trending on GitHub this week were skill collections, agent setups, or Claude Code recipe bundles.
AI sandbox and execution tooling pushed back. CubeSandbox, smolvm, browser-harness, and chrome-devtools-mcp all kept trending around giving agents a controlled execution surface.
Token-cost and context-optimisation tools kept showing up. caveman, context-mode, claude-context, code-review-graph, GitNexus, and graphify all trended together with “cut tokens by X%” pitches.
Financial-data tools made the trending list. Kronos and FinceptTerminal both trended this week, hinting that LLM-style approaches to market data are going mainstream.
This week’s picks:
perry (⭐ 1.8k). Native TypeScript compiler in Rust. Compiles
.tsstraight to a self-contained executable. There is no V8 in the binary; the standard library is reimplemented in Rust.browser-harness (⭐ 7.1k). Browser-use’s deliberately small sibling. A long-lived daemon sits between any number of LLM-written Python snippets and one Chrome session, hiding stale CDP sessions from the agent.
hyperframes (⭐ 11.3k). HeyGen’s HTML-to-video framework. A composition is a single HTML file with
data-start/data-durationattributes, which is exactly the format an LLM can author and edit in one prompt.Kronos (⭐ 21.6k). Open-source foundation model for K-line (candlestick) data.
CubeSandbox (⭐ 4.2k). Tencent’s Rust-based microVM sandbox for AI agents. The request path from REST call to a booted microVM is worth tracing.
PerryTS/perry
⭐ 1.8k · Rust
Perry compiles TypeScript directly to a native executable. SWC (a Rust-based TypeScript parser) reads the source, Perry lowers to its own HIR (a desugared, type-aware intermediate form between AST and LLVM IR), perry-codegen emits LLVM IR (the intermediate representation Clang, Rust, and Swift all target), and cc links the result. There is no V8 in the binary. The standard library is a Rust crate (perry-stdlib) that reimplements Node APIs (fs, fetch, mysql2, redis, ws, mongodb, fastify).
That raises a hard question. JavaScript code is full of await and setTimeout. There is no Node event loop in a Perry binary, so what does the main thread block on? Earlier versions called js_sleep_ms(10.0) in a hot loop, which capped cross-thread async latency at half the quantum. Perry replaced that with a Condvar-based pump.
crates/perry-runtime/src/event_pump.rs:32-97
struct Pump { flag: Mutex<bool>, cvar: Condvar }
static PUMP: Pump = Pump { flag: Mutex::new(false), cvar: Condvar::new() };
const IDLE_CAP_MS: u64 = 1000;
#[no_mangle]
pub extern "C" fn js_notify_main_thread() {
let mut flag = PUMP.flag.lock().unwrap();
*flag = true;
drop(flag);
PUMP.cvar.notify_one();
}
#[no_mangle]
pub extern "C" fn js_wait_for_event() {
let mut budget_ms: u64 = IDLE_CAP_MS;
for d in [js_timer_next_deadline(), js_callback_timer_next_deadline(),
js_interval_timer_next_deadline()] {
if d >= 0.0 { let d_ms = d as u64; if d_ms < budget_ms { budget_ms = d_ms; } }
}
let mut flag = PUMP.flag.lock().unwrap();
if *flag { *flag = false; return; }
if budget_ms == 0 { return; }
let (mut new_flag, _) = PUMP.cvar
.wait_timeout(flag, Duration::from_millis(budget_ms)).unwrap();
*new_flag = false;
}The main thread is single-threaded JS. When code awaits a Promise, the generated code calls js_wait_for_event(), which sleeps on the condvar until either the next timer is due or some background tokio worker calls js_notify_main_thread() after pushing a result into a queue. The flag-before-wait pattern is what survives a notify that races the lock acquire.
The twist is on the producer side. Async stdlib functions (a Mongo query, an HTTP request) spawn into a tokio runtime, but they cannot return a JSValue from a worker thread. JSValues live in a per-thread arena, and one allocated by a worker would corrupt the main thread’s heap. So spawn_for_promise_deferred (crates/perry-stdlib/src/common/async_bridge.rs:343) takes the future plus a converter closure. The future returns raw Rust data (Option<String>, a Vec, a number) and the converter runs on the main thread inside the deferred-resolution drain to turn it into a JSValue.
browser-use/browser-harness
⭐ 7.1k · Python
browser-harness is browser-use’s deliberately small sibling. The README pitches it as “self-healing,” but the self-healing is structural, not retry-loop logic. The whole harness is one file (daemon.py, 258 lines) plus helper functions (helpers.py) the agent imports.
The architecture inverts the usual “spawn a browser per script” model. A single daemon holds one CDP WebSocket to Chrome, exposes a Unix socket at /tmp/bu-{name}.sock, and accepts requests from any number of short-lived Python processes the LLM might spawn. (CDP, the Chrome DevTools Protocol, is the JSON-over-WebSocket wire protocol Chrome speaks to its own dev tools.) Different agent runs share or isolate themselves by setting BU_NAME.
method = req["method"]
params = req.get("params") or {}
# Browser-level Target.* calls must not use a session (stale or otherwise).
# For everything else, explicit session in req wins; else default.
sid = None if method.startswith("Target.") \
else (req.get("session_id") or self.session)
try:
return {"result": await self.cdp.send_raw(method, params, session_id=sid)}
except Exception as e:
msg = str(e)
if "Session with given id not found" in msg and sid == self.session and sid:
log(f"stale session {sid}, re-attaching")
if await self.attach_first_page():
return {"result": await self.cdp.send_raw(
method, params, session_id=self.session)}
return {"error": msg}That except block is the harness’s load-bearing line. CDP sessions die for boring reasons (the page navigated, the tab was closed, Chrome restarted a tab on out-of-memory). A Playwright-shaped script would crash and leave the agent guessing. Here the daemon catches the “Session with given id not found” string, runs attach_first_page() which finds a real page (anything that is not chrome://, devtools://, or an extension popup), creates a fresh session id, and replays the original CDP call. The Python snippet never sees the failure.
Two more design choices reinforce the long-lived daemon model. CDP events are pushed into a 500-entry ring buffer (deque(maxlen=BUF)) the agent drains with meta=drain_events. And every Page.loadEventFired triggers a Runtime.evaluate that prepends a green circle to the page title ('\U0001F7E2 ' + document.title). The next agent looking at a screenshot can see at a glance that the page has settled, no document.readyState polling needed.
The whole thing talks raw CDP via cdp_use.CDPClient. There is no Puppeteer or Playwright underneath, which is what keeps the boundary thin enough to fit in 250 lines.
heygen-com/hyperframes
⭐ 11.3k · TypeScript
hyperframes’ pitch is “Write HTML, render video.” The shape of the input file is the thesis. A composition is a single HTML document with a <div data-composition-id> root, child clips with data-start / data-duration attributes, GSAP timelines for animation, and CSS for appearance. The engine (Puppeteer + FFmpeg) seeks GSAP frame-by-frame and streams rgb48le frames into the encoder.
That format choice is what makes hyperframes interesting for agents. LLMs write HTML fluently. Remotion forces them onto React + a bundler; hyperframes lets them emit and edit one file.
registry/examples/product-promo/index.html:57-77
<body>
<div id="root" data-composition-id="main"
data-start="0" data-duration="20"
data-width="1920" data-height="1080">
<!-- Scene 1: Logo Intro -->
<div id="scene-1" class="scene"
data-composition-id="scene1-logo-intro"
data-composition-src="compositions/scene1-logo-intro.html"
data-start="0" data-duration="1.5"
data-track-index="1"
data-width="1920" data-height="1080"></div>
<!-- Scene 2-4: Continuous Canvas -->The whole video lives in data-* attributes the agent can compute and rewrite without parsing any AST. Sub-compositions reference a separate file via data-composition-src, so an agent builds a multi-scene video by stitching pre-existing block files (registry/blocks/data-chart, flowchart, logo-outro, plus 50+ shader transitions) into a parent composition.
The agent surface goes further than CLI flags. The skill bundle in skills/hyperframes/SKILL.md gates the agent through a real workflow. Before any HTML is written, the skill checks for a DESIGN.md and refuses default greys (#333, #3b82f6, Roboto) so the output does not look generic. Then layout-before-animation. Build the static end frame as CSS, then add gsap.from(...) entrances and gsap.to(...) exits against that ground truth. The whole loop is lint → validate → preview → render, every step a CLI command an agent can call.
This is what HeyGen wanted. The same HTML their AI avatars are rendered against can be authored, tweaked, and re-rendered by an agent in one prompt cycle.
shiyu-coder/Kronos
⭐ 21.6k · Python
Kronos is a decoder-only foundation model for K-line (OHLCV candlestick) sequences. It ships at four sizes (4.1M / 24.7M / 102.3M / 499.2M params), three of them open on Hugging Face Hub, accessible via Kronos.from_pretrained("NeoQuasar/Kronos-small"). The README calls it a “language model for markets.” The fine-tuning flow is where it gets unusual.
Most LLM workflows assume “load pretrained, fine-tune the head.” Kronos splits the work in two. The tokenizer must learn your asset class before the predictor sees a single batch.
finetune/train_predictor.py:95-109
for i, (batch_x, batch_x_stamp) in enumerate(train_loader):
batch_x = batch_x.to(device, non_blocking=True)
batch_x_stamp = batch_x_stamp.to(device, non_blocking=True)
# Tokenize input data on-the-fly
with torch.no_grad():
token_seq_0, token_seq_1 = tokenizer.encode(batch_x, half=True)
token_in = [token_seq_0[:, :-1], token_seq_1[:, :-1]]
token_out = [token_seq_0[:, 1:], token_seq_1[:, 1:]]
logits = model(token_in[0], token_in[1], batch_x_stamp[:, :-1, :])
loss, s1_loss, s2_loss = model.module.head.compute_loss(
logits[0], logits[1], token_out[0], token_out[1])Two things stand out. First, with torch.no_grad(): tokenizer.encode(...) runs inside the predictor training loop. The tokenizer is frozen and acts as a read-only encoder. It must already match the distribution of batch_x because no gradient flows back into it. Second, the encoder returns two token streams (token_seq_0, token_seq_1). Kronos uses Binary Spherical Quantization that produces a coarse s1 token plus a fine s2 token per K-line, and the model predicts both with cross-entropy on each (s1_loss + s2_loss).
That is why fine-tuning is two stages. train_tokenizer.py first fits the BSQ codebook to your dataset (tokenizer_learning_rate=2e-4 in finetune/config.py). Crypto, US equities, and Chinese A-shares all have different price granularity and volatility regimes, and the codebook has to capture that before the predictor can predict anything sensible. Then train_predictor.py runs with the frozen tokeniser at a much lower rate (predictor_learning_rate=4e-5).
TencentCloud/CubeSandbox
⭐ 4.2k · Rust
CubeSandbox is Tencent’s E2B-API-compatible sandbox runtime. Each sandbox is a Cloud-Hypervisor microVM with its own kernel. The team claims cold start under 60ms and per-instance memory under 5MB. The system is split across CubeAPI (Rust HTTP), CubeMaster (Go scheduler), Cubelet (Go per-node agent), CubeNet (eBPF dataplane), and an in-VM Rust agent talking ttrpc over vsock.
What happens when an agent calls sandbox.create() is interesting. CubeAPI’s handler turns the E2B-shaped request into an internal one and forwards it to CubeMaster.
CubeAPI/src/handlers/sandboxes.rs:292-345
pub async fn create_sandbox(
State(state): State<AppState>,
Json(body): Json<NewSandbox>,
) -> AppResult<impl IntoResponse> {
let mut annotations: HashMap<String, String> = HashMap::new();
annotations.insert("cube.master.appsnapshot.template.id".to_string(),
body.template_id.clone());
annotations.insert("cube.master.appsnapshot.template.version".to_string(),
"v2".to_string());
let req = CreateSandboxRequest {
request_id: Uuid::new_v4().to_string(),
instance_type: state.config.instance_type.clone(),
timeout: Some(body.timeout),
annotations, labels,
volumes: None,
containers: vec![],
exposed_ports: vec![],
network_type: Some("tap".to_string()),
cubevs_context: build_cubevs_context(body.allow_internet_access,
body.network.as_ref()),
};
let resp = state.cubemaster.create_sandbox(&req).await.map_err(|e| {
AppError::Internal(anyhow::anyhow!(e.to_string()))
})?;CubeMaster receives the request and runs its scheduler, which is recognizably K8s-shaped without the rest of K8s.
CubeMaster/pkg/scheduler/schedule.go:25-57
func Select(selCtx *selctx.SelectorCtx) (nodes *node.Node, err error) {
if err := runPreFilter(selCtx); err != nil {
if shouldSkipBackoffForTemplate(selCtx) { return nil, err }
if err = runBackoffFilter(selCtx); err != nil { return nil, err }
}
if err := runFilter(selCtx, scheduler.filter); err != nil {
if shouldSkipBackoffForTemplate(selCtx) { return nil, err }
return BackoffSelect(selCtx)
}
if err := runScoreFilter(selCtx, scheduler.score); err != nil {
return nil, err
}
return selCtx.LeastRandomSelect(
config.GetConfig().Scheduler.PrioritySelectNum), nil
}PreFilter narrows to nodes that have the template’s snapshot. Filter prunes by capacity and per-template create-rate limits. ScoreFilter ranks the survivors. LeastRandomSelect picks the lightest-loaded node with random tie-breaking among the top-N. If filters wipe the slate, BackoffSelect falls back to a separately maintained pool.
Once a Cubelet is chosen, it does not boot a kernel from scratch. It clones a pre-built rootfs disk via cp --reflink=always against a base image that was formatted with mkfs.ext4 -O ^has_journal (sandboxes are ephemeral, so the journal is just overhead). Cloud Hypervisor boots the new disk, the in-VM cube-agent registers itself over vsock, and CubeAPI returns the sandbox_id to the caller. Subsequent run_code calls land as ttrpc ExecProcess messages against the same vsock channel; the agent forks an OCI container under rustjail and pipes stdout back.
What makes “60ms” possible is that almost nothing on this path actually computes. The kernel was prebuilt, the rootfs is a reflink, the network is an attached TAP whose eBPF program (from_cube in CubeNet) is already loaded, and the only fresh bytes are a UUID and an annotation map.

