| name | blur-autoclicker-automation |
| description | An accuracy-focused Windows auto-clicker with advanced features including CPS control, keyboard automation, position clicking, and performance optimization built with TypeScript and Tauri. |
| triggers | ["how do I build blur autoclicker from source","set up blur autoclicker development environment","how to configure blur autoclicker features","create an autoclicker script with blur","blur autoclicker keyboard automation","configure blur autoclicker position clicking","blur autoclicker performance optimization","how to package blur autoclicker for windows"] |
Blur AutoClicker Automation
Skill by ara.so — Devtools Skills collection.
Blur AutoClicker is a high-performance Windows auto-clicker built with TypeScript and Tauri that provides precise CPS (clicks per second) control up to 500 CPS, keyboard automation, position clicking, and advanced timing features. It combines a web-based UI with Rust backend for optimal performance while maintaining under 100MB RAM usage.
Installation
End User Installation
Download the latest release from GitHub:
# Download from https://github.com/Blur009/Blur-AutoClicker/releases/latest
# Default installation location
%localappdata%\BlurAutoClicker\BlurAutoClicker.exe
# Config and stats location
%appdata%\BlurAutoClicker
Development Setup
Requirements:
- Node.js 20 or newer
- Rust via rustup
- Microsoft C++ Build Tools / Visual Studio Build Tools
# Clone the repository
git clone https://github.com/Blur009/Blur-AutoClicker.git
cd Blur-AutoClicker
# Install dependencies
npm install
# Set up Rust toolchain
rustup default stable-x86_64-pc-windows-msvc
Development Commands
# Run in development mode
npm run dev
# Build release bundle
npm run build
# Lint code
npm run lint
# Build frontend only
npm run frontend:build
# Run Rust tests
cargo test --manifest-path src-tauri/Cargo.toml
# Check Rust code
cargo check --manifest-path src-tauri/Cargo.toml
Built installer location: src-tauri/target/release/bundle/nsis/
Project Structure
Blur-AutoClicker/
├── src/ # TypeScript frontend (web UI)
├── src-tauri/ # Rust backend (Tauri)
│ ├── src/ # Rust source code
│ ├── Cargo.toml # Rust dependencies
│ └── tauri.conf.json # Tauri configuration
├── public/ # Static assets
└── package.json # Node.js dependencies
Core Features
1. Mouse Button Control
The application supports left, right, and middle mouse button clicking:
interface MouseConfig {
button: 'left' | 'right' | 'middle';
mode: 'hold' | 'toggle';
cps: number;
}
const config: MouseConfig = {
button: 'left',
mode: 'toggle',
cps: 50
};
2. Keyboard Key Automation
Automate keyboard key presses with case control:
interface KeyConfig {
key: string;
uppercase: boolean;
mode: 'hold' | 'toggle';
pressesPerSecond: number;
}
const keyConfig: KeyConfig = {
key: 'a',
uppercase: false,
mode: 'hold',
pressesPerSecond: 10
};
3. Click Timing (Duty Cycle)
Control the timing between press and release:
interface TimingConfig {
clickDuration: number;
interval: number;
}
const timing: TimingConfig = {
clickDuration: 10,
interval: 20
};
4. Speed Range Mode
Randomize CPS within a range:
interface SpeedRangeConfig {
enabled: boolean;
minCps: number;
maxCps: number;
}
const speedRange: SpeedRangeConfig = {
enabled: true,
minCps: 40,
maxCps: 60
};
5. Position Clicking
Click at specific screen coordinates:
interface PositionConfig {
enabled: boolean;
x: number;
y: number;
moveBeforeClick: boolean;
}
const positionClick: PositionConfig = {
enabled: true,
x: 1920,
y: 1080,
moveBeforeClick: true
};
6. Click and Time Limits
Stop after specific conditions:
interface LimitsConfig {
clickLimit?: number;
timeLimit?: number;
}
const limits: LimitsConfig = {
clickLimit: 1000,
timeLimit: 60
};
7. Corner and Edge Stopping
Automatically stop when mouse reaches screen edges:
interface EdgeStoppingConfig {
enabled: boolean;
cornerThreshold: number;
edgeThreshold: number;
}
const edgeStopping: EdgeStoppingConfig = {
enabled: true,
cornerThreshold: 50,
edgeThreshold: 10
};
Tauri Backend Integration
Tauri Commands
When developing features, interact with the Rust backend via Tauri commands:
import { invoke } from '@tauri-apps/api/tauri';
async function startClicking(config: ClickConfig): Promise<void> {
await invoke('start_clicking', { config });
}
async function stopClicking(): Promise<void> {
await invoke('stop_clicking');
}
async function getStats(): Promise<ClickStats> {
return await invoke('get_stats');
}
interface ClickStats {
totalClicks: number;
currentCps: number;
averageCps: number;
uptime: number;
}
Rust Backend Example
use tauri::State;
use std::sync::Mutex;
struct ClickerState {
is_active: bool,
total_clicks: u64,
}
#[tauri::command]
fn start_clicking(state: State<Mutex<ClickerState>>) -> Result<(), String> {
let mut clicker = state.lock().unwrap();
clicker.is_active = true;
Ok(())
}
#[tauri::command]
fn stop_clicking(state: State<Mutex<ClickerState>>) -> Result<(), String> {
let mut clicker = state.lock().unwrap();
clicker.is_active = false;
Ok(())
}
#[tauri::command]
fn get_stats(state: State<Mutex<ClickerState>>) -> Result<u64, String> {
let clicker = state.lock().unwrap();
Ok(clicker.total_clicks)
}
Configuration Management
Saving Configuration
import { appDataDir } from '@tauri-apps/api/path';
import { writeTextFile, readTextFile } from '@tauri-apps/api/fs';
async function saveConfig(config: AppConfig): Promise<void> {
const appData = await appDataDir();
const configPath = `${appData}/config.json`;
await writeTextFile(configPath, JSON.stringify(config, null, 2));
}
async function loadConfig(): Promise<AppConfig | null> {
try {
const appData = await appDataDir();
const configPath = `${appData}/config.json`;
const content = await readTextFile(configPath);
return JSON.parse(content);
} catch (error) {
console.error('Failed to load config:', error);
return ;
}
}
{
: | | ;
: | ;
: ;
: ;
: ;
}
{
: ;
?: ;
?: ;
?: ;
?: ;
}
Hotkey Management
import { register, unregister } from '@tauri-apps/api/globalShortcut';
async function setupHotkeys(hotkey: string): Promise<void> {
await unregister(hotkey).catch(() => {});
await register(hotkey, async () => {
const isActive = await invoke('is_clicking_active');
if (isActive) {
await invoke('stop_clicking');
} else {
await invoke('start_clicking');
}
});
}
const hotkeyExamples = [
'F6',
'F7',
'F8',
'Ctrl+Shift+A',
'Alt+C'
];
Performance Optimization
Timer Resolution
use std::time::{Duration, Instant};
use std::thread;
pub struct PrecisionTimer {
interval: Duration,
last_tick: Instant,
}
impl PrecisionTimer {
pub fn new(cps: u32) -> Self {
let interval = Duration::from_micros(1_000_000 / cps as u64);
Self {
interval,
last_tick: Instant::now(),
}
}
pub fn wait_for_next_tick(&mut self) {
let elapsed = self.last_tick.elapsed();
if elapsed < self.interval {
thread::sleep(self.interval - elapsed);
}
self.last_tick = Instant::now();
}
}
let mut timer = PrecisionTimer::new(50);
loop {
send_click();
timer.wait_for_next_tick();
}
Memory Management
Keep RAM usage under 100MB:
let clickHistory: number[] = [];
const MAX_HISTORY_SIZE = 1000;
function recordClick(timestamp: number): void {
clickHistory.push(timestamp);
if (clickHistory.length > MAX_HISTORY_SIZE) {
clickHistory = clickHistory.slice(-MAX_HISTORY_SIZE);
}
}
function calculateCps(): number {
const now = Date.now();
const recentClicks = clickHistory.filter(t => now - t < 1000);
return recentClicks.length;
}
Building for Release
Windows Release Process
# 1. Update version in package.json and Cargo.toml
# 2. Clean previous builds
Remove-Item -Recurse -Force src-tauri/target/release/bundle -ErrorAction SilentlyContinue
# 3. Build release
npm run build
# 4. Installer location
# src-tauri/target/release/bundle/nsis/Blur-AutoClicker_X.X.X_x64-setup.exe
# 5. Test installer
Start-Process "src-tauri\target\release\bundle\nsis\*.exe"
Code Signing (Optional)
# Note: Windows Authenticode signing is separate from Tauri updater signing
# See docs/windows-release-trust.md for complete signing instructions
# Environment variables needed for signing
# WINDOWS_CERTIFICATE (base64 certificate)
# WINDOWS_CERTIFICATE_PASSWORD (certificate password)
Common Development Patterns
Creating a Custom Click Mode
interface CustomModeConfig {
pattern: number[];
repeat: boolean;
}
class CustomClickMode {
private config: CustomModeConfig;
private patternIndex: number = 0;
constructor(config: CustomModeConfig) {
this.config = config;
}
getNextDelay(): number {
const delay = this.config.pattern[this.patternIndex];
this.patternIndex = (this.patternIndex + 1) % this.config.pattern.length;
return delay;
}
async executePattern(): Promise<void> {
do {
for (const delay of this.config.) {
();
( (resolve, delay));
}
} (..);
}
}
customMode = ({
: [, , , ],
:
});
Statistics Tracking
interface ClickStatistics {
totalClicks: number;
sessionClicks: number;
averageCps: number;
peakCps: number;
uptime: number;
startTime: number;
}
class StatsTracker {
private stats: ClickStatistics;
private clickTimestamps: number[] = [];
constructor() {
this.stats = {
totalClicks: 0,
sessionClicks: 0,
averageCps: 0,
peakCps: 0,
uptime: 0,
startTime: Date.now()
};
}
recordClick(): void {
const now = Date.now();
this.stats.totalClicks++;
this.stats.sessionClicks++;
this..(now);
oneSecondAgo = now - ;
. = ..( t > oneSecondAgo);
currentCps = ..;
(currentCps > ..) {
.. = currentCps;
}
}
(): {
.. = .((.() - ..) / );
.. = .. >
? .. / ..
: ;
{ .... };
}
(): <> {
({ : . });
}
}
Troubleshooting
Windows SmartScreen Warning
The application shows SmartScreen warnings for unsigned installers:
- This is normal for open-source GitHub releases
- See
docs/windows-release-trust.md for signing information
- Users can click "More info" → "Run anyway"
CPS Accuracy Issues
If actual CPS doesn't match configured CPS:
const DEBUG = true;
async function debugClickAccuracy(targetCps: number, duration: number): Promise<void> {
const clicks: number[] = [];
const startTime = Date.now();
while (Date.now() - startTime < duration) {
const clickTime = Date.now();
await invoke('send_click');
clicks.push(clickTime);
if (DEBUG) {
const recentClicks = clicks.filter(t => clickTime - t < 1000);
console.log(`Target: ${targetCps} CPS, Actual: ${recentClicks.length} CPS`);
}
}
const totalTime = (Date.now() - startTime) / 1000;
const actualCps = clicks.length / totalTime;
accuracy = (actualCps / targetCps) * ;
.();
}
High RAM Usage
If RAM usage exceeds 100MB:
if (performance.memory) {
const usedMemory = performance.memory.usedJSHeapSize / 1024 / 1024;
console.log(`Memory usage: ${usedMemory.toFixed(2)} MB`);
if (usedMemory > 80) {
clickHistory = clickHistory.slice(-100);
if (global.gc) global.gc();
}
}
Build Errors
# Clean install
Remove-Item -Recurse -Force node_modules
Remove-Item package-lock.json
npm install
# Clean Rust build
cargo clean --manifest-path src-tauri/Cargo.toml
# Update Rust toolchain
rustup update stable-x86_64-pc-windows-msvc
# Rebuild
npm run build
Tauri Command Not Found
import { invoke } from '@tauri-apps/api/tauri';
{
"tauri": {
"allowlist": {
"all": false,
"fs": {
"all": false,
"readFile": true,
"writeFile": true
},
"globalShortcut": {
"all": true
}
}
}
}
Testing
describe('Click Accuracy', () => {
it('should click at specified CPS within 5% tolerance', async () => {
const targetCps = 50;
const duration = 5000;
const tolerance = 0.05;
const clicks = await testClickAccuracy(targetCps, duration);
const actualCps = clicks.length / (duration / 1000);
const lowerBound = targetCps * (1 - tolerance);
const upperBound = targetCps * (1 + tolerance);
expect(actualCps).toBeGreaterThanOrEqual(lowerBound);
expect(actualCps).toBeLessThanOrEqual(upperBound);
});
});
License
GPL-3.0 - See LICENSE.md