How to contribute
Contributions are welcome. This project values clear, practical, well-sourced content that follows consistent editorial, technical, and licensing standards.
You can contribute through any of the following workflows:
- GitHub-based contributions (pull requests using
gh/git) - File- and patch-based contributions using Git (anonymous workflow)
- File- and patch-based contributions using
got(OpenBSD workflow) - Patch creation from signed archive snapshots (archive-based workflow)
Content guidelines
- Keep content concise, precise, and actionable.
- Use a respectful, formal, neutral tone.
- Avoid commercial endorsements or promotional language.
- Write in U.S. English, and include translations whenever possible.
- Use repository templates when available (see templates/).
- Cite reliable sources, and include links for tools, commands, standards, and references.
- Do not include personal data, credentials, or sensitive information.
- Follow existing markup and formatting conventions (headings, paragraphs, tags, etc.).
- Optimize all media assets and store them within the repository (e.g. images/).
Licensing
All contributions must comply with the project license at ./license.html. If any content (code, images, or other assets) is not covered by this license, clearly declare the exception at the beginning of the file and include the applicable license or permission notice.
Suggested exception notice format:
EXCEPTIONS: files/images/thirdparty.jpg — licensed under CC BY 4.0 (see LICENSE in images/) some-code/snippet.c — used with permission from upstream (MIT)
Method 1: Contributing via GitHub (gh / git)
This workflow is for contributors with GitHub accounts who prefer to collaborate online through pull requests (PRs).
- Fork the repository on GitHub.
- Clone your fork locally.
- Create a dedicated branch for your changes.
- Commit your work with a clear, descriptive commit message.
- Open a pull request that summarizes your contribution.
Recommended workflow using GitHub CLI:
gh repo fork daviduhden/cypherpunk-handbook --clone=true cd cypherpunk-handbook git switch -c my-article git add articles/my-article.html data/articles.json git commit -m "Add article: My Article" git push --set-upstream origin my-article gh pr create --fill
Alternative workflow using plain Git:
git clone https://github.com/daviduhden/cypherpunk-handbook.git cd cypherpunk-handbook git switch -c my-article git add articles/my-article.html data/articles.json git commit -m "Add article: My Article" git push origin my-article
Method 2: Contributing via files and patches
This workflow is for contributors who prefer anonymous collaboration or do not use GitHub accounts.
Submitting individual files
- Send files directly to the SimpleX group.
- Files must be attached without compression.
- Archive formats (zip, tar, tar.gz, etc.) are ignored.
- All formatting, metadata, and licensing requirements must be met.
Submitting Git patches (preferred)
git clone https://github.com/daviduhden/cypherpunk-handbook.git cd cypherpunk-handbook git switch -c my-contribution git add articles/my-article.html data/articles.json git commit -m "Add article: My Article" git format-patch -1 HEAD
Send the generated .patch file(s) and other attachments
uncompressed to the SimpleX
group.
Method 3: Contributing via got (Game of Trees)
This workflow is for contributors on OpenBSD who prefer a patch-based process without relying on GitHub accounts.
Submitting Git-compatible patches using got (preferred)
got clone https://github.com/daviduhden/cypherpunk-handbook.git cypherpunk-handbook.git got checkout cypherpunk-handbook.git cypherpunk-handbook cd cypherpunk-handbook got branch -c main my-contribution got update -b my-contribution got add articles/my-article.html got add data/articles.json got commit -m "Add article: My Article" got diff main my-contribution > 0001-Add-article-My-Article.patch
Before committing, make sure GOT_AUTHOR is set or
configured in got.conf / Git configuration, otherwise
got commit will refuse to run.
Send the generated .patch file(s) and other attachments
uncompressed to the administrator of this website via email.
The resulting patch is a standard unified diff, compatible with patch(1) and Git-based workflows.
Method 4: Contributing via archive snapshots
This workflow lets contributors work directly from the signed archive instead of the Git repository. It is useful for offline or anonymous contributions.
Steps:
- Download the latest signed archive and its checksum/signature from
archive/cypherpunk-handbook.tar.gz. - Verify the archive checksum and signature before extracting.
- Extract the archive into a temporary working directory:
mkdir -p ~/cypherpunk-handbook-work tar -xzf cypherpunk-handbook.tar.gz -C ~/cypherpunk-handbook-work cd ~/cypherpunk-handbook-work
- Edit or add files as needed, following the site’s article templates and metadata requirements.
- Generate patch files based on the changes relative to the extracted
archive:
diff -Naur original/ modified/ > 0001-my-contribution.patch
Tip: Use the extracted archive as
original/and your working directory asmodified/. - Send the generated
.patchfile(s) and other attachments uncompressed to the site's administrator or submission point (email or SimpleX group).
Submitting Articles
To publish a new article, create an HTML file in articles/ and include a header with the following elements:
- kicker: a short category, tag, or label for the
article, inside a
<p class="kicker">element. - title: the main article title inside a
<h2>element. - meta: author information and last updated date
inside a
<p class="meta">element, using a<time>element with the ISO date. - lede: a short paragraph (
<p class="lede">) summarizing the value and context of the article in one or two sentences. - TL;DR section: a
<section>inside the header containing a<h2>TL;DR</h2>and an unordered list (<ul>) of 2–4 primary takeaways or recommendations.
<article>
<header id="article-header">
<p class="kicker">CATEGORY OR TAG</p>
<h2>Article Title</h2>
<p class="meta">By AUTHOR - Updated
<time datetime="2025-01-01">DATE</time>
</p>
<p class="lede">One or two sentences that set reader expectations
and highlight the value of the article.</p>
<section>
<h2>TL;DR</h2>
<ul>
<li>Primary takeaway or recommendation.</li>
<li>Another concise outcome or decision.</li>
<li>Links to supporting resources if helpful.</li>
</ul>
</section>
</header>
Use the provided article template and update the following files:
data/articles.json Structure
The site uses data/articles.json as an index for articles and feeds. Each top-level key is an article ID (slug). Example:
{
"my-article-slug": {
"en": "articles/my-article.html",
"pubdate": "2025-12-18",
"title_en": "My Article Title"
}
}
Set "pubdate" to an ISO date
(YYYY-MM-DD) to control the publication date in feeds.
Author Metadata and Pseudonyms
Include the author name in the article header following the template
(see the <p class="meta"> line in templates/articles.html
). The author can use a real name or a pseudonym; real names are
optional.
After updating the article file and data/articles.json,
regenerate the feeds or open a pull request. The maintainer will run the
site scripts in scripts/ if needed.
Stripping metadata from files
Before submitting articles, images, videos, audio, or other assets, we recommend removing potentially sensitive metadata. For most file types, including SVG and PDF, mat2 (Metadata Anonymisation Toolkit 2) is the preferred tool. Video and audio files can be cleaned with ffmpeg.
-
mat2 removes metadata from images, documents, audio,
and video files. By default, it creates a new file with
metadata removed:
mat2 filename.pdf mat2 filename.png mat2 filename.jpg
-
exiftool can also be used but is not recommended
for PDFs:
exiftool -all= filename.jpg
-
ffmpeg can remove metadata from videos and audio
files. Use the following commands to create a new cleaned file
without overwriting the original:
ffmpeg -i input.mp4 -map_metadata -1 -c copy output.mp4 ffmpeg -i input.mp3 -map_metadata -1 -c copy output.mp3
Replace
input.*with your original file andoutput.*with the new file name to preserve the original.
Always verify that metadata was removed from the new file and that the file remains intact before submission.
Automation
Perl scripts in scripts/ can be used to update and rebuild the site.
perl ./scripts/update-guides.pl perl ./scripts/update-feeds.pl articles/my-article.html perl ./scripts/rebuild-feeds.pl
Requires Perl with JSON::PP
Downloading Archives & Using Proxies
A signed archive of the repository is available at
archive/cypherpunk-handbook.tar.gz and is updated every
24 hours. The archive comes with a SHA256 hash and a
signify signature.
Downloading the archive using curl
Default HTTPS download:
curl -O https://handbook.uhden.dev/archive/cypherpunk-handbook.tar.gz curl -O https://handbook.uhden.dev/archive/cypherpunk-handbook.tar.gz.sig curl -O https://handbook.uhden.dev/archive/cypherpunk-handbook.tar.gz.sha256
SOCKS5 proxy via TOR [1]:
curl --socks5-hostname 127.0.0.1:9050 -O http://5u6pytvslmtzmlheqsno2wt3vpyd7nggxhdgn533spyy2euaqwvpfbid.onion/archive/cypherpunk-handbook.tar.gz curl --socks5-hostname 127.0.0.1:9050 -O http://5u6pytvslmtzmlheqsno2wt3vpyd7nggxhdgn533spyy2euaqwvpfbid.onion/archive/cypherpunk-handbook.tar.gz.sig curl --socks5-hostname 127.0.0.1:9050 -O http://5u6pytvslmtzmlheqsno2wt3vpyd7nggxhdgn533spyy2euaqwvpfbid.onion/archive/cypherpunk-handbook.tar.gz.sha256
HTTP proxy via I2P [2]:
curl -p -x 127.0.0.1:4444 -O http://poy7mv4bgjnjgxq73hck72x5lnspvev4pnsiea2gdyegt7xpeg3q.b32.i2p/archive/cypherpunk-handbook.tar.gz curl -p -x 127.0.0.1:4444 -O http://poy7mv4bgjnjgxq73hck72x5lnspvev4pnsiea2gdyegt7xpeg3q.b32.i2p/archive/cypherpunk-handbook.tar.gz.sig curl -p -x 127.0.0.1:4444 -O http://poy7mv4bgjnjgxq73hck72x5lnspvev4pnsiea2gdyegt7xpeg3q.b32.i2p/archive/cypherpunk-handbook.tar.gz.sha256
Verifying the archive
Verify checksum and signature before extracting the archive.
Linux
Verify using the SHA256 file.
sha256sum -c cypherpunk-handbook.tar.gz.sha256
BSD
Compute SHA256 and compare it manually with the value in the SHA256 file.
sha256 cypherpunk-handbook.tar.gz cat cypherpunk-handbook.tar.gz.sha256
Verify the signed archive:
signify -V -p cypherpunk-handbook.pub -x cypherpunk-handbook.tar.gz.sig -m cypherpunk-handbook.tar.gz.sha256
Extract the archive:
tar -xzf cypherpunk-handbook.tar.gz
Using Git with a proxy
Default (no proxy):
git clone https://github.com/daviduhden/cypherpunk-handbook.git
SOCKS5 proxy via TOR (global configuration)
git config --global http.proxy socks5://127.0.0.1:9050
Then clone normally:
git clone https://github.com/daviduhden/cypherpunk-handbook.git
HTTP proxy via I2P (global configuration)
git config --global http.proxy http://127.0.0.1:4444
Then clone normally:
git clone https://github.com/daviduhden/cypherpunk-handbook.git
SOCKS5 proxy via TOR (temporary for this command only)
git -c http.proxy=socks5://127.0.0.1:9050 clone https://github.com/daviduhden/cypherpunk-handbook.git
HTTP proxy via I2P (temporary for this command only)
git -c http.proxy=http://127.0.0.1:4444 clone https://github.com/daviduhden/cypherpunk-handbook.git
Global configuration (~/.gitconfig) affects all
subsequent git pull, git push, and other
commands. Temporary -c settings apply only to the specific
command.
Tools Used
This guide and the workflows described here use the following common tools and utilities:
- GitHub CLI
(
gh) - For forking repositories and creating PRs from the command line. - Git - For version control and patch generation.
- Got - For version control and patch generation on OpenBSD.
- curl - For file downloads and using HTTP and SOCKS5 proxies.
- GNU tar /
BSD tar - For
extracting
.tar.gzarchives. - sha256sum / sha256 - For SHA256 checksum verification (Linux / BSD).
- signify - For signature verification (OpenBSD utility) [3].
- Perl with
JSON::PP- For automation scripts included inscripts/. - Text editor - Vi, Vim, Kakoune, Helix, Geany, Kate, VSCodium, etc. - For editing HTML, CSS and JS/JSON files.
- Mat2 - For metadata removal from images and documents.
- ExifTool - For metadata removal from image files.
- FFmpeg - For metadata removal from video and audio files.