Codeforces Round 1133 (Div. 1, Div. 2) is coming soon! Register here. ×

forrealtho's blog

By forrealtho, history, 7 days ago, In English

Hey Codeforces,

Like many of you, I wanted an automated, hands-off way to back up all my Accepted solutions to GitHub so I could review my progress over time.

However, after trying existing extensions out there, I kept running into recurring issues:

  • Requiring an active Codeforces tab session: Many tools rely on content scripts scraping the DOM. If you practice using CLion/VS Code, close your tabs, or submit through tools like Competitive Companion, sync fails.

  • Hidden tabs popping up: Some tools spawn pinned/hidden tabs (chrome.tabs.create), which break with ACCESS_DENIED_ERROR on contest submissions.

  • Overwriting solutions: Most tools key by Problem ID (e.g. 1872A.cpp). If you solve a problem with brute force and later rewrite an optimized $$$O(N \log N)$$$ version or port it to Rust, your earlier Accepted attempt gets overwritten.

  • Plagiarism risk: Pushing solutions immediately to a public repository during live rated contests creates a real risk of plagiarism checks flagging your code.

To fix these issues, I built CommitForce from scratch. It is open-source (MIT licensed) and now officially available on both Microsoft Edge Add-ons and Mozilla Firefox AMO.

How it works under the hood

1. Zero Open Tabs Required (Cryptographic API Signing)

CommitForce does not touch the DOM or scrape HTML pages. Instead, it runs as a headless background service worker that queries the official Codeforces REST API (user.status with includeSources=true) using request signing:

apiSig = RAND + sha512Hex("RAND/user.status?PARAMS#SECRET")

RAND is 6 random hexadecimal characters. PARAMS is the query string with parameters sorted alphabetically by name (including apiKey and time). SECRET is your Codeforces API secret.

Because requests are cryptographically authenticated with your CF API credentials, Codeforces directly returns the full solution source code in the API payload. You can submit from any editor or IDE, close your browser, and synchronization occurs reliably in the background.

2. Contest-Safe Upload Protection

To stop the extension from publishing during a live contest: * CommitForce automatically checks whether a submission was made during an active contest. * If a contest is in progress, the solution is staged locally in an encrypted queue. * The solution is only synchronized to GitHub once the contest round has officially ended.

3. Preserves Every Accepted Solution (Deduplicated by Submission ID)

CommitForce organizes your repository by difficulty rating and problem folder, indexing files by Codeforces Submission ID:

Codeforces/
├── 800/
│   ├── 1872A_Two_Vessels/
│   │   ├── 222111000.cpp   # First AC (C++ brute force)
│   │   └── 222111555.py    # Second AC (Python rewrite)
│   └── 1915C_Can_I_Square/
│       └── 239840112.rs    # Accepted solution (Rust)
└── 1200/
    └── 1985E_Secret_Box/
        └── 265001122.cpp

Git blob SHAs are computed locally before pushing to prevent duplicate commits or clobbering existing custom files.

4. Dynamic Streak Fire Engine & Dashboard

  • Tracks your Current Streak, All-time Record, and rolling 365/30-day records computed from your full activity history.
  • Features 6 reactive flame tiers (Cold Start → Kindling Ember → Steady Flame → Blazing Torch → Roaring Inferno → Legendary Plasma) directly in the extension popup and dashboard.
  • Historical import lets you filter by problem rating, tags, or programming language.

5. Privacy

Your Codeforces API secret and GitHub tokens are encrypted on your device (PBKDF2-SHA256, 600,000 iterations, AES-GCM-256). The extension only asks for access to codeforces.com and api.github.com. The one server I run is a small Cloudflare Worker that handles the GitHub App sign-in token exchange. It never sees your Codeforces credentials or your code. No analytics. The source is MIT licensed, so you can audit it.


Limitations

  • Chrome Web Store listing is still pending, so Chrome and Brave users need to manually load the release ZIP via chrome://extensions.
  • You need to create a Codeforces API key and secret (Settings → API).
  • Requests are limited to 1 per 2.1 seconds, so the first import of a large history takes a while.
  • Automatic sync runs every 6 hours by default (configurable down to 1 hour). Use Sync now for an immediate run.

Links & Installation

If you find this useful or want to support future development, a ⭐ on GitHub would mean a lot!

Feel free to leave your thoughts, bug reports, or feature suggestions below. Happy coding!

  • Vote: I like it
  • 0
  • Vote: I do not like it

»
7 days ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

Auto comment: topic has been updated by forrealtho (previous revision, new revision, compare).

»
7 days ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

What a great community to just hate on people..

»
7 days ago, hide # |
 
Vote: I like it +4 Vote: I do not like it

hello sir how do you actually install this need a tutorial

  • »
    »
    6 days ago, hide # ^ |
     
    Vote: I like it +1 Vote: I do not like it

    You can download in directly on Firefox or windows edge browser, but if your are using brave or chrome then you have to download it from the releases from GitHub and load it into your browser extension

    • »
      »
      »
      6 days ago, hide # ^ |
       
      Vote: I like it +4 Vote: I do not like it

      i have downloaded it i understood that i have to load it but how do i load it thats what i was asking this seemes pretty cool extension to have

      • »
        »
        »
        »
        6 days ago, hide # ^ |
         
        Vote: I like it +4 Vote: I do not like it

        i understood how to load it thanks for creating such a cool extension!

        • »
          »
          »
          »
          »
          6 days ago, hide # ^ |
          ← Rev. 2  
          Vote: I like it +1 Vote: I do not like it

          Thanks <3, consider reviewing it on the webstore or by star on github

»
6 days ago, hide # |
← Rev. 2  
Vote: I like it +4 Vote: I do not like it

It would be helpful if you could address the security aspect of this extension. I don't see any security.txt or anything related to security at all in the source code. Also, when entering the api key and the secret the extension just closes when you try to copy both of them. You can try reproducing this bug copy the key paste it and then try copying the secret the extension doesn't remember that you pasted a key and typed your cf handle earlier and hence you can't really copy and paste sequentially. Moreover, the ui is very AI, it would be lovely if you could make the ui cleaner. Also, I am sure I don't understand how this works but from what I understood is that GitHub sign-in needs a secret that can’t be kept inside an extension. So the extension sends the one-time GitHub login code, and later the refresh token, to the your Worker. The Worker swaps it for a GitHub token and passes it back. The repo’s version of that code (backend/src/index.ts) does only that and stores nothing. But I can’t check that the deployed Worker runs exactly this code, or that the store version of the extension matches the repo. It would be helpful if you could shed some light on this as well. Good job btw! Dunno the reason for downvotes lmao

  • »
    »
    6 days ago, hide # ^ |
    ← Rev. 2  
    Vote: I like it +1 Vote: I do not like it

    thanks for checking it out!

    1. good catch on the popup bug lol, completely forgot that popups lose state on blur because while testing i had my credentials in my clipboard...just pushed a fix to main that caches the draft in session storage so it wont reset when you switch tabs to copy the secret.

    2. added a SECURITY.md in the repo explaining the encryption and permissions.

    3. regarding the worker, you understood it correctly. it only does the github token swap so the client secret isnt exposed in extension code. it never touches your cf keys or solutions. but yeah fair point that you cant verify what's deployed, you can always self-host the worker from the backend folder if you want full control.

    4. noted on the ui, will make it cleaner and more minimal in the next update.