Open-source project
jmerle/competitive-companion avatar
jmerle/competitive-companion

Competitive Companion: turning a judge problem page into a local test harness

Browser extension which parses competitive programming problems

1,338 stars218 forksTypeScriptMIT

At a glance

What is it?
Competitive Companion is a browser extension that parses competitive programming problems from dozens of online judges, extracts the sample test cases and the time and memory limits, and pushes all of it into an editor or a competitive programming helper. It suits someone who solves problems on a judge and wants the boilerplate gone, and it is a parser that has to keep up with sites that change their markup.
Who is it for?
Competitive Companion fits a competitive programmer who works on a judge and already uses an editor integration, because the extension removes the transcription of samples and limits and because the parsed data is not locked into one tool, since any program that can read the payload can consume it. Skip it if you only read problems, since the whole point is the hand-off to a coding tool, and skip it if you depend on a judge the list does not cover.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 8 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A parser for problem pages, and a data format other tools read

Competitive Companion is a browser extension that parses competitive programming problems from various online judges, like AtCoder and Codeforces, and sends them to various tools, like CP Editor and CPH.

What it extracts is listed plainly: problems and contests, and data like the example test cases and the time and memory constraints.

That list is the value. A competitive programming problem page carries a small amount of machine-readable structure that a human reads with their eyes and a human then types into an editor. The sample inputs and outputs, the time limit, the memory limit, the problem name. Transcribing those is exactly the kind of tedious, error-prone step that competitive programming helpers were invented to remove, and this extension is the front end of that pipeline.

The interesting design decision is the boundary between the extension and the tools. The extension does the parsing and the sending, and the tool does the running. The documentation lists more than twenty tools that use Competitive Companion, including acmX, Assistant.nvim, AutoCp, Caide, CHelper, the Competitive Programming Gradle Plugin, Competitive Programming Helper, CompetiTest.nvim, CP-Assist, CP Editor, cpbooster, CPH-NG, cphelper.nvim, Fast Olympic Coding, Faster-OJ.nvim, Hightail, JHelper, LazyCPH, Mind Sport, Red Panda Dev-C++, and rust-competitive-helper.

That list spans editors, IDE plugins, a Neovim plugin, a Gradle plugin, a Rust crate, a JavaScript package and a competitive programming helper for Visual Studio Code. A single extension serving all of them means the payload format has to be a published contract rather than a private conversation between two programs, and the documentation explicitly invites other tools to join, saying any other tool that can parse the data being sent can read more about that in the custom tools section.

The language is TypeScript, the licence is MIT, and the project is published on both the Chrome Web Store and Mozilla Add-ons.

One parser per judge, and judges change their markup

The supported websites table is the longest part of the documentation, and its shape tells you how the project is built.

There is a row per judge, with two columns, one for a problem parser and one for a contest parser. The list includes 33OJ, A2 Online Judge, ACMP, AcWing, Aizu Online Judge, Algotester, AlgoZenith, Anarchy Golf, AtCoder, A.Y. Jackson Online Judge, Baekjoon Online Judge, BAPS OJ, beecrowd, BJTU OJ, Bloomberg CodeCon, BUCTOJ, CodeChef, CodeDrills, Codeforces, CodeMarshal, CodeRun, CodeUp, COJ, Contest Hunter, CPython.uz, CS Academy, CSES, CSGOJ, CSU-ACM Online Judge, CYEZOJ, Daimayuan Online Judge, Dimik OJ, DMOJ, DOMjudge, DotOJ, Eolymp, ECNU Online Judge, FZU Online Judge, Google Coding Competitions, HackerEarth, HackerRank, HDOJ, HIT Online Judge, hihoCoder, HKOI Online Judge, HOJ, Hrbust Online Judge, Hydro, ICPC Live Archive, InfoArena, ITCoder HUTECH, Jutge, Kattis, KEP.uz, Kilonova and more.

The two columns are not the same set, and the exceptions are informative. DOMjudge has a contest parser but no problem parser, which is unusual and suggests the site structures its individual problems in a way the author did not implement. Some judges have only a problem parser, since a site that hosts single problems but not scheduled contests has nothing to parse for the contest side.

The reason this is a long table rather than a generic solution is the nature of the work. A parser has to know where in the page the time limit is, which element holds the sample input block, whether the sample output is in a separate tab, and how the site marks its code blocks. Each judge is a different HTML structure with different conventions, and there is no standard to hang a generic parser on. So the project is a large collection of per-site parsers, and the maintenance reality follows from that.

The topics list names atcoder, codeforces, icpc and kattis as well as browser-extension and competitive-programming, which is the same idea from the other end: the sites with the most users get the most attention, and the long tail of regional judges gets whatever is left over.

Building the extension for two browsers from one script

The build setup is a small, well-organised TypeScript project, and the scripts show how the two browser targets are handled.

The package is `competitive-companion`, version 2.65.0, marked private and with type module. The package manager is pnpm, with a `pnpm-lock.yaml` and a `pnpm-workspace.yaml` at the top level.

The build and package scripts are the interesting part. The build script runs every script matching the build pattern, and the two targets are separate:

code
build:chrome
build:firefox

Each calls the same script with a different target and two flags, `tsx scripts/build/extension.ts chrome true false`, where the two booleans control the production and watch modes. That is the whole multi-browser strategy in one line: one build script, a target argument, and a flag pair, so Chrome and Firefox cannot drift apart because they are produced by the same code path.

The package scripts then wrap the build with `web-ext build`, which is Mozilla's tool, used for both browsers, producing a zip named after the package and version with a chrome or firefox suffix. The web-ext tool is used for Chrome as well, which is convenient since it means one packaging path rather than two.

The lint setup has four parts, and they are worth reading as a statement about what matters. `lint:eslint` runs eslint with the codeframe formatter over the source, tests and scripts. `lint:prettier` checks formatting and, notably, uses `--ignore-path .gitignore` so that generated and ignored files are skipped. `lint:tsc` runs `tsc --noEmit`. And `lint:package` is the unusual one: it builds the Firefox target and then runs `web-ext lint` on the result, so the extension is checked against Mozilla's own manifest and packaging rules as part of linting.

The test setup is a single spec file, `tests/parsers.spec.ts`, run after a `build:test` step that uses a separate build script, and there is a `test:no-headless` variant that sets `HEADLESS=false` through cross-env, which implies the parser tests drive a real browser to load real judge pages. That is the only way to test a scraper honestly, and it also means the test suite depends on the sites staying up and unchanged.

There is a `scripts/generate-banners.ts` script for the store listing images, and the repository has a `media/` directory for them.

What the payload contains, and why the editor still matters

It is worth being precise about what the extension does not do, because the name suggests more than it delivers.

Competitive Companion parses and sends. It does not run your code, and it does not decide when to stop. The tool on the other end does that. Competitive Programming Helper, for instance, is the piece that compiles your file, feeds it the test cases, and compares against the expected output.

That division is what makes the extension useful across twenty tools. A minimal payload is a problem name, an input file, an output file, and the limits, and the receiving tool decides how to present it. Some tools open a file with the samples written into it, some split them into separate input and output files, some show a test panel.

The contest parser is a different job. Where the problem parser handles one statement, the contest parser handles a listing of problems, so that a whole round can be pulled in at once, which is what a practice session or a virtual contest needs.

The time and memory constraints are the other extracted field worth singling out. They are the two numbers that change how you approach a problem, a two second limit with a 1024 megabyte ceiling implies a different algorithm than a one second limit with 256 megabytes. Having them carried into the editor as configuration, rather than read off the page, is part of what makes the tool work, because it means the test runner can enforce them.

So the flow is: you open a problem, the extension fires, the data is extracted from the page, and it is handed to the tool that will actually let you solve it. The extension is the adapter between a website's HTML and a tool's data model, and it is deliberately not the tool.

The failure mode is a judge changing its page

A scraper has one characteristic failure, and it is worth being clear about it before you build a habit around the extension.

Every parser in this project encodes assumptions about a specific website's markup. When a judge redesigns its problem page, the parser stops finding the samples, and the symptom is that clicking the button does nothing useful rather than an error message. There is no upstream you can file a bug against, and the fix has to wait for the extension to be updated by its author.

The test suite has the same exposure. If the parser tests drive real pages, then a judge's redesign breaks the build as well as the extension, and the difference is that the failure is at least visible in CI rather than in your browser.

The scale of the problem is set by the size of the table. Dozens of judges with dedicated parsers is a manageable amount of maintenance for one person. The long tail of regional and university judges is where the effort goes, and where a site that redesigns rarely gets a fix quickly, because the user base for that row is small.

The mitigation is the two-column structure. A judge that supports contests but not individual problems still works for the contest workflow, and a judge with a broken problem parser may still have a working contest parser, so the coverage degrades gracefully rather than all at once.

There is a second limitation that is not about breakage. The extension extracts what is on the page, and what is on the page is the public statement. If a judge does not publish the time limit on the statement page, the extension cannot send it, and the receiving tool falls back to its default. That is a quiet difference between problems rather than a failure, which is harder to notice.

The alternative approaches are worth naming. Copying the samples by hand takes a few seconds per problem and has no dependency, and for a casual session it is not worth automating. Some judges have their own editor integrations that avoid the browser round trip entirely. And some competitive programming helpers have their own problem scraping, which duplicates this work rather than consuming it. The difference in approach is that Competitive Companion puts the parsing in the browser, where the page already is, and publishes the result as a format other tools can consume, so the parsing work is done once instead of once per tool.

Editorial conclusion

Competitive Companion fits a competitive programmer who works on a judge and already uses an editor integration, because the extension removes the transcription of samples and limits and because the parsed data is not locked into one tool, since any program that can read the payload can consume it. Skip it if you only read problems, since the whole point is the hand-off to a coding tool, and skip it if you depend on a judge the list does not cover. Before you rely on it, check the supported websites table for your judge, and note that the extension is a scraper, so a judge that changes its markup will break its parser until the extension is updated, with the last push on 2026-09-30 and the current release 2.65.0 from 2026-06-29.

Frequently asked questions

What does the Competitive Companion extension do?

It parses competitive programming problems from various online judges like AtCoder and Codeforces and sends them to various tools like CP Editor and CPH, extracting the example test cases and the time and memory constraints.

Which websites does Competitive Companion support?

A long list of judges, each with a problem parser and a contest parser column, including AtCoder, Codeforces, CodeChef, Baekjoon Online Judge, CSES, DMOJ, Kattis, Hydro, Eolymp, beecrowd, HackerRank, HackerEarth and many regional judges.

Which tools can use Competitive Companion?

More than twenty are listed, including CP Editor, Competitive Programming Helper, Caide, CP-Assist, CHelper, JHelper, LazyCPH, Hightail, cphelper.nvim, CompetiTest.nvim, Assistant.nvim, AutoCp, cpbooster, Red Panda Dev-C++ and rust-competitive-helper, plus any other tool that can parse the data being sent.

How do I install Competitive Companion?

Install the Chrome extension from the Chrome Web Store or the Firefox add-on from Mozilla Add-ons. The project is MIT licensed and the last push was on 2026-09-30.

Does Competitive Companion run my code for me?

No. It parses and sends the problem data, and the tool on the other end handles compiling, running the test cases and comparing the output, which is why the extension can serve editors, IDE plugins, a Neovim plugin and a Rust crate equally.

Official sources

  1. jmerle/competitive-companion on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/jmerle-competitive-companion.svg)](https://hysenlabs.com/projects/jmerle-competitive-companion)

Was this useful?