Configuration and login
Configuration
Configuration is stored within $XDG_CONFIG_HOME/cpg (called $config in this document) by default.
Overridable with $CPG_CONFIG_HOME environment variable.
When XDG variables are unset, the configuration directory is ~/.config/cpg
and the data directory is ~/.local/share/cpg.
Run the interactive setup before downloading or listing problems:
cpg init
It creates configuration files and directories. If configuration file of oj-prepare exists, it will be imported automatically.
You can also set the workspace root manually in $config/config.toml:
root = "/home/your-name/competitive-programming"
The JSON Schema for the configuration file is available on
https://raw.githubusercontent.com/sevenc-nanashi/competitive-programming-cli/refs/tags/v{version}/docs/public/config.schema.json,
or print it locally with cpg config --schema.
In addition to the configuration file, the following directories are created:
$config/config.toml: Configuration file.$config/config.local.toml: Optional machine-specific overrides forconfig.toml.$config/workspace_template: Template for workspace directory.- Files and directories within this directory is called "workspace template".
- This should contain root files for your workspace, such as
Gemfile,Cargo.toml, etc.
$config/problem_template: Template for problem directory.- Files and directories within this directory is called "problem template".
- This should contain files for a single problem, such as
solve.cpp,naive.rb, etc.
$config/contest_template: Template for contest directory.- Files and directories within this directory is called "contest template".
- This should contain files for a contest,
Cargo.tomlwith workspace configuration, etc.
$config/single_problem_template: Template for single problem directory.- Files and directories within this directory is called "single problem template".
- This should contain files that makes single problem directory self-contained, such as overwriting
Cargo.tomlwith one without workspace dependencies, etc.
These directories can be obtained by running cpg config:
cpg config
# Workspace root: /home/your-name/competitive-programming
# Configuration directory: /home/your-name/.config/cpg
# Cookies directory: /home/your-name/.local/share/cpg/cookies
# oj virtual environment directory: /home/your-name/.local/share/cpg/oj-venv
# Workspace template directory: /home/your-name/.config/cpg/workspace_template
# Problem template directory: /home/your-name/.config/cpg/problem_template
# Contest template directory: /home/your-name/.config/cpg/contest_template
# Single problem template directory: /home/your-name/.config/cpg/single_problem_template
# Print the workspace root
cpg config --root
# Print the configuration directory
cpg config --config-dir
cpg config --cookies-dir
cpg config --oj-venv-dir
cpg config --workspace-template-dir
cpg config --problem-template-dir
cpg config --contest-template-dir
cpg config --single-problem-template-dir
Local overrides
Create config.local.toml next to config.toml to override settings for the
current machine. Both files are read from $CPG_CONFIG_HOME when it is set,
otherwise from the configuration directory described above.
# config.local.toml
root = "~/local-competitive-programming"
[language.cpp]
compile = "clang++ -std=c++23 -O2 -o {binary} {input}"
[clipboard]
kind = "command"
command = "/mnt/c/Windows/System32/clip.exe"
Logging
CPG_LOG accepts tracing-subscriber's
EnvFilter syntax. Logs never appear on stdout.
CPG_LOG=debug cpg prepare https://atcoder.jp/contests/abc473/tasks/abc473_f
CPG_LOG=info,cpg=debug,reqwest=warn cpg prepare https://atcoder.jp/contests/abc473/tasks/abc473_f
CPG_LOG=off cpg list
Directory prefixes
To use lowercase letters for contest problem directory prefixes, add this at the
top level of config.toml (or config.local.toml):
alphabetic = true
Prefixes are a, ..., z, aa, ... and are left-padded with underscores to
match the longest prefix. For 27 problems, directories start with _a_, ..., _z_,
aa_. The default is false, which keeps zero-padded numeric prefixes.
Clipboard
cpg submit --clipboard copies the source after preprocessing and presubmit.
Choose its backend with [clipboard] in $config/config.toml:
[clipboard]
kind = "osc52"
osc52 is the default when the section is omitted. It sends an OSC 52 escape
sequence to stderr, asking the terminal to copy the text. The terminal must
support OSC 52 and allow clipboard writes, and the stderr stream must be a
terminal.
By default, clipboard contents are cleared when cpg submit --clipboard fails.
This is to prevent accidentally submitting the wrong source, because you will
paste the empty clipboard into the submission form, and many online judges reject
empty submissions. You can disable this behavior with:
[clipboard]
clear_on_failure = false
To use the system clipboard through arboard:
[clipboard]
kind = "arboard"
On Linux, a clipboard manager must retain the text after cpg exits; otherwise,
use a command such as wl-copy or xclip below.
To use a clipboard command instead:
[clipboard]
kind = "command"
command = "wl-copy"
command is required for this backend and runs through sh -c (cmd /C on Windows) in the current
directory. The complete UTF-8 text is piped to its standard input without adding
a newline. Command stdout and stderr go to cpg's stderr. A nonzero exit status
fails the copy; Ctrl-C stops the command and its process group.
For X11, you can use command = "xclip -selection clipboard".
On WSL, you might want to use command = "/mnt/c/Windows/System32/clip.exe" to
copy the content to the Windows clipboard, in case arboard fails to work.
Remote mode
cpg has a remote mode that changes behavior to work on a remote server.
- Clipboard backend is set to
osc52. - Copies the URL instead of opening it in a browser when
--openis specified.
By default, remote mode is automatically enabled when:
- SSH environment variables are detected,
CPG_REMOTEis set to1, or--remoteis specified on the command line.
You can disable SSH detection in $config/config.toml with:
remote = "manual"
Templates and setup commands
You can put files in the template directories to copy them into the workspace or problem directories when preparing problems or contests.
Also, you can run commands after copying templates by configuring [setup] to $config/config.toml to run shell commands after copying templates:
[setup]
workspace = ["git init", "bundle install"]
problem = "ruby setup_problem.rb"
contest = "ruby setup_contest.rb"
single_problem = "ruby setup_single_problem.rb"
Each key accepts a single command string or an array of command strings, which run in order. Put scripts in the corresponding template directory so they are available when the commands run. Commands also run when that template directory is absent, allowing setup entirely through commands.
| Key | Template | Working directory |
|---|---|---|
workspace |
workspace_template |
Single problem or contest root |
problem |
problem_template |
Each problem directory |
contest |
contest_template |
Contest root |
single_problem |
single_problem_template |
Single problem root |
Later templates overwrite earlier files with the same path.
Template and setup commands are applied in this order:
- Write
.cpg.tomlwith problem or contest metadata. - Copy
workspace_templateto the workspace root. - Copy
contest_templateto the contest root. (for contests) - Copy
problem_templateto each problem directory. - Copy
single_problem_templateto the problem root. (for single problems) - Run
[setup.problem]in each problem directory. - Run
[setup.workspace]in the workspace root. - Run
[setup.contest]in the contest root. (for contests) - Run
[setup.single_problem]in the problem root. (for single problems)
You would want to set bundle install or git clone https://github.com/atcoder/ac-library.git in the workspace template,
for example.
Login
This tool does not provide login form itself. You need to prepare cookies for each online judge and save them in Netscape HTTP Cookie Format. For example, you can use Get cookies.txt LOCALLY extension.
The cookies file is saved in $XDG_DATA_HOME/cpg/cookies by default, and the permission is 600.
# Login to an online judge
cpg login atcoder --cookie-file /path/to/cookies.txt
Use --info to verify the saved session and print its username and profile URL:
cpg login atcoder --info
cpg login yukicoder --info
cpg login codeforces --info
cpg login share-oj --info
cpg login atcoder-problems --info
It prints the user name on the first stdout line and the profile URL on the second.
Experimental oj support
URLs outside the native backends are automatically passed to a fork of online-judge-api-client. Supported URLs and operations depend on that client and the judge. For example:
cpg download https://onlinejudge.u-aizu.ac.jp/problems/ITP1_1_A
Install uv and make it available on PATH. On first use, cpg creates
$XDG_DATA_HOME/cpg/oj-venv, defaulting to ~/.local/share/cpg/oj-venv, and
installs its pinned API client.
oj backends use oj+<host> as the service name. For example, Aizu Online Judge is oj+onlinejudge.u-aizu.ac.jp.
cpg login oj+onlinejudge.u-aizu.ac.jp --cookie-file /path/to/cookies.txt
This backend is experimental. Login verification and submission may fail or be
unsupported for a judge, and cpg results is not supported. Downloading a contest
can be slower than with native backends.
Language settings
Add [language.<name>] tables to $config/config.toml. cpg selects a language
by the source file's extension. These settings apply to solutions, generators, reference solutions, and judge files.
| Key | Required | Purpose |
|---|---|---|
extensions |
Yes | File extensions without the leading dot, such as ["cpp", "cc"]. |
run |
Yes | Shell command to execute the solution or script. |
compile |
No | Shell command to compile or check the source before running it. |
preprocess |
No | Transform the source before local execution and submission. |
presubmit |
No | Transform the source only for submission, after preprocess. |
profile |
No | Named overrides for commands and submission language IDs, selected with --profile. |
submit |
No | Submission language IDs keyed by service, such as atcoder, yukicoder, and so on. |
In compile and run, {input} expands to the source path and {binary} to the same path with
its final extension removed on Linux/macOS or replaced with .exe on Windows.
Placeholder are automatically shell-quoted, so leave them unquoted.
When preprocessing is configured, {input} points to the transformed source.
Direct commands after -- do not use these language settings.
All language commands (compile, run, preprocess, and presubmit), including
profile overrides, support the following placeholders:
{workspace}: the absolute path to the contest root or single problem directory.{problem}: the absolute path to the problem directory, even for sources in subdirectories.
[language.cpp]
extensions = ["cpp"]
compile = "g++ -std=c++23 -I{workspace}/ac-library -I{problem}/include -o {binary} {input}"
run = "{binary}"
Build profiles
Use [language.<name>.profile.<profile>] to override these commands.
Note that this overrides the entire command, not appending extra commands or flags.
You can use an empty string ("") or false to disable an inherited command.
[language.python.profile.plain]
preprocess = false
presubmit = ""
compile = false
For example, use a different interpreter and submission language together:
[language.python.profile.pypy]
run = "pypy3 {input}"
[language.python.profile.pypy.submit]
yukicoder = "pypy3"
An explicit --language ID takes precedence over the profile's submit setting.
Executable files
If no configured extension matches, executable files use the built-in
executable language, which runs {input} without compilation. This works
with extensionless binaries and scripts with execute permission and a shebang
on Linux/macOS, and .exe or .com files on Windows:
cpg test ./a.out
cpg generate --count 10 ./generator
To customize the fallback, define [language.executable] in config.toml:
[language.executable]
extensions = []
run = "{input}"
[language.executable.profile.debug]
run = "env DEBUG=1 {input}"
Source transformations
Optional language.<name>.preprocess runs before compilation (or execution for
interpreted languages) and before submission. language.<name>.presubmit runs
only for submission, after preprocess.
[language.cpp]
extensions = ["cpp"]
preprocess = "ruby ~/expand.rb {input} {processed}"
compile = "g++ -std=c++23 -O2 -o {binary} {input}"
run = "{binary}"
The same placeholder is available in presubmit. Use presubmit instead of
preprocess to apply a transformation only when submitting.
See the ACL recipe for an example.
Submission language IDs
Add the judge's language ID to an existing language's submit table. For C++23:
[language.cpp.submit]
atcoder = "6017"
yukicoder = "cpp23"
IDs must be quoted strings, including numeric IDs. These IDs can be found when you
attempt to submit a solution with an unconfigured language with cpg submit.
A profile's submit table can also override these IDs.
See submitting solutions.
Recipes
Copy the settings you need into $config/config.toml and install the compilers
or interpreters used by their commands.
C++ with debugging and a fast profile
This configuration uses GCC with C++23. The default build enables debug symbols and
UndefinedBehaviorSanitizer.
-fno-sanitize-recover=all makes a detected error stop the program so the test
reports RE. The fast profile enables optimization and defines ONLINE_JUDGE.
[language.cpp]
extensions = ["cpp", "cc"]
compile = "g++ -std=c++23 -O0 -g -Wall -Wextra -fsanitize=undefined -fno-sanitize-recover=all -o {binary} {input}"
run = "{binary}"
[language.cpp.profile.fast]
compile = "g++ -std=c++23 -O2 -Wall -Wextra -DONLINE_JUDGE -o {binary} {input}"
[language.cpp.submit]
atcoder = "6017" # C++23 (GCC 15.2.0)
yukicoder = "cpp23"
# If you prefer Clang:
#
# atcoder = "6116" # C++23 (Clang 21.1.0)
# yukicoder = "cpp-clang"
#
# But note that Clang on yukicoder is C++17, so you may need to change -std=c++23 to -std=c++17 in the compile commands.
Ruby
The compile command checks syntax with ruby -c. The run command executes the script.
[language.ruby]
extensions = ["rb"]
compile = "ruby -c {input}"
run = "ruby {input}"
[language.ruby.submit]
atcoder = "6087" # Ruby 3.4 (ruby 3.4.5)
yukicoder = "ruby"
Python
The run command executes the script with Python 3.
[language.python]
extensions = ["py"]
run = "python3 {input}"
[language.python.submit]
atcoder = "6083" # PyPy 3.11-v7.3.20
yukicoder = "pypy3"
# Or if you prefer CPython:
#
# atcoder = "6082" # Python (CPython 3.13.7)
# yukicoder = "python3"
Expand AtCoder Library headers
With ac-library checked out at
~/ac-library, use its expander
to inline ACL headers before local compilation and submission. This requires
Python 3 and GCC.
[language.cpp]
extensions = ["cpp"]
preprocess = "python3 ~/ac-library/expander.py --console --lib ~/ac-library {input} > {processed}"
compile = "g++ -std=c++23 -O2 -o {binary} {input}"
run = "{binary}"
[language.cpp.submit]
atcoder = "6017" # C++23 (GCC 15.2.0)
yukicoder = "cpp23"
To expand only for submission, rename preprocess to presubmit and add
-I "$HOME/ac-library" to your compilation command so local tests can find
the headers without expansion.