# Education (/docs/about/education)
# Education [#education]
## University of Toronto [#university-of-toronto]
### Honours Bachelor of Science (2017 Sep. - 2022 Jun.) [#honours-bachelor-of-science-2017-sep---2022-jun]
**Computer Science Specialist**
* Artificial Intelligence
* Computer Vision
* Web and Internet Technologies
**Statistics Major**
### Master of Science (2022 Sep. - 2023 Nov.) [#master-of-science-2022-sep---2023-nov]
Research on reliability of Computer Vision models
## Published Papers [#published-papers]
1. **Assessing Visually-Continuous Corruption Robustness of Neural Networks Relative to Human Performance**, H. Shen, B. C. Hu, K. Czarnecki, L. Marsso, M. Chechik, IEEE/CVF Winter Conference on Applications of Computer Vision (WACV 2025)
* [arXiv](https://arxiv.org/abs/2402.19401)
* [CVF Open Access](https://openaccess.thecvf.com/content/WACV2025/html/Shen_Assessing_Visually-Continuous_Corruption_Robustness_of_Neural_Networks_Relative_to_Human_WACV_2025_paper.html)
2. **If a Human Can See It, So Should Your System: Reliability Requirements for Machine Vision Components**, B. C. Hu, L. Marsso, K. Czarnecki, R. Salay, H. Shen, M. Chechik, the 44th International Conference on Software Engineering (ICSE 2022)
* [arXiv](https://arxiv.org/abs/2202.03930)
* [ICSE 2022](https://conf.researchr.org/details/icse-2022/icse-2022-papers/72/If-a-Human-Can-See-It-So-Should-Your-System-Reliability-Requirements-for-Machine-Vi)
# About Me (/docs/about)
# About Me [#about-me]
My name is **Huakun Shen**, a programmer.
> Talk is cheap, show me the code. I love coding, and making ideas come true.
## Photography [#photography]
I love aerial photography. Check out my [Sky Pixel Profile](https://www.skypixel.com/users/djiuser-j1togd4cot0z) for photos I've taken with drones.
## GitHub Contribution [#github-contribution]
## Connect [#connect]
* **GitHub**: [HuakunShen](https://github.com/HuakunShen)
* **Twitter**: [@HuakunShen](https://twitter.com/HuakunShen)
* **Instagram**: [@huakunshen](https://instagram.com/huakunshen)
* **LinkedIn**: [huakun-shen](https://www.linkedin.com/in/huakun-shen/)
* **YouTube**: [Huakun Shen](https://www.youtube.com/channel/UC1gJeFbvRcQXDC_C8nKetdA)
# Skills (/docs/about/skills)
# Skills [#skills]
## Languages [#languages]
| Language | Description |
| --------------- | -------------------------------------------------------------- |
| **Python** | Machine Learning, Data Science, and prototyping |
| **Rust** | Desktop apps, high performance apps, and system-level programs |
| **JavaScript** | Web development |
| **TypeScript** | Primary choice over JavaScript for type safety |
| **Bash** | Linux scripting and commands (daily Linux user) |
| **SQL** | Database querying with ORMs (Prisma, TypeORM, SQLAlchemy) |
| **Golang** | High-performance microservices and system-level APIs |
| **Java** | Software Design course TA experience |
| **C** | System Programming course TA experience |
| **C++** | High-performance algorithms (back testing, huffman encoding) |
| **WebAssembly** | Cross-platform universal libraries from Rust |
## Frameworks [#frameworks]
| Framework | Description |
| ---------------------- | -------------------------------------------------------- |
| **React & Next.js** | First modern UI framework learned |
| **Vue & Nuxt.js** | Second UI framework; built many web/desktop apps |
| **Svelte & SvelteKit** | Favorite UI framework in terms of design |
| **Flask** | Prototyping simple web APIs |
| **Django** | Building more serious APIs |
| **Streamlit** | ML/Quant project prototyping and visualization |
| **Tauri** | Cross-platform desktop apps (Rust backend, web frontend) |
| **Electron** | Extensible cross-platform desktop applications |
## Libraries [#libraries]
| Library | Description |
| ---------------- | ----------------------------------------------------- |
| **Tailwind CSS** | Most used CSS framework for flexibility |
| **Three.js** | 3D web models with react-three/fiber, TresJS, Threlte |
| **PyTorch** | Machine Learning |
## Databases [#databases]
| Database | Description |
| ------------------------------- | ------------------------------------------------------- |
| **MySQL / PostgreSQL / SQLite** | Data persistence across apps and services |
| **MongoDB** | Document-based data persistence |
| **Neo4j** | Graph-like data storage |
| **Redis** | Caching and pub-sub distributed communication |
| **Prisma** | Favorite ORM supporting SQL and MongoDB with TypeScript |
## DevOps & Cloud [#devops--cloud]
| Technology | Description |
| -------------------- | ----------------------------------------- |
| **CI/CD** | Auto-testing and auto-deployment |
| **GitHub Actions** | Most used CI/CD tool |
| **GCP Cloud Build** | Docker builds and Cloud Run deployment |
| **Docker** | Containerization for distribution |
| **AWS** | S3, EC2, Lambda |
| **GCP** | Cloud Run for container deployment |
| **Cloudflare** | Pages, Workers, Tunnel |
| **Firebase** | Authentication and data storage |
| **Kafka** | Asynchronous actions and notifications |
| **Nginx** | Reverse proxy with SSL and load balancing |
| **Vercel / Netlify** | Web app deployment |
## Design & Other [#design--other]
| Skill | Description |
| ----------------------- | --------------------------------------------------- |
| **System Design** | Large-scale systems ready to scale up |
| **Software Design** | Following best practices for code elegance |
| **Web UI Design** | Building nice-looking interfaces |
| **Video Editing** | FCP, DaVinci, Premiere Pro for YouTube |
| **3D Printing** | Personal hobby - creating custom designs |
| **3D Modeling** | Building models when not available online |
| **Piano** | Amateur player |
| **Homelab** | Self-hosting services (Plex, VPN, NAS, smart home) |
| **Web Scraping** | Data extraction for analysis |
| **Penetration Testing** | Security vulnerability discovery |
| **Drone Photography** | Aerial cinematography with cinematic and FPV drones |
# Huakun (/docs)
# Huakun [#huakun]
**A programmer passionate about building things.**
> Talk is cheap, show me the code. I love coding, and making ideas come true.
## Connect with Me [#connect-with-me]
* **GitHub**: [HuakunShen](https://github.com/HuakunShen)
* **Twitter**: [@HuakunShen](https://twitter.com/HuakunShen)
* **Instagram**: [@huakunshen](https://instagram.com/huakunshen)
* **LinkedIn**: [huakun-shen](https://www.linkedin.com/in/huakun-shen/)
* **YouTube**: [Huakun Shen](https://www.youtube.com/channel/UC1gJeFbvRcQXDC_C8nKetdA)
## Explore [#explore]
Check out my open-source projects including Kunkun, CrossCopy, and more.
Learn more about my background, education, and skills.
## GitHub Contribution [#github-contribution]
# 3D Path Planning Algorithm (/docs/projects/archived/3D-path-planning-algorithm)
GitHub: [https://github.com/HuakunShen/3D-Planning-Algorithm-Visualization](https://github.com/HuakunShen/3D-Planning-Algorithm-Visualization)
> This project is implements a few popular Path Planning Algorithm in 3D as well as a visualizer for visualizing the environment and result.
## Tech Stack [#tech-stack]
* Python
* Plotly
# 2048 AI (/docs/projects/archived/AI-2048AI)
> Make game 2048 with Pygame and play it with AI + Machine Learning
[GitHub](https://github.com/HuakunShen/2048AI)

## Tech Stack [#tech-stack]
* Python
* Pygame
* Non-ML AI Algorithm
* Machine Learning/Reinforcement Learning
# Git Skyline (/docs/projects/archived/GitSkyline)
Website: [https://git-skyline.huakun.tech/](https://git-skyline.huakun.tech/)
GitHub: [https://github.com/HuakunShen/git-skyline](https://github.com/HuakunShen/git-skyline)

This is a full-stack project trying to clone [https://skyline.github.com/](https://skyline.github.com/).
[https://skyline.github.com/](https://skyline.github.com/) is a cool feature of GitHub that shows your contribution graph in 3D but it stops working, and I decided to built my own version of it.
## Features [#features]
* Show GitHub contribution graph in 3D given any username
* I provide transparent background so that you can embed it in your website using iframe
Here is an example of embedding it in my website:
```html
```
# MyWeb (/docs/projects/archived/MyWeb)
# MyWeb [#myweb]
[https://huakunshen.com](https://huakunshen.com)
My personal website. With my skills, project portfolio, an AI chat bot and some other stuff.
[https://github.com/HuakunShen/MyWeb](https://github.com/HuakunShen/MyWeb)
## Tech Stack [#tech-stack]
* Nuxt
* Vue
* Tailwind CSS
* TypeScript
* Threejs
# TicketDapp (/docs/projects/archived/TicketDapp)
# TicketDapp [#ticketdapp]
A blockchain decentralized application for ticketing.
# Acorn Parser (/docs/projects/archived/acorn-parser)
Academic History Chrome Extension
> Description: A Chrome Extension allowing UofT students to calculate average GPA, download academic history in json. The goal is to provide student with a easier interface to have a understanding of their grade.
[GitHub](https://github.com/HuakunShen/Acorn-ParserExtension)
## Tech Stack [#tech-stack]
* [Vue](https://vuejs.org/)
* Chrome Extension
* [Element Plus](https://element-plus.org/en-US/)
# Android App (Game Center) (/docs/projects/archived/android-game-center)
> Description: An android app (school project, CSC207, Software Design) of game centre, containing 3 games (Sudoku, Sliding Tiles, Picture Match)
[Android Game Center](https://github.com/HuakunShen/AndroidApp_Game_Centre)
## Tech Stack [#tech-stack]
* Java
* Android
## Demo [#demo]
# Applications Rust (/docs/projects/archived/applications-rs)
# applications-rs [#applications-rs]
> This crate is used to
>
> * get a list of installed applications on the system
> * get the frontmost application
> * get a list of running applications
## Platforms [#platforms]
* [x] Mac
* [x] Linux
* [x] Windows
## Usage [#usage]
```rust
use applications::{common::SearchPath, AppInfo, AppInfoContext, AppTrait};
fn main() {
let mut ctx = AppInfoContext::new(vec![SearchPath::new(
std::path::PathBuf::from("/home/user/..."),
1,
)]);
ctx.refresh_apps().unwrap(); // must refresh apps before getting them
let apps = ctx.get_all_apps();
println!("Apps: {:#?}", apps);
let frontmost_app = ctx.get_frontmost_application().unwrap();
println!("Frontmost App: {:#?}", frontmost_app);
let running_apps = ctx.get_running_apps();
println!("Running Apps: {:#?}", running_apps);
}
```
## How? [#how]
> How and where to search for available desktop applications on each platform?
### Linux [#linux]
Desktop applications are specified in files that ends with `.desktop`. `echo $XDG_DATA_DIRS` to see a list of paths where these desktop files could reside in.
The `.desktop` files are in toml format. Parse them with [toml](https://crates.io/crates/toml) crate.
The `Exec` can be used to launch the app, and `Icon` field contains the app icon.
### MacOS [#macos]
The simplest way is to search in `/Applications` folder. The app icon is in `.icns` format.
Apple silicon macs can now run iOS apps. iOS app icons are in `.png` format.
`system_profiler` command can be used to get installed applications.
`system_profiler SPApplicationsDataType` is the command to use to get a full list of applications.
### Windows [#windows]
[https://crates.io/crates/winreg](https://crates.io/crates/winreg) could be useful. Ask chatgpt for sample code.
## Libraries [#libraries]
* [https://crates.io/crates/icns](https://crates.io/crates/icns): Read and write icns files, convert into PNG format.
# Binance Data Loader (/docs/projects/archived/binance-data-loader)
> A Python library for downloading and processing historical data from Binance Vision.
**GitHub:** [https://github.com/HuakunShen/binance-data-loader](https://github.com/HuakunShen/binance-data-loader)\
**PyPI:** [https://pypi.org/project/binance-data/](https://pypi.org/project/binance-data/)
## Features [#features]
* Download historical data from Binance Vision S3 bucket
* Support for multiple asset types (spot, futures)
* Flexible prefix-based approach for any data type
* Output formats: **Parquet** (default) or CSV
* **Pandera schema validation** for data integrity
* Timestamp auto-detection (milliseconds vs nanoseconds)
* **Concurrent downloads** for better performance
* Optional retention of raw ZIP files
* Preserve original directory structure
## Installation [#installation]
```bash
pip install binance-data
# Or with uv
uv pip install binance-data
```
## Quick Start [#quick-start]
```python
from binance_data_loader import BinanceDataDownloader
# Download BTCUSDT 1h futures data as Parquet
downloader = BinanceDataDownloader(
prefix="data/futures/um/daily/klines/BTCUSDT/1h/",
destination_dir="./data",
output_format="parquet",
)
downloader.download()
```
## Data Loading & Resampling [#data-loading--resampling]
```python
from binance_data_loader import BinanceDataLoader
from datetime import datetime, timedelta, UTC
loader = BinanceDataLoader(data_dir="./data", data_type="spot")
# Load with resampling
df = loader.load(
symbol="BTCUSDT",
interval="1m",
resample_to="15m",
start_time=datetime.now(UTC) - timedelta(days=7),
)
```
## Supported Intervals [#supported-intervals]
* Seconds: `1s`
* Minutes: `1m`, `3m`, `5m`, `15m`, `30m`
* Hours: `1h`, `2h`, `4h`, `6h`, `8h`, `12h`
* Days: `1d`, `3d`
* Weeks: `1w`
* Months: `1M`
## Shifted Resampling [#shifted-resampling]
Generate multiple shifted datasets for training data augmentation:
```python
# Default 15m intervals end at 0, 15, 30, 45 minutes
df_standard = loader.load(symbol="ETHUSDT", interval="1m", resample_to="15m")
# Shifted by 1m - intervals end at 1, 16, 31, 46 minutes
df_shifted = loader.load(
symbol="ETHUSDT", interval="1m", resample_to="15m", shift="1m"
)
```
Perfect for machine learning training with data augmentation.
## Data Schema [#data-schema]
Kline data columns: `open_time`, `open`, `high`, `low`, `close`, `volume`, `close_time`, `quote_volume`, `count`, `taker_buy_volume`, `taker_buy_quote_volume`, `ignore`
A Python library for quantitative trading data preparation.
# Brain (/docs/projects/archived/brain)
# Brain [#brain]
My knowledge base and blog written in Markdown, and built with [Docusaurus](https://docusaurus.io/).
[https://brain.huakunshen.com/](https://brain.huakunshen.com/)
## Tech Stack [#tech-stack]
* Docusaurus
* Markdown
* React
* TypeScript
# Campground Display Gallery (/docs/projects/archived/campground-gallary)
# Campground Gallery [#campground-gallery]
> This is a practice web development app, displaying campground image and information.
>
> This is my first web dev project, no longer maintaining it. See GitHub repo for some screenshots.
[GitHub](https://github.com/HuakunShen/Web_Campgrounds)
## Tech Stack [#tech-stack]
* Node.js
* Express
* EJS
* MongoDB
* Bootstrap
* Heroku
# CV Canny Edge Detection (/docs/projects/archived/canny-edge-detection)
# Canny Edge Detection [#canny-edge-detection]
> Canny Edge Detection Program for detecting edges in images
[GitHub](https://github.com/HuakunShen/ComputerVision-CannyEdge)
## Tech Stack [#tech-stack]
* Python
# Chrome Extension Template with TypeScript + Vue3 (/docs/projects/archived/chrome-ext-ts-vue3-template)
# Chrome Extension Vue3 TS Template [#chrome-extension-vue3-ts-template]
> Chrome Extension Template implemented with TypeScript + Vue3
[GitHub](https://github.com/HuakunShen/chrome-ext-vue3-ts)
## Tech Stack [#tech-stack]
* [Vue](https://vuejs.org/)
* [TypeScript](https://www.typescriptlang.org/)
* Chrome Extension
# CLI Video Length Calculator (/docs/projects/archived/cli-video-length-calculator)
# CLI Video Length Calculator [#cli-video-length-calculator]
> A command line Video Length calculator, can calculate a video's length, or the total length of videos in a given directory.
[GitHub](https://github.com/HuakunShen/Toolbox/#videolen)


Written completely in bash ([https://github.com/HuakunShen/Toolbox/blob/master/bin/videoLen](https://github.com/HuakunShen/Toolbox/blob/master/bin/videoLen)), no dependencies.
## Story [#story]
I was watching OSCP tutorial videos which consists of many videos. I wanted to know how long it would take to finish all the videos and how long is each chapter. I couldn't find a tool that can do this, so I wrote one myself.
## Tech Stack [#tech-stack]
* Bash
# Clipboard Listener (/docs/projects/archived/clipboard-listener)
# Clipboard Listener [#clipboard-listener]
NodeJS doesn't have package for reading clipboard image and listening to clipboard.
I created this package to solve this problem with a Golang package.
GitHub Repo: [https://github.com/HuakunShen/general-clipboard-listener](https://github.com/HuakunShen/general-clipboard-listener)
GitHub Repo: [https://github.com/CrossCopy/clipboard](https://github.com/CrossCopy/clipboard)
> A Cross-Platform clipboard listener that listens for both text and image (screenshots).
> Designed for NodeJS, not for web.
> Provides API to read and write text/image from/to clipboard.
npm package: [https://www.npmjs.com/package/@crosscopy/clipboard](https://www.npmjs.com/package/@crosscopy/clipboard)
## Tech Stack [#tech-stack]
* Golang
* NodeJS
* TypeScript
## Sample Usage [#sample-usage]
```ts
import clipboardEventListener from "@crosscopy/clipboard";
console.log(clipboard.readTextSync());
console.log(await clipboard.readText());
const imgBuf = clipboard.readImageSync();
// console.log(imgBuf.toString("base64"));
// console.log(clipboard.readImageBase64Sync());
// await clipboard.writeImage(base64img); // add fake image to clipboard
clipboard.writeImageSync(base64img); // add fake image to clipboard
console.log(""); // give some time
console.assert(clipboard.readImageBase64Sync() === base64img);
// * test readimage
clipboard.writeImageSync(base64img);
console.log();
console.assert((await clipboard.readImage()).toString("base64") === base64img);
await clipboard.writeImage(base64img);
console.log();
console.assert((await clipboard.readImageBase64()) === base64img);
clipboard.on("text", (text) => {
console.log(text);
});
clipboard.on("image", (data) => {
fs.writeFileSync("test.png", data);
});
clipboard.listen();
setTimeout(() => {
clipboard.close();
}, 10000);
```
# Cloudinary Image Uploader (/docs/projects/archived/cloudinary-image-uploader)
# Cloudinary Image Uploader [#cloudinary-image-uploader]
> This is just a practice project for learning uploading media to Cloudinary when I first started learning web dev. It's not interesting at all.
> Image Uploader built with React for front-end, Nodejs\&Express for backend and Cloudinary for storage.
[GitHub](https://github.com/HuakunShen/Image-Uploader-React-Express-Cloudinary)
# Condos Crawler (/docs/projects/archived/condos-scraper)
> A web crawler that can download real estate (home) sales data from Condos website.
>
> This project was for a data analysis task on Toronto house price
[GitHub Repo](https://github.com/HuakunShen/condos-crawler)
## Tech Stack [#tech-stack]
* Python
* Scrapy
# Drag And Drop Image Uploader with AWS S3 (/docs/projects/archived/drag-n-drop-aws-image-upload)
# Drag And Drop Image Uploader with AWS S3 [#drag-and-drop-image-uploader-with-aws-s3]
> This is a demo project I made to show how to upload images to AWS S3 with a React frontend and Express backend.
[GitHub Repo](https://github.com/HuakunShen/Drag-and-Drop-Image-Uploader-With-AWS-S3)
## Tech Stack [#tech-stack]
* React
* Express
* AWS S3
* Multer
# Dynamic CLI Progress Bar (/docs/projects/archived/dynamic-cli-progress-bar)
# Dynamic CLI Progress Bar [#dynamic-cli-progress-bar]
> Dynamic Command Line Progress Bar, can be used by other apps to display progress bar with custom styles
[GitHub](https://github.com/HuakunShen/Toolbox/#progress)


## Example [#example]
I use the progress bar in my video length calculator bash script.

## Tech Stack [#tech-stack]
* Bash
# EzUp (/docs/projects/archived/ezup)
# EzUp [#ezup]
> A quick file/image uploaded built with Tauri (Rust + SvelteKit)
* Main purpose: a imagebed client, I use it for writing blog and notes in Markdown
* I take screenshot all the time, saving screenshots as files and moving them is too time consuming, and takes lots of space in git repo.
* Images from other website can also to uploaded to my own imagebed as a mirror, in case original images were removed, then references on my website will expire too.
* [GitHub](https://github.com/huakunshen/ezup)
* I you have a image file path, screnshot in your clipboard, or a image url, you can upload it to your imagebed with a keyboard hotkey.
## Tech Stack [#tech-stack]
* [Tauri](https://tauri.studio/en/)
* Rust + SvelteKit
* Tauri is a framework for building tiny, blazing fast binaries for all major desktop platforms. Developers can integrate any front-end framework that compiles to HTML, JS and CSS for building their user interface. The backend of the application is a rust-sourced binary with an API that the front-end can interact with.
* [SvelteKit](https://kit.svelte.dev/)
* SvelteKit is a framework for building web applications of all sizes, with a beautiful development experience and flexible filesystem-based routing.
* [TailwindCSS](https://tailwindcss.com/)
* A utility-first CSS framework for rapidly building custom designs.
* [Flowbite](https://flowbite-svelte.com/)
# fmtree (/docs/projects/archived/fmtree)
# fmtree [#fmtree]
> A python package for parsing file system (or any tree like structure) and output a custom format such as markdown table of content.
[PyPi](https://pypi.org/project/fmtree/)
[GitHub](https://github.com/fmtree-dev/fmtree)
## Usage [#usage]
```bash
pip install fmtree
```
## Features [#features]
* Parse file system
* Filter file system with custom filter
* MarkdownFilter
* ExtensionFilter
* Output file system with custom format
* TreeCommandFormatter
* GithubMarkdownContentFormatter
```
# TreeCommandFormatter
OSCP
└── Notes
├── Tools
│ ├── Python.md
│ ├── nmap.md
│ ├── Netcat.md
│ └── Metasploit.md
├── common.md
├── FileTransfer.md
├── README.md
├── Service.md
└── Bash.md
```
```python
import sys
import pathlib2
from fmtree.core.scraper import Scraper
from fmtree.core.format import TreeCommandFormatter, GithubMarkdownContentFormatter
from fmtree.core.filter import MarkdownFilter
from fmtree.core.sorter import Sorter
path_ = pathlib2.Path('/OSCP')
scraper = Scraper(path_, scrape_now=False, keep_empty_dir=False)
# add filter
scraper.add_filter(filter_=MarkdownFilter())
# run scraper
scraper.run()
# GNU Tree Format
formatter = TreeCommandFormatter(scraper.get_tree())
stringio = formatter.generate()
print(stringio.getvalue())
# sort
sorter_ = Sorter()
tree = sorter_(scraper.get_tree())
# GitHub Content Format
formatter = GithubMarkdownContentFormatter(tree)
stringio = formatter.generate()
print(stringio.getvalue())
formatter.to_stream(sys.stdout)
```
# fs-docs (/docs/projects/archived/fs-docs)
# fs-docs [#fs-docs]
[https://github.com/HuakunShen/fs-docs](https://github.com/HuakunShen/fs-docs)
A gatsby.js theme for documentation. Showing all markdowns from a file system recursively in a tree structure.
My old personal website was built with it. Built with Gatbsy.js and React.js.
## Tech Stack [#tech-stack]
* Gatsby.js
* React.js
* GraphQL
# GitHub GraphQL (/docs/projects/archived/github-graphql)
**GitHub:** [https://github.com/HuakunShen/github-graphql](https://github.com/HuakunShen/github-graphql)
## Documentation: [#documentation]
* [https://huakunshen.github.io/github-graphql/](https://huakunshen.github.io/github-graphql/)
* [https://jsr.io/@hk/github-graphql/doc](https://jsr.io/@hk/github-graphql/doc)
This project is a codegen wrapper around GitHub's GraphQL API, with some queries I needed for my own projects.
As rest API doesn't provide types, I prefer to use GraphQL for type safety and intellisense.
I found myself duplicating this codegen setup in multiple projects, so I decided to extract it into a standalone package.
If you managed to find this project and think it's useful, feel free to use it in your own projects.
If you want to add some common queries you find yourself using, feel free to open a PR. Add the query files to `./src/operations` folder.
If the queries you need is very specific to your project, you can fork this project and modify it to your needs.
## Installation [#installation]
Since the main purpose of this project is to get the benefits of types, I recommend using it with TypeScript and the package doesn't provide bundled JS files.
This package is published to both npm and jsr. The package name is slightly different on jsr as it requires a scoped package name.
```bash
# npm
npm install github-graphql
pnpm install github-graphql
# check https://jsr.io/@hk/github-graphql for more info
# JSR
pnpm dlx jsr add @hk/github-graphql
npx jsr add @hk/github-graphql
```
## Usage [#usage]
Sample code is the best way to learn. Look at tests in [`__tests__`](./__tests__/) folder for examples. It's quite simple.
Note that to use GitHub's GraphQL API, you need to provide a token.
If you install from jsr, make sure `@hk/github-graphql` is used as the package name.
A star history example is provided at [`./examples/star-history`](./examples/star-history/README.md).
```ts
// If you install from npm
import { getSdk } from "github-graphql/req";
// If you install from jsr
import { getSdk } from "@hk/github-graphql/req";
```
See [operations](./src/operations/) folder for available queries.
## Flavors [#flavors]
There are two flavors of this API. `graphql-request` and `@apollo/client`.
You can find sample code for both in the tests.
### `graphql-request` [#graphql-request]
Exported under `/req` subpackage.
```ts
import { GraphQLClient } from "graphql-request";
import { getSdk } from "@hk/github-graphql/req";
const client = new GraphQLClient("https://api.github.com/graphql", {
headers: {
authorization: `Bearer ${Bun.env.GITHUB_TOKEN}`,
"User-Agent": "github-graphql package",
},
});
const sdk = getSdk(client);
const data = await sdk.Repository({
owner: "tauri-apps",
name: "tauri",
});
expect(data.data.repository?.stargazerCount).toBeGreaterThan(100);
```
### `@apollo/client` [#apolloclient]
```ts
import { ApolloClient, InMemoryCache, HttpLink } from "@apollo/client";
import { DefaultGitHubContributionDocument } from "@hk/github-graphql";
const client = new ApolloClient({
cache: new InMemoryCache(),
link: new HttpLink({
uri: "https://api.github.com/graphql",
headers: {
authorization: `Bearer ${Bun.env.GITHUB_TOKEN}`,
"User-Agent": "github-graphql package",
},
}),
});
const result = await client.query({
query: RepositoryDocument,
variables: {
owner: "tauri-apps",
name: "tauri",
},
});
const stargazerCount = result.data.repository?.stargazerCount;
```
## Development [#development]
This project is built with [Bun](https://bun.sh).
No Node or npm or pnpm is required to develop/build this project.
To build this project
Add GitHub Token to `.env` file
```
GITHUB_TOKEN=github_pat_xxx
```
```bash
bun install
bun run build
bun run test
```
This is a pure TypeScript project, no JS code will be generated.
# GitHub Wall Painter (/docs/projects/archived/github-wall-painter)
# GitHub Wall Painter [#github-wall-painter]
> The entire Github Contribution Wall Green :) written in pure C
>
> [GitHub](https://github.com/HuakunShen/Github-Wall-Painter)
[YouTube](https://www.youtube.com/watch?v=w6SQUTZIpGU)
## Tech Stack [#tech-stack]
* C
* Git
# Golang Auth Template (/docs/projects/archived/golang-auth-template)
# Golang Auth Template [#golang-auth-template]
Authentication is an important and tedious part of a web application. This template is a simple authentication template for Golang web applications using JWT and mysql.
GitHub: [https://github.com/HuakunShen/golang-auth-template](https://github.com/HuakunShen/golang-auth-template)
## Tech Stack [#tech-stack]
* Golang
* JWT
* MySQL
* Docker
# Graph Search Visualizer (/docs/projects/archived/graph-search-visualizer)
# Graph Search Visualizer [#graph-search-visualizer]
> This is one of my first web app when I first started learning. In the meanwhile I was learning AI algorithms, and I thought it would be interesting to write a visualization for the algorithms.
>
> It's completely written in vanilla JS, HTML and CSS. If I were to rewrite it, I would use TypeScript, framework like React or Vue, and an animation library like p5.js
>
> This is a milestone, the starting point of my web development journey. Although it's not the best code I've written, it's still a good memory.
GitHub: [https://github.com/HuakunShen/GraphSearchVisualizer](https://github.com/HuakunShen/GraphSearchVisualizer)
Website: [https://huakunshen.github.io/GraphSearchVisualizer/](https://huakunshen.github.io/GraphSearchVisualizer/)
This is a graph search visualizer that visualizes different graph search algorithms. The user can choose the start node and the end node, and the algorithm will find the shortest path between the two nodes. The user can also choose the speed of the visualization.
## Algorithms Supported [#algorithms-supported]
* BFS
* DFS
* A\*

## Tech Stack [#tech-stack]
* HTML
* CSS
* JavaScript
# Home Network Setup YouTube Playlist (/docs/projects/archived/home-network-network-setup-youtube)
# Home Network Setup YouTube Playlist [#home-network-setup-youtube-playlist]
> 10+ Videos Playlist for Home Network Setup Tutorial (YouTube)
[Playlist](https://www.youtube.com/playlist?list=PLUxw2JoWliirPs3pAnGeUSY92kYqHsXZj)
[GitHub](https://github.com/HuakunShen/Home-Network-Setup)
## Topics [#topics]
* Raspberry Pi and Pi OS Setup
* Discussion on private ip, mac address and public ip, DDNS with no-ip and domain name
* VNC
* Honeypot for ssh
* Samba NAS
* `ssh` with ssh key
* Pi Camera
* VPN with PiVPN
* Docker
* MotionEye surveillance system with docker
* Pi-hole: DNS ad blocker and DHCP server
* WakeOnLan
* Octoprint
* File Transfer with `scp` and `SFTP`
# Huffman Coding (/docs/projects/archived/huffman-coding)
# Huffman Coding [#huffman-coding]
> Implement Huffman Coding Algorithm With C++ and Produce Executable for Different OS
[GitHub](https://github.com/HuakunShen/HuffmanCoding)
## Tech Stack [#tech-stack]
* C++
* CMake
# Archived Projects (/docs/projects/archived)
This section contains old projects that are practice projects, experiments, or no longer actively maintained.
# inspect-value (/docs/projects/archived/inspect-value)
> Web Component value inspector — works in React, Vue, Angular, Svelte, or vanilla JS. Drop-in debug panel for any framework.
**GitHub:** [https://github.com/HuakunShen/inspect-value](https://github.com/HuakunShen/inspect-value)\
**Documentation:** [https://huakunshen.github.io/inspect-value/](https://huakunshen.github.io/inspect-value/)
## Overview [#overview]
[svelte-inspect-value](https://github.com/ampled/svelte-inspect-value) as a **Web Component** — use in React, Vue, Angular, or plain HTML. Zero performance overhead. The same Svelte-compiled code runs inside a standard Custom Element.
## Acknowledgement [#acknowledgement]
This package is a Web Component wrapper around [svelte-inspect-value](https://github.com/ampled/svelte-inspect-value) by [ampled](https://github.com/ampled). All core functionality, themes, and inspection capabilities come from the original Svelte library.
## Installation [#installation]
```bash
npm install inspect-value
```
## Usage [#usage]
### Plain HTML / Vanilla JS [#plain-html--vanilla-js]
```html
```
### React [#react]
```tsx
import "inspect-value";
import { useRef, useEffect } from "react";
function Inspector({ data }: { data: any }) {
const ref = useRef(null);
useEffect(() => {
if (ref.current) {
ref.current.value = data;
}
}, [data]);
return ;
}
```
### Vue [#vue]
```vue
```
## Components [#components]
### `` [#inspect-value]
| Property | Type | Default | Description |
| ----------- | -------------- | ----------- | ------------------------------------------- |
| `value` | any | `undefined` | Value to inspect |
| `name` | string | `''` | Display name |
| `theme` | string | `'default'` | Theme (`default`, `dark`, `stereo`, `drak`) |
| `search` | boolean/string | `false` | Enable search |
| `depth` | number | `Infinity` | Max expansion depth |
| `expandAll` | boolean | `false` | Expand all nodes |
### `` [#inspect-panel]
Fixed-position panel variant for persistent debugging.
## Features [#features]
* Framework-agnostic Web Component
* Multiple themes (default, dark, stereo, drak)
* Search/filter capabilities
* Collapsible tree view
* Type annotations
* Zero dependencies
# IP Info Cache (/docs/projects/archived/ip-info-cache-pb)
GitHub Repo: [https://github.com/HuakunShen/ip-info-cache-pb](https://github.com/HuakunShen/ip-info-cache-pb)
In some of my projects, I need to visualize IP addresses on a map, thus I will need to get the longitude and latitude of the IP address.
IP info APIs costs money. e.g. ipgeolocation.io has a free tier of 30k requests/month.
It's hard to request 30k unique ips in a month, but if the same ip address is checked frequently the free quota could be used up quickly. Thus I built this simple cache server. This cache server is used as a proxy server, requests sent to `/api/info/<:ip>` is forwarded to API service and cached in pocketbase.
## Why Pocketbase? [#why-pocketbase]
Key value DB like redis is usually used for caching, however Redis memory is expensive.
We may need to store millions of ip addresses.
[Pockethost](https://pockethost.io/) provides free pocketbase service. So I deployed a pocketbase service on pockethost and built this simple cache server.
## Sample Response [#sample-response]
```json
{
"calling_code": "+61",
"city": "South Brisbane",
"connection_type": "",
"continent_code": "OC",
"continent_name": "Oceania",
"country_capital": "Canberra",
"country_code2": "AU",
"country_code3": "AUS",
"country_emoji": "🇦🇺",
"country_flag": "https://ipgeolocation.io/static/flags/au_64.png",
"country_name": "Australia",
"country_name_official": "Commonwealth of Australia",
"country_tld": ".au",
"currency": {
"code": "AUD",
"name": "Australian Dollar",
"symbol": "A$"
},
"district": "Brisbane",
"geoname_id": "10113228",
"ip": "1.1.1.1",
"is_eu": false,
"isp": "APNIC Research and Development",
"languages": "en-AU",
"latitude": "-27.47306",
"longitude": "153.01421",
"organization": "Cloudflare, Inc.",
"state_code": "AU-QLD",
"state_prov": "Queensland",
"time_zone": {
"current_time": "2025-03-08 06:13:39.206+1000",
"current_time_unix": 1741378419.206,
"dst_end": "",
"dst_exists": false,
"dst_savings": 0,
"dst_start": "",
"is_dst": false,
"name": "Australia/Brisbane",
"offset": 10,
"offset_with_dst": 10
},
"zipcode": "4101"
}
```
# j8s (/docs/projects/archived/j8s)
> A lightweight service orchestration framework for JavaScript/TypeScript. Run multiple services in a single process using worker threads.
**GitHub:** [https://github.com/HuakunShen/j8s](https://github.com/HuakunShen/j8s)\
**JSR:** [https://jsr.io/@hk/j8s](https://jsr.io/@hk/j8s)
## Features [#features]
* Run services in **main thread** or **worker threads**
* **Health checks** for all services
* **Restart policies** (always, unless-stopped, on-failure, no)
* Run services on a **schedule** (cron jobs)
* **Timeout** support for services
* Communication between worker and main thread using **RPC**
* Built-in **REST API** with OpenAPI documentation
## Installation [#installation]
```bash
# Deno
deno add @hk/j8s
# Bun
bunx jsr add @hk/j8s
# npm
npx jsr add @hk/j8s
```
## Basic Usage [#basic-usage]
### Main Thread Service [#main-thread-service]
```typescript
import { BaseService, ServiceManager } from "j8s";
class MyService extends BaseService {
async start(): Promise {
console.log("Service started");
}
async stop(): Promise {
console.log("Service stopped");
}
async healthCheck() {
return { status: "running", details: {} };
}
}
const manager = new ServiceManager();
const service = new MyService("my-service");
manager.addService(service, { restartPolicy: "always" });
await manager.startService(service);
```
### Worker Thread Service [#worker-thread-service]
```typescript
import { ServiceManager, createWorkerService } from "j8s";
const workerService = createWorkerService(
"worker-service",
new URL("./worker.ts", import.meta.url),
{
workerData: { config: { maxRetries: 5 }, initialState: "idle" },
},
);
const manager = new ServiceManager();
manager.addService(workerService, {
restartPolicy: "on-failure",
maxRetries: 3,
});
await manager.startService(workerService);
```
### Cron Jobs [#cron-jobs]
```typescript
class BackupService extends BaseService {
async start(): Promise {
console.log("Running backup...");
// Backup logic
}
}
const backupService = new BackupService("backup-service");
manager.addService(backupService, {
cronJob: {
schedule: "0 0 * * *", // Midnight every day
timeout: 60000,
},
});
```
### REST API [#rest-api]
```typescript
import { serve } from "@hono/node-server";
import { ServiceManager, createServiceManagerAPI } from "j8s";
const manager = new ServiceManager();
// Add services...
const app = createServiceManagerAPI(manager, {
openapi: { enabled: true },
scalar: { enabled: true },
});
serve({ fetch: app.fetch, port: 3000 });
```
## API Endpoints [#api-endpoints]
* `GET /services` - List all services
* `GET /services/:name` - Get service details
* `GET /services/:name/health` - Get health for a service
* `POST /services/:name/start` - Start a service
* `POST /services/:name/stop` - Stop a service
* `POST /services/:name/restart` - Restart a service
* `DELETE /services/:name` - Remove a service
## Use Cases [#use-cases]
* Microservices orchestration
* Background job workers
* Scheduled tasks
* Service health monitoring
* Multi-service desktop applications
A JavaScript service orchestration framework inspired by Kubernetes.
# Kantu (/docs/projects/archived/kantu)
# Kantu [#kantu]
GitHub: [https://github.com/HuakunShen/kantu](https://github.com/HuakunShen/kantu)
Deployment:
* [https://kantu.huakun.tech/](https://kantu.huakun.tech/)
* [https://kantu.vercel.app/](https://kantu.vercel.app/)
Kantu is a image browser with some cool features I implemented for my other machine learning projects.
It is mainly a desktop application built with [Tauri](https://tauri.app/) and [Nuxt](https://nuxt.com/). I also built a web version with [Nuxt](https://nuxt.com/) with limited features.
## Features [#features]
* Image Browser
* Browse images in a given folder on desktop
* Image labelling, you can label images with keyboard
* I am too lasy to label images using mouse, so I implemented this feature which allows me to label images using keyboard. When I press the keyboard arrow keys, the images will be swiped left and right.
* After labelling, the labels will be saved in a json file in the same folder.
* Image slideshow, you can play a slideshow of images in a given folder
## Supported Platforms [#supported-platforms]
* Windows, Mac, Linux
* Web
## Plan to Support [#plan-to-support]
* iOS, Android
## Tech Stack [#tech-stack]
* [Tauri](https://tauri.app/)
* [Nuxt](https://nuxt.com/)
* [Vue](https://vuejs.org/)
* [Tailwind CSS](https://tailwindcss.com/)
* [Vite](https://vitejs.dev/)
* [TypeScript](https://www.typescriptlang.org/)
* [Node.js](https://nodejs.org/en/)
# LeetCode Web Crawler (/docs/projects/archived/leetcode-scraper)
# LeetCode Web Crawler [#leetcode-web-crawler]
> A Web Crawler Scraping LeetCode Problems info such as Difficulties, Related Questions and Topics.
[GitHub](https://github.com/HuakunShen/LeetCodeCrawler)
## Tech Stack [#tech-stack]
* Python
* pandas
* Graphql
# Logitech Privacy Camera Cover Design (3D Model) (/docs/projects/archived/logitech-3d-camera-cover)
# Logitech Privacy Camera Cover Design (3D Model) [#logitech-privacy-camera-cover-design-3d-model]
My Logitech Web Cam doesn't come with a privacy cover, so I designed one myself.
> A 3D design for logitech camera
[GitHub](https://github.com/HuakunShen/3D-Printing-Design/tree/master/my-designs/Logitech-Camera-C920-Cover)
[Thingiverse](https://www.thingiverse.com/thing:6265816)


# Realtime Math Equation Generator (/docs/projects/archived/math-equation-generator)
# Realtime Math Equation Generator [#realtime-math-equation-generator]
> Generate realtime math equation with latex online.
>
> This was one of the first projects I built when I first started learning web dev. It looks sketchy. I was playing with MathJax.
[GitHub](https://github.com/HuakunShen/realtime-math-equation-generator)
[Website](https://huakunshen.github.io/realtime-math-equation-generator/)
# monio-napi (/docs/projects/archived/monio-napi)
> Cross-platform input monitoring for Node.js, powered by [monio](https://github.com/HuakunShen/monio) and [napi-rs](https://napi.rs).
**GitHub:** [https://github.com/HuakunShen/monio-napi](https://github.com/HuakunShen/monio-napi)
## Features [#features]
* **Cross-platform**: macOS, Windows, and Linux (X11) support
* **Proper drag detection**: Distinguishes `MouseDragged` from `MouseMoved` events
* **Event listening**: Non-blocking background listener with callback
* **Event simulation**: Programmatically generate keyboard and mouse events
* **Display queries**: Get monitor info, scale factor, refresh rate, system settings
* **Native performance**: Rust native addon via N-API, no electron/node-gyp required
## Installation [#installation]
```bash
npm install monio-napi
# or
pnpm add monio-napi
```
## Usage [#usage]
### Listening for Events [#listening-for-events]
```typescript
import { startListen, EventTypeJs } from "monio-napi";
const hook = startListen((event) => {
switch (event.eventType) {
case EventTypeJs.KeyPressed:
console.log("Key pressed:", event.keyboard?.key);
break;
case EventTypeJs.MouseDragged:
console.log(`Dragging at (${event.mouse?.x}, ${event.mouse?.y})`);
break;
case EventTypeJs.MouseWheel:
console.log("Scroll:", event.wheel?.direction);
break;
}
});
// Stop when done
hook.stop();
```
### Simulating Input [#simulating-input]
```typescript
import {
simulateMouseMove,
simulateMouseClick,
simulateKeyTap,
ButtonJs,
KeyJs,
} from "monio-napi";
// Move mouse to position
simulateMouseMove(100, 200);
// Click
simulateMouseClick(ButtonJs.Left);
// Type a key
simulateKeyTap(KeyJs.KeyA);
```
### Display Information [#display-information]
```typescript
import { getDisplays, getPrimaryDisplay, getSystemSettings } from "monio-napi";
const displays = getDisplays();
for (const display of displays) {
console.log(
`Display ${display.id}: ${display.bounds.width}x${display.bounds.height}`,
);
console.log(
` Scale: ${display.scaleFactor}, Refresh: ${display.refreshRate}Hz`,
);
}
```
## Platform Notes [#platform-notes]
* **macOS**: Requires Accessibility permissions
* **Windows**: No special permissions required for hooking
* **Linux**: Uses X11 (XRecord for capture, XTest for simulation)
# monio-rs (/docs/projects/archived/monio)
> A pure Rust cross-platform input hook library with proper drag detection.
**GitHub:** [https://github.com/HuakunShen/monio](https://github.com/HuakunShen/monio)
## Features [#features]
* **Cross-platform**: macOS, Windows, and Linux (X11/evdev) support
* **Proper drag detection**: Distinguishes `MouseDragged` from `MouseMoved` events
* **Event grabbing**: Block events from reaching other applications (global hotkeys)
* **Async/Channel support**: Non-blocking event receiving with std or tokio channels
* **Event recording & playback**: Record and replay macros (requires `recorder` feature)
* **Input statistics**: Analyze typing speed, mouse distance, etc.
* **Display queries**: Get monitor info, DPI scale, system settings
* **Pure Rust**: No C dependencies (uses native Rust bindings)
* **Event simulation**: Programmatically generate keyboard and mouse events
* **Thread-safe**: Atomic state tracking for reliable button/modifier detection
## The Problem This Solves [#the-problem-this-solves]
Most input hooking libraries report all mouse movement as `MouseMoved`, even when buttons are held down. This makes implementing drag-and-drop, drawing applications, or gesture recognition difficult.
**monio-rs** tracks button state globally and emits `MouseDragged` events when movement occurs while any mouse button is pressed.
## Installation [#installation]
```toml
[dependencies]
monio = "0.1"
# With Tokio support
monio = { version = "0.1", features = ["tokio"] }
# With recorder feature (macros)
monio = { version = "0.1", features = ["recorder"] }
# With statistics feature
monio = { version = "0.1", features = ["statistics"] }
# Linux evdev support (works on X11 AND Wayland)
monio = { version = "0.1", features = ["evdev"], default-features = false }
```
## Quick Start [#quick-start]
```rust
use monio::{listen, Event, EventType};
fn main() {
listen(|event: &Event| {
match event.event_type {
EventType::KeyPressed => {
if let Some(kb) = &event.keyboard {
println!("Key pressed: {:?}", kb.key);
}
}
EventType::MouseDragged => {
if let Some(mouse) = &event.mouse {
println!("Dragging at ({}, {})", mouse.x, mouse.y);
}
}
_ => {}
}
}).expect("Failed to start hook");
}
```
## Use Cases [#use-cases]
* Global hotkeys with event blocking
* Macro recording and playback
* Input analytics (typing speed, mouse distance)
* Drag-and-drop implementations
* Drawing applications
* Gesture recognition
Published on [crates.io](https://crates.io/crates/monio)
# mturk-vue-template (/docs/projects/archived/mturk-vue-template)
# mturk-vue-template [#mturk-vue-template]
GitHub: [https://github.com/HuakunShen/mturk-vue-template](https://github.com/HuakunShen/mturk-vue-template)
Mturk is a ugly platform. Not surprise as it's built by Amazon.
I've seen ugly vanilla JS HTML code for mturk projects with thousands of lines of code in a single html file.
This is a template for building mturk projects with Vue.js. Components are much easier to maintain and reuse.
## Tech Stack [#tech-stack]
* Vue.js
* TypeScript
* Mturk
# Netmon (/docs/projects/archived/netmon)
GitHub: [https://github.com/HuakunShen/netmon](https://github.com/HuakunShen/netmon)
A network speed monitoring CLI/library written in Rust.
# Notify Me (/docs/projects/archived/notify-me)
# Notify Me [#notify-me]
GitHub: [https://github.com/HuakunShen/Notify-Me](https://github.com/HuakunShen/Notify-Me)
This project is for sending notification to oneself.
Seems like a boring useless tool, but I can find some use cases.
The web app has a frontend and backend both written with Nuxt 3.
The frontend is only for development and demo purpose. The useful part is the API.
The API allows you to send message to yourself with both GET and POST requests. With GET request support you can send the message within browser.
The notion integration not only allows you to send message to yourself, but also record the messages in a database.
Think about when you need to send message to yourself using an API.
## Use Cases [#use-cases]
### Send Automatic Message to Yourself [#send-automatic-message-to-yourself]
1. A monitor app or CRON job can send automatic notification to yourself.
2. Automatic script such as [Wifi Password Thief](https://github.com/HuakunShen/rubber-ducky-toolbox).
3. Web Cralwer Notification.
4. Transfer message from one device to another using only Browser Address Bar.
### Upload to Notion or Database [#upload-to-notion-or-database]
1. "Leave a Message" or "Contact Form" information can be uploaded to Notion Database (for free).
## Supported Platforms [#supported-platforms]
* [x] Email
* [x] Telegram
* [x] Notion
* [ ] Slack
* [ ] Discord
## Example [#example]
## Tech Stack [#tech-stack]
* Netlify
* Nuxt
* Daisyui
* Tailwind CSS
* TypeScript
* Vue
# OctoPrint Assistant (/docs/projects/archived/octoprint-assistant)
# OctoPrint Assistant [#octoprint-assistant]
> Control 3D printer with your voice through OctoPrint.
[GitHub](https://github.com/HuakunShen/OctoPrint-Assitant)
## Tech Stack [#tech-stack]
* Python
* Django
* OctoPrint
* Siri
* Raspberry Pi
* Docker
* Nginx Reverse Proxy
# OpenCode Design Lab (/docs/projects/archived/opencode-design-lab)
> An OpenCode plugin that registers a primary design agent and model-specific subagents to generate and review designs directly to Markdown files.
**GitHub:** [https://github.com/HuakunShen/opencode-design-lab](https://github.com/HuakunShen/opencode-design-lab)
## Overview [#overview]
Design Lab uses a file-first, multi-model workflow:
* **Dynamic model mapping**: Subagents are created from your config
* **Correct model usage**: Each subagent is bound to its configured model
* **File-first outputs**: Designs and reviews are written to disk, not chat
* **Cross-review**: The same model set reviews all designs in a single report
## Installation [#installation]
### From Source [#from-source]
```bash
git clone https://github.com/HuakunShen/opencode-design-lab.git
cd opencode-design-lab
bun install
bun run build
```
Add to your OpenCode config (`~/.config/opencode/opencode.json`):
```json
{
"plugin": ["opencode-design-lab"]
}
```
## Configuration [#configuration]
Create `~/.config/opencode/design-lab.json` or `.opencode/design-lab.json`:
```json
{
"design_models": ["claude-sonnet-4", "gpt-4o", "gemini-3-pro"],
"review_models": ["claude-opus-4", "gpt-5-2"],
"base_output_dir": ".design-lab",
"design_agent_temperature": 0.7,
"review_agent_temperature": 0.1
}
```
| Option | Type | Default | Description |
| ----------------- | ---------- | --------------- | ------------------------------------ |
| `design_models` | `string[]` | Required | Models for design generation (min 2) |
| `review_models` | `string[]` | `design_models` | Models for reviews |
| `base_output_dir` | `string` | `.design-lab` | Base directory for outputs |
## Usage [#usage]
### 1. Generate Designs [#1-generate-designs]
Use the `designer` agent:
```
Ask all designer_model subagents to design a deepwiki clone.
Output each design as a Markdown file with the model name as the filename.
```
### 2. Cross-Review [#2-cross-review]
```
Now ask the same set of models to review all designs.
Each reviewer outputs one Markdown report comparing all designs at once.
```
## Output Structure [#output-structure]
```
.design-lab/YYYY-MM-DD-topic/
├── designs/
│ ├── claude-sonnet-4.md
│ ├── gpt-4o.md
│ └── gemini-3-pro.md
└── reviews/
├── review-claude-opus-4.md
└── review-gpt-5-2.md
```
## Development [#development]
```bash
bun run build # Build the plugin
bun run dev # Watch mode
bun run test # Run tests
bun run format # Format code
```
An OpenCode plugin for multi-model design generation and review workflows.
# OpenVPN3 CLI Wrapper (/docs/projects/archived/openvpn3-cli-wrapper)
# OpenVPN3 CLI Wrapper [#openvpn3-cli-wrapper]
GitHub: [https://github.com/HuakunShen/openvpn3-cli-wrapper](https://github.com/HuakunShen/openvpn3-cli-wrapper)
A wrapper for openvpn3 to make openvpn3 cli easier to use
There is no official openvpn GUI client on linux, `openvpn` and `openvpn3` are available but not that easy to use.
`openvpn3` has similar functionalities to GUI clients on Windows and Mac but still hard to use because users have to remember and type out the long commands.
I made a Gist Note of how to use `openvpn3` [here](https://gist.github.com/HuakunShen/b2b7169222c2c0658760777505e9eef4).
I am tired with `openvpn3`, and `openvpn` isn't as powerful, so I wrote a simple bash script as a wrapper of `openvpn3` client to make my life easier.
You can import, connect, disconnect ... with the simpliest commands.
## Teach Stack [#teach-stack]
* Bash
* openvpn3
# Password Peeper (/docs/projects/archived/password-peeper)
# Password Peeper [#password-peeper]
> Browsers usually remember my passwords. I need to check the browser settings if I forget the password. This extension helps me to check the password directly on the page.
[GitHub](https://github.com/HuakunShen/password-peeper)
## Tech Stack [#tech-stack]
* Svelte
* TypeScript
* JavaScript

# Personal Online Clipboard (/docs/projects/archived/personal-clipboard)
# Personal Online Clipboard [#personal-online-clipboard]
A simple personal website where you can store your text to transfer data between your devices.
GitHub: [https://github.com/HuakunShen/Personal-Online-Clipboard/](https://github.com/HuakunShen/Personal-Online-Clipboard/)
In fact this is no different from using google doc to transfer data between devices.
But this is the first time I didn't something about the inconvenience of transferring data between devices/platforms.
Later I created CrossCopy, a real seamless cross-platform clipboard. This is a good starting point.
## Tech Stack [#tech-stack]
* React
* JavaScript
* Express.js
# Polymarket Kit (/docs/projects/archived/polymarket-kit)
> A fully typed SDK and proxy server built with Elysia for Polymarket APIs. Available in TypeScript and Go.
**GitHub:** [https://github.com/HuakunShen/polymarket-kit](https://github.com/HuakunShen/polymarket-kit)\
**JSR:** [https://jsr.io/@hk/polymarket](https://jsr.io/@hk/polymarket)
## Features [#features]
* **Fully Typed SDK**: Complete TypeScript support with no `any` types
* **WebSocket Client**: Real-time market data streaming with auto-reconnection
* **Proxy Server**: REST API with OpenAPI documentation
* **MCP Server**: Model Context Protocol server for AI interactions
* **Type Safety**: End-to-end type validation and transformation
* **Multiple Runtimes**: Supports Bun, Node.js, Deno, and Cloudflare Workers
* **Multi-Language**: TypeScript and Go clients with identical APIs
## Architecture [#architecture]
Dual-purpose package:
1. **Standalone SDK Clients**
* `PolymarketSDK`: For CLOB operations (requires credentials)
* `GammaSDK`: For Gamma API operations (no credentials required)
* `PolymarketWebSocketClient`: Real-time market data streaming
2. **Proxy Server** (Optional)
* Gamma API (`/gamma/*`) - Market and event data
* CLOB API (`/clob/*`) - Trading and price history
## Installation [#installation]
```bash
# Deno
deno add @hk/polymarket
# Bun
bunx jsr add @hk/polymarket
# npm
npx jsr add @hk/polymarket
```
## Usage [#usage]
### GammaSDK (No credentials) [#gammasdk-no-credentials]
```typescript
import { GammaSDK } from "@hk/polymarket";
const gamma = new GammaSDK();
// Get active markets
const markets = await gamma.getActiveMarkets();
// Get market by slug
const market = await gamma.getMarketBySlug("bitcoin-above-100k");
```
### PolymarketSDK (With credentials) [#polymarketsdk-with-credentials]
```typescript
import { PolymarketSDK } from "@hk/polymarket";
const sdk = new PolymarketSDK({
privateKey: process.env.POLYMARKET_KEY!,
funderAddress: process.env.POLYMARKET_FUNDER!,
});
const priceHistory = await sdk.getPriceHistory({
market: "0x123...",
interval: "1h",
});
```
### WebSocket Real-Time Data [#websocket-real-time-data]
```typescript
import { PolymarketWebSocketClient } from "@hk/polymarket";
const ws = new PolymarketWebSocketClient(clobClient, {
assetIds: [
"60487116984468020978247225474488676749601001829886755968952521846780452448915",
],
autoReconnect: true,
});
ws.on({
onBook: (msg) => console.log(`Bids: ${msg.bids.length}`),
onPriceChange: (msg) => console.log(`Changes: ${msg.price_changes.length}`),
onLastTradePrice: (msg) => console.log(`Trade: ${msg.price}`),
});
await ws.connect();
```
## MCP Server [#mcp-server]
Natural language interface to Polymarket data for AI models:
```json
{
"mcpServers": {
"polymarket": {
"command": "bun",
"args": ["run", "path/to/polymarket-kit/src/mcp/polymarket.ts"]
}
}
}
```
Example queries:
* "Show me the most active prediction markets right now"
* "Find markets about the 2024 US election"
* "What are the trending markets in the last 24 hours?"
A fully typed Polymarket SDK with WebSocket support, proxy server, and MCP integration.
# Print Image In Python Shell (/docs/projects/archived/print-image-in-python-shell)
# Print Image In Python Shell [#print-image-in-python-shell]
GitHub: [https://github.com/HuakunShen/printImageInPythonShell](https://github.com/HuakunShen/printImageInPythonShell)
This is probably my first personal Python project. I was a first year CS student back then.
I was learning Python and I thought it would be cool to print an image in the Python shell.
The program reads the image pixel by pixel, and print a character based on the pixel.
The program is very simple, but it's a good starting point for me to learn Python.
Memorial milestone of my programming journey.
# Proxmox Helper (/docs/projects/archived/proxmox-helper)
# Proxmox Helper [#proxmox-helper]
> An browser extension that removes the subscription popup when logged in. Just enter the proxmox portal url
[GitHub](https://github.com/HuakunShen/proxmox-helper)
## Tech Stack [#tech-stack]
* Chrome Extension
* JavaScript
* HTML
* CSS
# Rubber Ducky Toolbox + Scripts (/docs/projects/archived/rubber-ducky)
# Rubber Ducky Toolbox + Scripts [#rubber-ducky-toolbox--scripts]
> A project containing necessary tools to make a pico rubber ducky as well as the scripts I wrote
[GitHub Repo](https://github.com/HuakunShen/rubber-ducky-toolbox)
* [Wifi Password Thief](https://github.com/HuakunShen/rubber-ducky-toolbox/tree/master/scripts/wifi-thief-request-email)
* Plug a pico rubber ducky into a computer, it will automatically steal wifi passwords and send them to your email
## Tech Stack [#tech-stack]
* Powershell
* Shell
* Python
* Arduino
# Spring Boot GraphQL Template (/docs/projects/archived/spring-boot-graphql-template)
# Spring Boot GraphQL Template [#spring-boot-graphql-template]
GitHub: [https://github.com/HuakunShen/spring-boot-graphql-template](https://github.com/HuakunShen/spring-boot-graphql-template)
A template for Spring Boot GraphQL project.
Most GraphQL server tutorials are based on Node.js. This is a template for Spring Boot GraphQL server.
Including 3 ways to implement it.
## Tech Stack [#tech-stack]
* Spring Boot
* GraphQL
* Java
# Star History (/docs/projects/archived/star-history)
GitHub: [https://github.com/HuakunShen/star-history](https://github.com/HuakunShen/star-history)
This is a simple tool to show the star history of any GitHub repository.
PocketBase is used for caching.
## Usage [#usage]
Send a `GET` request to `https://star-history.pockethost.io/api/star-history//`
e.g. `https://star-history.pockethost.io/api/star-history/kunkunsh/kunkun`
If you request a repo with lots of stars (e.g. 80k stars), it may take a while to get the result if it's the first time the repo is requested.
You could get timeout error if the request takes too long, but the request is still being processed. Come back in a few minutes and try again.
After the first request, the result will be cached and the next request will be instant.
The GitHub Token can only send 5000 requests per hour. If it reaches the limit, the request will fail.
You can add your own GitHub Token with `github_token` query parameter. Append `?github_token=` to the URL.
# Super Resolution (/docs/projects/archived/super-resolution)
# Super Resolution [#super-resolution]
> CSC420 (Introduction to Image Understanding) project. Train models to achieve Super Resolution
[GitHub Repo](https://github.com/HuakunShen/Super-Resolution)



# Tauri Nuxt Template (/docs/projects/archived/tauri-nuxt-template)
# Tauri Nuxt Template [#tauri-nuxt-template]
Tauri doesn't provide support for nuxt officially, so I created this template to help people get started with Tauri and Nuxt.
[https://github.com/HuakunShen/tauri-nuxt-template](https://github.com/HuakunShen/tauri-nuxt-template)
Added to [awesome-tauri](https://github.com/tauri-apps/awesome-tauri)
# Toronto Crime Rate Analysis (/docs/projects/archived/toronto-crime-rate-analysis)
# Toronto Crime Rate Analysis [#toronto-crime-rate-analysis]
GitHub: [https://github.com/HuakunShen/Toronto-Crime-Rate-Analysis](https://github.com/HuakunShen/Toronto-Crime-Rate-Analysis)
The crime rates in different regions of Toronto ranges largely. The crime rate also has an increasing trend from 2014 to 2019, and a sudden drop in 2020 probably due to covid 19.
## Tech Stack [#tech-stack]
* R
* ggplot2
* dplyr
* tidyr
# Typing Master (/docs/projects/archived/type-master)
# Typing Master [#typing-master]
> A web crawler that mimic human speed typing, and tries to type as fast as possible.
[GitHub](https://github.com/HuakunShen/TypingMaster)
[YouTube](https://youtu.be/eUGTaYQ20Zk)
# Verilog Ping Pong Game (/docs/projects/archived/verilog-ping-pong-game)
> A Ping Pong Game written in Verilog and installed on FPGA
[GitHub](https://github.com/HuakunShen/verilog-ping-pong-project)
# Web Request Viewer (/docs/projects/archived/web-request-viewer)
# Web Request Viewer [#web-request-viewer]
> Send a request to this server and it tells what your request look like.
## Use cases [#use-cases]
It's hard to know the exact information of a request sent out from your code. The best and eaiset way is of course have a real server listening to your requests and reply with what information they can see from your request.
For example, if you are writing a web scrapying bot and you want to change your user-agent to hide this bot, how can you make sure the request sent indeed hides your user-agent?
Or if request headers contains any information that could leak your identity.
What about you are using a VPN and you are unsure whether the VPN indeed hides your IP. You can send to request to this server and check the IP this server sees.
### VPN [#vpn]
Some VPN protocols like shadowsocks work in layer 4 (transport layer) in the 7-layer OSI model, some work in layer 3 (network layer). It feels the same in browsers.
If you use terminal (`curl` command or `git`), VPNs like OpenVPN automatically handles the traffic for you. While VPNs using shadowsocks requires extra http/socks proxy configuration.
If you are a hacker/pentester, how can you verify whether you hide your identity behind VPN successfully? Simply send a request to the request viewer server and compare with your real ip. It also returns the intermmediate routers' ip.
## Features [#features]
* `/online`: check if the server is online
* `/headers`: return all headers in the request
* `/ip`: return the ip of the request, including intermediate routers
* `/user-agent`: return the user-agent of the request
* `/cookies`: return the cookies of the request
* `/time`: return the time of the request
# Wormhole GUI (/docs/projects/archived/wormhole-gui)
# Wormhole GUI [#wormhole-gui]
[https://github.com/HuakunShen/wormhole-gui](https://github.com/HuakunShen/wormhole-gui)
Magic Wormhole is an awesome tool for transferring files between devices with P2P tech. However, it is a command line tool. This GUI makes it easier to use.
Wormhole GUI is a desktop GUI for Magic wormhole. [rymdport](https://github.com/Jacalz/rymdport) is another GUI written in Golang.
This app is written in Rust + Nuxt + Tauri.
## Tech Stack [#tech-stack]
* Rust
* Tauri
* TypeScript
* Desktop
* P2P
* Nuxt
* Vue
* Tailwind CSS
# CrossCopy (/docs/projects/crosscopy)
[https://crosscopy.io/](https://crosscopy.io/)
[GitHub Organization](https://github.com/CrossCopy)
> CrossCopy is a cloud based clipboard manager aiming to provide a seamless cross-platform data transfer solution.
It's the largest personal project I've ever worked on. It's a full-stack project with a lot of technologies involved. I've learned a lot from it.
Full-stack here is not limited to web development (frontend and backend). It also includes mobile development, desktop development, mobile apps, cloud infrastructure, and much more.
We attended [University of Toronto's Hatchery Program](https://hatchery.engineering.utoronto.ca/) to prepare this project as a startup.
## Features [#features]
* Universal clipboard experience across all devices all platforms
* Seamless file transfer between devices with P2P technology
* Airdrop between any platform
* Easy sharing with friends
* Client-side End-to-end Encryption
* Real-time Sync
* Clipboard History
## Tech Stack [#tech-stack]
* Languages: Rust, TypeScript, JavaScript, Python, Golang, WebAssembly
* Frontend: React, Nextjs, SvelteKit, Vue, Nuxtjs, Tauri (for desktop)
* API: GraphQL, REST
* Backend: Node.js, Express, MySQL, Redis, ActixWeb
* Cloud: GCP
* Deployment: Docker, Terraform, Github Actions
## Other Topics Involved [#other-topics-involved]
Distributed System, WebRTC, WebSockets, WebAssembly, P2P, Encryption, Authentication, Authorization, OAuth, REST API, GraphQL, CI/CD, Monitoring, Logging, Security, Scalability, Performance, SEO, UX/UI, System Design, Product, Marketing, Business, OS, API etc.
# Projects (/docs/projects)
I love coding and I love to share my knowledge with others. I have created many projects and I am still working on new ones.
See my GitHub for more: [https://github.com/huakunshen](https://github.com/huakunshen)
## Featured Projects [#featured-projects]
* [Kunkun](/docs/projects/kunkun) - Open source, cross-platform, extensible app launcher
* [CrossCopy](/docs/projects/crosscopy) - Cloud-based clipboard manager with P2P file transfer
* [kkrpc](/docs/projects/kkrpc) - TypeScript-first RPC library for bi-directional communication
* [Uniview](/docs/projects/uniview) - Infrastructure for building universal React plugin ecosystems with multi-framework hosts
## Plugin Ecosystem [#plugin-ecosystem]
### Tauri Plugins [#tauri-plugins]
A collection of plugins extending Tauri's capabilities for desktop applications:
* [Tauri Plugin JS](/docs/projects/tauri-plugin-js) - Spawn and manage JavaScript runtimes (Bun, Node.js, Deno) from Tauri apps
* [Tauri Plugin Clipboard](/docs/projects/tauri-plugin-clipboard) - Extended clipboard functionality with image support and change listeners
* [Tauri Plugin Keyring](/docs/projects/tauri-plugin-keyring) - Secure keyring access for storing passwords and sensitive data
* [Tauri Plugin Network](/docs/projects/tauri-plugin-network) - Network utilities including interface info, port scanning, and packet sniffing
* [Tauri Plugin System Info](/docs/projects/tauri-plugin-system-info) - Comprehensive system information (CPU, memory, battery, processes)
* [Tauri Plugin User Input](/docs/projects/tauri-plugin-user-input) - Monitor and simulate keyboard and mouse inputs
## File Transfer [#file-transfer]
Implementations of the LocalSend protocol for secure local network file sharing:
* [LocalSend Rust](/docs/projects/localsend-rs) - High-performance Rust implementation with CLI and TUI
* [LocalSend TypeScript](/docs/projects/localsend-ts) - Cross-platform TypeScript implementation for Node.js, Bun, and Deno
## Networking & System Tools [#networking--system-tools]
* [WakeOnLan Web](/docs/projects/wol-web) - Web-based Wake-on-LAN tool with SvelteKit and PocketBase
* [WakeOnLan](/docs/projects/wakeonlan) - Wake-on-LAN protocol implementations in Python and Go
## GitHub Contribution [#github-contribution]
> A TypeScript-first RPC library that enables seamless bi-directional communication between processes.
> Call remote functions as if they were local, with full TypeScript type safety and autocompletion support.
* [JSR Package](https://jsr.io/@kunkun/kkrpc)
* [NPM Package](https://www.npmjs.com/package/kkrpc)
* [Documentation by JSR](https://jsr.io/@kunkun/kkrpc/doc)
* [Typedoc Documentation](https://kunkunsh.github.io/kkrpc/)
## Supported Environments [#supported-environments]
* stdio: RPC over stdio between any combinations of Node.js, Deno, Bun processes
* web: RPC over `postMessage` API and message channel between browser main thread and web workers, or main thread and iframe
* Web Worker API (web standard) is also supported in Deno and Bun, the main thread can call functions in worker and vice versa.
* http: RPC over HTTP like tRPC
* supports any HTTP server (e.g. hono, bun, nodejs http, express, fastify, deno, etc.)
* WebSocket: RPC over WebSocket
The core of **kkrpc** design is in `RPCChannel` and `IoInterface`.
* `RPCChannel` is the bidirectional RPC channel
* `LocalAPI` is the APIs to be exposed to the other side of the channel
* `RemoteAPI` is the APIs exposed by the other side of the channel, and callable on the local side
* `rpc.getAPI()` returns an object that is `RemoteAPI` typed, and is callable on the local side like a normal local function call.
* `IoInterface` is the interface for implementing the IO for different environments. The implementations are called adapters.
* For example, for a Node process to communicate with a Deno process, we need `NodeIo` and `DenoIo` adapters which implements `IoInterface`. They share the same stdio pipe (`stdin/stdout`).
* In web, we have `WorkerChildIO` and `WorkerParentIO` adapters for web worker, `IframeParentIO` and `IframeChildIO` adapters for iframe.
> In browser, import from `kkrpc/browser` instead of `kkrpc`, Deno adapter uses node:buffer which doesn't work in browser.
```ts
interface IoInterface {
name: string;
read(): Promise; // Reads input
write(data: string): Promise; // Writes output
}
class RPCChannel<
LocalAPI extends Record,
RemoteAPI extends Record,
Io extends IoInterface = IoInterface,
> {}
```
## Examples [#examples]
Below are simple examples.
### Stdio Example [#stdio-example]
```ts
import { NodeIo, RPCChannel } from "kkrpc";
import { apiMethods } from "./api.ts";
const stdio = new NodeIo(process.stdin, process.stdout);
const child = new RPCChannel(stdio, { expose: apiMethods });
```
```ts
import { spawn } from "child_process";
const worker = spawn("bun", ["scripts/node-api.ts"]);
const io = new NodeIo(worker.stdout, worker.stdin);
const parent = new RPCChannel<{}, API>(io);
const api = parent.getAPI();
expect(await api.add(1, 2)).toBe(3);
```
### Web Worker Example [#web-worker-example]
```ts
import { RPCChannel, WorkerChildIO, type DestroyableIoInterface } from "kkrpc";
const worker = new Worker(
new URL("./scripts/worker.ts", import.meta.url).href,
{ type: "module" },
);
const io = new WorkerChildIO(worker);
const rpc = new RPCChannel(io, {
expose: apiMethods,
});
const api = rpc.getAPI();
expect(await api.add(1, 2)).toBe(3);
```
```ts
import { RPCChannel, WorkerParentIO, type DestroyableIoInterface } from "kkrpc";
const io: DestroyableIoInterface = new WorkerChildIO();
const rpc = new RPCChannel(io, {
expose: apiMethods,
});
const api = rpc.getAPI();
const sum = await api.add(1, 2);
expect(sum).toBe(3);
```
### HTTP Example [#http-example]
Codesandbox: [https://codesandbox.io/p/live/4a349334-0b04-4352-89f9-cf1955553ae7](https://codesandbox.io/p/live/4a349334-0b04-4352-89f9-cf1955553ae7)
#### `api.ts` [#apits]
Define API type and implementation.
```ts
export type API = {
echo: (message: string) => Promise;
add: (a: number, b: number) => Promise;
};
export const api: API = {
echo: (message) => {
return Promise.resolve(message);
},
add: (a, b) => {
return Promise.resolve(a + b);
},
};
```
#### `server.ts` [#serverts]
Server only requires a one-time setup, then it won't need to be touched again.
All the API implementation is in `api.ts`.
```ts
import { HTTPServerIO, RPCChannel } from "kkrpc";
import { api, type API } from "./api";
const serverIO = new HTTPServerIO();
const serverRPC = new RPCChannel(serverIO, { expose: api });
const server = Bun.serve({
port: 3000,
async fetch(req) {
const url = new URL(req.url);
if (url.pathname === "/rpc") {
const res = await serverIO.handleRequest(await req.text());
return new Response(res, {
headers: { "Content-Type": "application/json" },
});
}
return new Response("Not found", { status: 404 });
},
});
console.log(`Start server on port: ${server.port}`);
```
#### `client.ts` [#clientts]
```ts
import { HTTPClientIO, RPCChannel } from "kkrpc";
import { api, type API } from "./api";
const clientIO = new HTTPClientIO({
url: "http://localhost:3000/rpc",
});
const clientRPC = new RPCChannel<{}, API>(clientIO, { expose: api });
const clientAPI = clientRPC.getAPI();
const echoResponse = await clientAPI.echo("hello");
console.log("echoResponse", echoResponse);
const sum = await clientAPI.add(2, 3);
console.log("Sum: ", sum);
```
### Chrome Extension Example [#chrome-extension-example]
#### `background.ts` [#backgroundts]
```ts
import { ChromeBackgroundIO, RPCChannel } from "kkrpc";
import type { API } from "./api";
// Store RPC channels for each tab
const rpcChannels = new Map>();
// Listen for tab connections
chrome.runtime.onConnect.addListener((port) => {
if (port.sender?.tab?.id) {
const tabId = port.sender.tab.id;
const io = new ChromeBackgroundIO(tabId);
const rpc = new RPCChannel(io, { expose: backgroundAPI });
rpcChannels.set(tabId, rpc);
port.onDisconnect.addListener(() => {
rpcChannels.delete(tabId);
});
}
});
```
#### `content.ts` [#contentts]
```ts
import { ChromeContentIO, RPCChannel } from "kkrpc";
import type { API } from "./api";
const io = new ChromeContentIO();
const rpc = new RPCChannel(io, {
expose: {
updateUI: async (data) => {
document.body.innerHTML = data.message;
return true;
},
},
});
// Get API from background script
const api = rpc.getAPI();
const data = await api.getData();
console.log(data); // { message: "Hello from background!" }
```
# Kunkun (/docs/projects/kunkun)
> Kunkun is an open source, cross-platform, extensible app launcher like Raycast or Alfred.
> All extensions run in a sandboxed environment by default to ensure security.
> Comes with a permission control system to regulate what extensions can do.
**GitHub:** [https://github.com/kunkunsh/kunkun](https://github.com/kunkunsh/kunkun)
**Official Website:** [https://kunkun.sh](https://kunkun.sh)
## Demo Video and Instructions [#demo-video-and-instructions]
* [https://docs.kunkun.sh/guides/demo/](https://docs.kunkun.sh/guides/demo/)
* Download extension from [https://kunkun.sh/download](https://kunkun.sh/download)
## Platforms [#platforms]
* [x] MacOS
* [x] Linux
* [x] Windows
## Download [#download]
* From the Website: [https://kunkun.sh/download/](https://kunkun.sh/download/)
* From GitHub Releases: [https://github.com/kunkunsh/kunkun/releases](https://github.com/kunkunsh/kunkun/releases)
## Sample Extensions [#sample-extensions]
##### Kunkun Dance [#kunkun-dance]

##### Extension Store [#extension-store]

##### Battery Health [#battery-health]

##### IP Info [#ip-info]

##### Image Format Conversion [#image-format-conversion]

##### List of Commands [#list-of-commands]

##### Extension Details in Store (Permission Inspector) [#extension-details-in-store-permission-inspector]

##### Video Info [#video-info]

##### Video Conversion [#video-conversion]

##### 3D Git Skyline [#3d-git-skyline]

##### Letterboxd Movie Search [#letterboxd-movie-search]

##### Key Displayer [#key-displayer]

##### JWT Inspector [#jwt-inspector]

##### Image Info [#image-info]

##### Hacker News [#hacker-news]

##### QRCode Generator [#qrcode-generator]

##### File Transfer [#file-transfer]


##### Disk Speed Test [#disk-speed-test]

##### Clipboard History [#clipboard-history]

# LocalSend Rust (/docs/projects/localsend-rs)
> A high-performance, type-safe implementation of LocalSend protocol (v2) in Rust.
**GitHub:** [https://github.com/CrossCopy/localsend-rs](https://github.com/CrossCopy/localsend-rs)
## Features [#features]
### Core Functionality [#core-functionality]
* **Protocol Compatibility**: Full interoperability with official LocalSend clients
* **Automatic Discovery**: Multicast UDP discovery to find devices instantly
* **Direct Send**: Transfer files or text directly to an IP address
* **HTTPS Security**: TLS encryption with certificate fingerprinting
* **Text Messages**: Support for sending and receiving instant text messages
* **CLI & TUI**: Intuitive command-line interface with optional terminal UI
### Performance & Quality [#performance--quality]
* **Streaming Transfers**: Memory-efficient streaming for large files
* **Async I/O**: Non-blocking file operations for high concurrency
* **Type Safety**: Strong typing throughout (`SessionId`, `FileId`, `Token`, `Port`)
* **State Management**: Type-safe state machine for transfer lifecycle
* **Well-Tested**: 32+ unit tests covering core functionality
## Installation [#installation]
```bash
# Install CLI version
cargo install localsend-rs
# Install with interactive TUI
cargo install localsend-rs --features tui
```
## Quick Start [#quick-start]
```bash
# Discover devices
cargo run --features https -- discover
# Receive files
cargo run --features https -- receive --https
# Send files
cargo run --features https -- send "My Phone" ./photos/vacation.jpg
# Send text
cargo run --features https -- send "ROG16" "Hello from Rust CLI!"
# Launch TUI
cargo run --features all -- tui
```
## Architecture [#architecture]
Clean, domain-driven modules:
```
src/
├── core/ # Core domain logic (device, file, session, transfer)
├── crypto/ # Cryptography (fingerprint, hash, tls)
├── storage/ # Storage abstraction
├── discovery/ # Multicast UDP & HTTP discovery
├── server/ # Axum HTTP/HTTPS server
├── client/ # Request-based client
├── protocol/ # Protocol types & validation
├── cli/ # Command-line interface
└── tui/ # Terminal UI
```
### Key Design Patterns [#key-design-patterns]
* **Newtype Pattern**: Strong typing for protocol identifiers
* **State Machine**: Type-safe transfer lifecycle management
* **Builder Pattern**: Fluent API for constructing DeviceInfo
* **Strategy Pattern**: Pluggable FileSystem implementations
Built as a [CrossCopy](https://crosscopy.io) project.
# LocalSend TypeScript (/docs/projects/localsend-ts)
> A TypeScript implementation of the LocalSend protocol for secure, local network file and text transfers.
**GitHub:** [https://github.com/CrossCopy/localsend-ts](https://github.com/CrossCopy/localsend-ts)
## Features [#features]
* **Full Protocol Support**: Complete implementation of LocalSend protocol v2
* **Cross-Platform**: Works with Node.js, Bun, and Deno
* **Multiple Server Adapters**: Bun, Node.js, Deno, and Hono server adapters
* **Interactive TUI**: Sophisticated terminal UI built with Ink (React for CLI)
* **Library & CLI**: Use as a library or CLI tool
* **Multicast Discovery**: Automatic device discovery on local network
* **HTTP Discovery**: Alternative HTTP-based discovery method
## Installation [#installation]
```bash
# NPM
npm install localsend
# JSR
npx jsr add @crosscopy/localsend
```
## Usage [#usage]
### Library [#library]
```typescript
import {
BunServerAdapter,
NodeServerAdapter,
DenoServerAdapter,
createServerAdapter,
LocalSendServer,
LocalSendHonoServer,
LocalSendClient,
MulticastDiscovery,
HttpDiscovery,
} from "localsend";
```
### CLI - Interactive TUI (Recommended) [#cli---interactive-tui-recommended]
```bash
# Run the sophisticated TUI with real-time device scanning
npm run tui
# or with Bun
bun src/cli-tui.tsx
# With custom port and alias
npm run tui -- --port 8080 --alias "My Device"
```
The TUI provides:
* **Real-time device scanning** - Continuously discover LocalSend devices
* **Device selection** - Navigate and select from discovered devices
* **Send text messages** - Interactive text input and sending
* **Send files** - File path input with validation
* **Receiver mode** - Real-time file receiving with progress
* **Settings** - Dynamic device configuration
### CLI - Traditional [#cli---traditional]
```bash
npx localsend
# Please use a subcommand: send | receive | discover
# Examples:
# localsend send 192.168.1.100 ./file.txt
# localsend receive --saveDir ./downloads
# localsend discover --timeout 10
```
## Development [#development]
```bash
deno -A --unstable-sloppy-imports --unstable-net src/cli.ts receive -=alias deno-client
bun run src/cli.ts receive
```
Built for integrating LocalSend into [Kunkun](https://github.com/kunkunsh/kunkun).
# Tauri Plugin Clipboard (/docs/projects/tauri-plugin-clipboard)
**GitHub:** [https://github.com/CrossCopy/tauri-plugin-clipboard](https://github.com/CrossCopy/tauri-plugin-clipboard)
> A Tauri plugin that extends clipboard functionality with image support and clipboard change listener.
Tauri's official clipboard API doesn't support image copy/paste and clipboard change listener. So I implemented a plugin for it, and use it in my own desktop apps.
## Tech Stack [#tech-stack]
* Rust
* Tauri
* Clipboard
* SvelteKit
# Tauri Plugin JS (/docs/projects/tauri-plugin-js)
> A Tauri v2 plugin that spawns and manages JavaScript runtime processes (Bun, Node.js, Deno) from your desktop app.
**GitHub:** [https://github.com/HuakunShen/tauri-plugin-js](https://github.com/HuakunShen/tauri-plugin-js)
## Why [#why]
Tauri gives you a tiny, fast, secure desktop shell — but sometimes you need a full JS runtime for things the webview can't do: filesystem watchers, native modules, long-running compute, local AI inference, dev servers, etc. This plugin bridges that gap without the weight of Electron.
## Features [#features]
* Run Bun/Node/Deno workers from a Tauri app with full process lifecycle management
* **Type-safe bidirectional RPC** between frontend and backend JS processes via kkrpc
* Multiple concurrent named processes with independent stdio streams
* Runtime auto-detection (discovers installed runtimes, paths, versions)
* Custom runtime executable paths via settings
* **Compiled binary sidecars** — compile TS workers into standalone executables
* Clean shutdown on app exit
* Multi-window support
## Architecture [#architecture]
```
┌─────────────────┐ ┌─────────────────┐
│ Browser Host │ ◄─postMessage─►│ Web Worker │
│ (Svelte) │ │ (Plugin) │
└─────────────────┘ └─────────────────┘
```
Rust never parses RPC payloads — it forwards raw newline-delimited strings between the webview and child processes. The RPC protocol layer (kkrpc) runs entirely in JS on both sides.
## Installation [#installation]
### Rust [#rust]
```toml
[dependencies]
tauri-plugin-js = "0.1"
```
### Frontend [#frontend]
```bash
pnpm add tauri-plugin-js-api kkrpc
```
## Usage [#usage]
```typescript
import {
spawn,
createChannel,
onStdout,
onStderr,
onExit,
} from "tauri-plugin-js-api";
import type { BackendAPI } from "../backends/shared-api";
// Spawn a worker
await spawn("my-worker", { runtime: "bun", script: "bun-worker.ts" });
// Create a typed RPC channel
const { api } = await createChannel, BackendAPI>(
"my-worker",
);
// Type-safe calls
const sum = await api.add(5, 3);
const info = await api.getSystemInfo();
```
### Compiled Binary Sidecars [#compiled-binary-sidecars]
Both Bun and Deno can compile TS workers into standalone executables:
```bash
# Bun
bun build --compile --minify backends/bun-worker.ts --outfile src-tauri/binaries/bun-worker-$TARGET
# Spawn sidecar — no runtime needed at runtime
await spawn("my-compiled-worker", { sidecar: "bun-worker" });
```
## Use Cases [#use-cases]
* Dev servers embedded in desktop apps
* File system watchers and build tools
* Long-running background tasks
* Native module access without node-gyp
* Local AI inference with GPU acceleration
# Tauri Plugin Keyring (/docs/projects/tauri-plugin-keyring)
**GitHub:** [https://github.com/HuakunShen/tauri-plugin-keyring](https://github.com/HuakunShen/tauri-plugin-keyring)
> A Tauri plugin that provides secure keyring access for your Tauri applications.
> Written in Rust and TypeScript.
A simple wrapper over rust [keyring](https://crates.io/crates/keyring) crate. This may be useful for many applications that require storing user's sensitive data on disk, so although it's simple, I made a plugin for it.
Using keyring allows you to store user's password in the system keychain safely without prompting user for password everytime.
Tauri's [stronghold plugin](https://tauri.app/plugin/stronghold/) is also used for storing secrets and keys. But it requires user to enter a password or storing the encryption key somewhere. keyring is a good place to store this encryption key.
**Sample Usage:**
* Storing random database encryption key
* Storing user's password for auto-login
* Storing user's auth token
**Sample Project that uses this plugin:** [kunkunsh/kunkun](https://github.com/kunkunsh/kunkun)
## Installation [#installation]
* Crate: [https://crates.io/crates/tauri-plugin-keyring](https://crates.io/crates/tauri-plugin-keyring)
* `cargo add tauri-plugin-keyring`
* NPM Package: [https://www.npmjs.com/package/tauri-plugin-keyring-api](https://www.npmjs.com/package/tauri-plugin-keyring-api)
* `npm install tauri-plugin-keyring-api`
## Usage [#usage]
### TypeScript/JavaScript [#typescriptjavascript]
```ts
import {
getPassword,
setPassword,
deletePassword,
} from "tauri-plugin-keyring-api";
const service = "my-service";
const user = "my-user";
if (!pass) {
await setPassword(service, user, "my-password");
}
const pass: string = await getPassword(service, user);
await deletePassword(service, user);
```
### Rust [#rust]
```rust
use tauri::Manager;
use tauri_plugin_keyring::KeyringExt;
// app is a tauri::AppHandle
let pass: Option = app.keyring().get_password("tauri-plugin-keyring", "test")?;
```
# Tauri Plugin Network (/docs/projects/tauri-plugin-network)
**GitHub:** [https://github.com/HuakunShen/tauri-plugin-network](https://github.com/HuakunShen/tauri-plugin-network)
> A tauri plugin written in Rust and TypeScript to provide network related functionalities to a tauri desktop app.
Added to [awesome-tauri](https://github.com/tauri-apps/awesome-tauri)
## Features [#features]
* Retrieve network interface information
* TCP host up detection
* Scan local network ips on specified port using HTTP
* With optional response keyword detection
* Batch scanning with multi-threading
* ICMP scan
* Network data transmission monitoring
* Packet sniffing (This is harder on Windows as [pnet](https://crates.io/crates/pnet) on Windows requires installation of WinPcap or npcap)
## Example [#example]
## Tech Stack [#tech-stack]
* Rust
* Tauri
* TypeScript
* Network
* SvelteKit
# Tauri Plugin System Info (/docs/projects/tauri-plugin-system-info)
**GitHub:** [https://github.com/HuakunShen/tauri-plugin-system-info](https://github.com/HuakunShen/tauri-plugin-system-info)
> A tauri plugin written in Rust and TypeScript to provide system information to a tauri desktop app.
Added to [awesome-tauri](https://github.com/tauri-apps/awesome-tauri)
## Features [#features]
* CPU
* Network
* Process
* Memory
* Hostname
* Kernel Version
* OS Version
* Battery
## Tech Stack [#tech-stack]
* Rust
* Tauri
* TypeScript
* System Info
* SvelteKit
# Tauri Plugin User Input (/docs/projects/tauri-plugin-user-input)
**GitHub:** [https://github.com/kunkunsh/tauri-plugin-user-input](https://github.com/kunkunsh/tauri-plugin-user-input)
> A Tauri plugin with user input features.
## Features [#features]
* Monitors user inputs from keyboard and mouse
* Simulates keyboard and mouse inputs
## Tech [#tech]
* Rust
* Tauri
* TypeScript
# Uniview (/docs/projects/uniview)
> Infrastructure for building universal React plugin ecosystems. Multi-framework hosts, isolated runtimes, type-safe RPC.
**GitHub:** [https://github.com/HuakunShen/uniview](https://github.com/HuakunShen/uniview)\
**Documentation:** [https://huakunshen.github.io/uniview/](https://huakunshen.github.io/uniview/)
## Overview [#overview]
Uniview enables writing plugins in React or Solid that can be rendered by Svelte, Vue, React, or any other framework. Plugins run in isolated environments (Web Workers, Node.js, Deno, Bun) and communicate with hosts via RPC.
```
RPC (kkrpc)
┌───────────────────────┐ ◄──────────────────► ┌──────────────────┐
│ Plugin (React/Solid) │ UINode tree │ Host (Svelte) │
│ Web Worker │ │ or Vue, React │
└───────────────────────┘ └──────────────────┘
```
## Key Features [#key-features]
* **Write plugins in React or Solid, render anywhere**
* **Sandboxed execution** in Web Workers for security
* **Server-side plugins** via Node.js/Deno/Bun with WebSocket Bridge
* **Incremental updates** - Only changed nodes are sent over RPC
* **Framework-agnostic protocol** - hosts implement their own adapters
* **Type-safe RPC communication** via kkrpc
## Packages [#packages]
| Package | Description |
| ------------------------- | ----------------------------------------------- |
| `@uniview/protocol` | Core types, UINode schema, RPC interfaces |
| `@uniview/react-renderer` | Custom React reconciler producing UINode trees |
| `@uniview/solid-renderer` | Solid universal renderer producing UINode trees |
| `@uniview/react-runtime` | React plugin bootstrap for Worker/WebSocket |
| `@uniview/solid-runtime` | Solid plugin bootstrap for Worker/WebSocket |
| `@uniview/host-sdk` | Framework-agnostic host controller |
| `@uniview/host-svelte` | Svelte 5 rendering adapter |
| `@uniview/tui-renderer` | Terminal UI renderer (non-DOM) |
## Host Targets [#host-targets]
Uniview plugins render on any target that implements the UINode protocol:
| Target | Rendering Approach |
| ------------------- | --------------------------------------- |
| **Svelte** (Web) | Svelte 5 ComponentRenderer |
| **React** (Web) | React component tree |
| **Vue** (Web) | Vue component tree |
| **SwiftUI** (macOS) | Declarative SwiftUI views |
| **AppKit** (macOS) | Imperative NSViews with diff reconciler |
| **Terminal** | ANSI escape codes |
## Runtime Modes [#runtime-modes]
| Mode | Environment | Isolation | Use Case |
| --------------- | ---------------- | ---------------- | -------------------------------- |
| **Worker** | Browser | Full sandbox | Production, untrusted plugins |
| **WebSocket** | Node.js/Deno/Bun | Process boundary | Server-side, full runtime access |
| **Main Thread** | Browser | None | Development only |
Built for [Kunkun](https://github.com/kunkunsh/kunkun) extension system.
# Wakeonlan (/docs/projects/wakeonlan)
I was curious how wakeonlan protocol work, and how can it wake up a computer using network packets. So I implemented the protocol in both Python and Golang.
[GitHub: Wake On Lan Implementaiton](https://github.com/HuakunShen/wol)
[GitHub: Wake On Lan Web](https://github.com/HuakunShen/wol-web)
## Tech Stack [#tech-stack]
* Python
* Golang
* Network
# WakeOnLan Web (/docs/projects/wol-web)
**GitHub:** [https://github.com/HuakunShen/wol-web](https://github.com/HuakunShen/wol-web)
> A web app hosted locally for wakeonlan
>
> This is a rewrite with sveltekit + PocketBase to replace the old version I wrote a few years ago
>
> In the new rewrite, instead of writing an entire rest API server and manage database with gorm, I use PocketBase as backend and database. Its golang extension feature allows me to add the wakeonlan feature easily. The most complicated part, Auth, is also fully handled by PocketBase, saving lots of time. PocketBase also has a built-in database management UI, making user creation/management much easier.

## Deployment (Docker) [#deployment-docker]
Deployment with docker is super simple.
Docker image [`huakunshen/wol`](https://hub.docker.com/repository/docker/huakunshen/wol/) is available on docker hub.
Both `linux/amd64` and `linux/arm64` are supported.
> \[!IMPORTANT]
>
> 1. The container must be in the same network as the target hosts
> 2. The container must be started with `--network=host`
> 3. Mac doesn't support `--network=host` with docker. On Mac you have to run server with go directly. It's recommended to use linux.
### Step 1: Start Server [#step-1-start-server]
Here is a full command to start the server with a superuser initialized
```bash
docker run --rm \
--network=host \
-e PORT=8090 \
-e SUPERUSER_EMAIL= \
-e SUPERUSER_PASSWORD= \
-v ./pb_data:/app/pb_data \
huakunshen/wol:latest
```
* In this example I used `--rm` to clean up the container after it's closed for demo purpose
* In production, you should replace `--rm` with `-d` to run it in detach mode
The 2 environment variables and volume are optional but recommended.
* The volume is for data persistence, so you don't lose your data after container is destroyed.
* Instead of using a local directory, it's better to create a volume and bind to it.
* `PORT` environment variable is used to specify the port the server listens on
* Default is 8090
* Since this app has to be run in host network, you can't set port mapping with `-p` option; thus the `PORT` environment variable can be used to change the port.
* The 2 environment variables are used to create an initial superuser in database
* This project uses pocketbase as its backend and database, there is no user register feature as we shouldn't allow random person to register and send magic packets in your network. The only way to create user is log into pocketbase admin console with a superuser account and manually create user in the `users` collection/table.
* When both `SUPERUSER_EMAIL` and `SUPERUSER_PASSWORD` are set, the server will create this superuser the first time it starts and you could login directly.
* If you didn't set initial superuser credentials, you could also create a superuser
* A long URL should be printed to console, open it in browser. The token in the URL allows you to create a superuser
```
(!) Launch the URL below in the browser if it hasn't been open already to create your first superuser account:
http://0.0.0.0:8090/_/#/pbinstal/eyJhbGciOiJIUzI1NiIs...
```
* If you ran `docker run -d` in detach mode, run `docker logs ` to find the long URL for superuser creation.
### Step 2: Create a Regular User [#step-2-create-a-regular-user]
The superuser we discussed previously is like a database admin, you need to create a regular user to login to the website.
1. Go to [`http://localhost:8090/_/`](http://localhost:8090/_/) (or the url of your environment), login with superuser credentials
2. Go to `users` collection, create a user, remember your email and password
### Step 3: Login to WOL Web [#step-3-login-to-wol-web]
You can go to `http://localhost:8090/auth` and login with your regular user credentials.
Create a host then you can wake up your computer from browser.
## Deployment (docker compose) [#deployment-docker-compose]
Docker compose makes creating and destroying wol container easier.
A [compose.yml](./compose.yml) is provided in this repo.
```yaml
services:
wol:
image: "huakunshen/wol"
container_name: wol-web
network_mode: host
volumes:
- wol_data:/app/pb_data
environment:
- SUPERUSER_EMAIL=root@example.com
- SUPERUSER_PASSWORD=changeme
- PORT=8090
volumes:
wol_data:
```
```bash
docker compose up
docker compose down
```
## Develop [#develop]
**Prerequisite:**
1. Bun
2. Golang
bun workspace is used to manage this monorepo, `dev` script will start frontend and backend together.
```bash
bun install
bun run dev # start both sveltekit dev server and golang pocketbase server
```
### Server [#server]
The golang server is in `apps/server`. It's a golang pocketbase extension with some custom routes.
```bash
air # start development
go run main.go serve # start the server without hot reload
```
#### Migrations [#migrations]
When table is modified, run `go run . migrate collections` to generate a migration `.go` file that will be auto loaded.
### Frontend [#frontend]
The frontend is in `apps/web`, written with sveltekit + `@sveltejs/adapter-static`.
In development, use `http://localhost:5173`.
Running `bun run build` will generate a `apps/web/build` directory,
and will be automatically copied to `apps/server/pb_public` ready to be served directly by the golang server as static assets.
In production the website is accesssible at `http://localhost:8090/`.
### Docker [#docker]
`make buildx` automatically builds docker image for `linux/amd64` and `linux/arm64` and push to dockerhub.