feat: first-launch welcome message for all install methods

Show welcome banner once per install (Python, JS, Docker).
Uses marker file in ~/.cloakbrowser/ — resets on cache clear or update.
Replaces logger.info() calls that were invisible by default.

Bump to v0.3.8.
This commit is contained in:
Cloak-HQ
2026-03-05 07:49:08 +01:00
parent 0a99a1458a
commit e411f24cf3
5 changed files with 50 additions and 15 deletions
+3 -1
View File
@@ -30,7 +30,9 @@ RUN cd js && npm install && npm run build
COPY examples/ examples/ COPY examples/ examples/
# Pre-download stealth Chromium binary during build (not at runtime) # Pre-download stealth Chromium binary during build (not at runtime)
RUN python -c "from cloakbrowser import ensure_binary; ensure_binary()" # Remove welcome marker so users see it on first container run
RUN python -c "from cloakbrowser import ensure_binary; ensure_binary()" \
&& rm -f ~/.cloakbrowser/.welcome_shown
# CLI shortcuts # CLI shortcuts
COPY bin/cloaktest /usr/local/bin/cloaktest COPY bin/cloaktest /usr/local/bin/cloaktest
+1 -1
View File
@@ -1 +1 @@
__version__ = "0.3.7" __version__ = "0.3.8"
+21 -3
View File
@@ -50,6 +50,25 @@ DOWNLOAD_TIMEOUT = 600.0
UPDATE_CHECK_INTERVAL = 3600 UPDATE_CHECK_INTERVAL = 3600
def _show_welcome() -> None:
"""Show welcome message on first launch. Uses a marker file to show only once."""
marker = get_cache_dir() / ".welcome_shown"
if marker.exists():
return
print()
print(" CloakBrowser — stealth Chromium for automation")
print(" https://github.com/CloakHQ/CloakBrowser")
print()
print(" Issues? https://github.com/CloakHQ/CloakBrowser/issues")
print(" Star us if CloakBrowser helps your project!")
print()
try:
marker.parent.mkdir(parents=True, exist_ok=True)
marker.write_text("")
except OSError:
pass
def ensure_binary() -> str: def ensure_binary() -> str:
"""Ensure the stealth Chromium binary is available. Download if needed. """Ensure the stealth Chromium binary is available. Download if needed.
@@ -77,6 +96,7 @@ def ensure_binary() -> str:
if binary_path.exists() and _is_executable(binary_path): if binary_path.exists() and _is_executable(binary_path):
logger.debug("Binary found in cache: %s (version %s)", binary_path, effective) logger.debug("Binary found in cache: %s (version %s)", binary_path, effective)
_show_welcome()
_maybe_trigger_update_check() _maybe_trigger_update_check()
return str(binary_path) return str(binary_path)
@@ -146,9 +166,7 @@ def _download_and_extract(version: str | None = None) -> None:
_verify_download_checksum(tmp_path, version) _verify_download_checksum(tmp_path, version)
_extract_archive(tmp_path, binary_dir, binary_path) _extract_archive(tmp_path, binary_dir, binary_path)
logger.info("Visit https://cloakbrowser.dev for docs and release notifications.") _show_welcome()
logger.info("Issues? https://github.com/CloakHQ/CloakBrowser/issues")
logger.info("Star us if CloakBrowser helps: https://github.com/CloakHQ/CloakBrowser")
finally: finally:
# Clean up temp file # Clean up temp file
tmp_path.unlink(missing_ok=True) tmp_path.unlink(missing_ok=True)
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "cloakbrowser", "name": "cloakbrowser",
"version": "0.3.7", "version": "0.3.8",
"description": "Stealth Chromium that passes every bot detection test. Drop-in Playwright/Puppeteer replacement with source-level fingerprint patches.", "description": "Stealth Chromium that passes every bot detection test. Drop-in Playwright/Puppeteer replacement with source-level fingerprint patches.",
"type": "module", "type": "module",
"main": "dist/index.js", "main": "dist/index.js",
+24 -9
View File
@@ -65,6 +65,7 @@ export async function ensureBinary(): Promise<string> {
const binaryPath = getBinaryPath(effective); const binaryPath = getBinaryPath(effective);
if (fs.existsSync(binaryPath) && isExecutable(binaryPath)) { if (fs.existsSync(binaryPath) && isExecutable(binaryPath)) {
showWelcome();
maybeTriggerUpdateCheck(); maybeTriggerUpdateCheck();
return binaryPath; return binaryPath;
} }
@@ -138,6 +139,28 @@ export async function checkForUpdate(): Promise<string | null> {
return latest; return latest;
} }
// ---------------------------------------------------------------------------
// Welcome message (shown once per install)
// ---------------------------------------------------------------------------
function showWelcome(): void {
const marker = path.join(getCacheDir(), ".welcome_shown");
if (fs.existsSync(marker)) return;
console.log();
console.log(" CloakBrowser — stealth Chromium for automation");
console.log(" https://github.com/CloakHQ/CloakBrowser");
console.log();
console.log(" Issues? https://github.com/CloakHQ/CloakBrowser/issues");
console.log(" Star us if CloakBrowser helps your project!");
console.log();
try {
fs.mkdirSync(getCacheDir(), { recursive: true });
fs.writeFileSync(marker, "");
} catch {
// Non-fatal
}
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Internal helpers // Internal helpers
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@@ -177,15 +200,7 @@ async function downloadAndExtract(version?: string): Promise<void> {
} }
await extractArchive(tmpPath, binaryDir, binaryPath); await extractArchive(tmpPath, binaryDir, binaryPath);
console.log( showWelcome();
`[cloakbrowser] Visit https://cloakbrowser.dev for docs and release notifications.`
);
console.log(
`[cloakbrowser] Issues? https://github.com/CloakHQ/CloakBrowser/issues`
);
console.log(
`[cloakbrowser] Star us if CloakBrowser helps: https://github.com/CloakHQ/CloakBrowser`
);
} finally { } finally {
// Clean up temp file // Clean up temp file
if (fs.existsSync(tmpPath)) { if (fs.existsSync(tmpPath)) {