Skip to main content

Obsidian Code Atlas

Mirror your GitHub code into an Obsidian vault.

[!NOTE] Who is this for?

People who write code, host it on GitHub, and use Obsidian as a work, lab, or personal notebook for its "Second Brain" features.

What problem does this solve?

As a scientist, I love having all my laboratory notes and ideas easily searchable within an Obisidian vault. But, when I write code, I often find myself clunkily searching on GitHub in the browser and/or through my local computer's files for previously written scripts.

Why obsidian-code-atlas?

It brings code from all my repos into easily searchable and visually appealling Base and Note objects inside an existing Obsidian vault. It updates each morning, so scripts are always fresh.

This tool generates four things from your gh-authenticated account:

  1. Activity.md — recent commits across every repo you touch.
  2. Repos/ + Repos.base — one note per repo, browsable as an Obsidian Base database.
  3. Scripts/ + Scripts.base — every source file you’ve written, as searchable notes.
  4. Issues/ + Issues.base — every open issue in those repos (labels, assignees, milestone, comment count), one note per issue named by number (e.g. Issues/owner-repo/42.md).

The generated Repos/, Scripts/, Issues/, Activity.md, GitHub Dashboard.md, and *.base files are fully managed by the tool — don’t hand-edit them.

Requirements

  • GitHub CLI (gh) installed and authenticated (gh auth status).
  • Python 3.9 or newer.

Installation

Install from PyPI with pip:

python3 -m pip install obsidian-code-atlas

For an isolated command-line installation, use pipx:

pipx install obsidian-code-atlas

Upgrade an existing installation:

python3 -m pip install --upgrade obsidian-code-atlas
# or, for pipx:
pipx upgrade obsidian-code-atlas
Installing from source

Install the latest development version directly from the Git URL:

python3 -m pip install git+https://github.com/tiszalab/obsidian-code-atlas.git

Or from a local clone:

git clone https://github.com/tiszalab/obsidian-code-atlas.git
cd obsidian-code-atlas
python3 -m pip install .

The application code lives in your Python environment; generated Obsidian notes live in the vault you choose below.

Initializing a vault

The init command prepares an existing Obsidian vault to receive generated notes and optionally installs a daily scheduler.

obsidian-code-atlas init "/path/to/My Vault" --output "Code Atlas" --scheduler launchd

Arguments:

  • VAULT_PATH — root of an existing Obsidian vault (the directory containing .obsidian/).
  • --output — name of the generated atlas folder inside the vault (default: Code Atlas).
  • --scheduler — launchd (macOS), cron (Unix), or none (default).
  • --gitignore — add the generated output folder to the parent Git repository’s .gitignore (default).
  • --no-gitignore (alias --track-generated) — opt out of the default .gitignore entry.
  • --force — initialize even if .obsidian/ is missing.
  • --no-refresh — skip the first refresh all.
  • --config — path to a custom obsidian-code-atlas.json configuration file.

init is idempotent: rerunning it updates the scheduler and Git ignore entry without duplicating them or deleting existing generated notes.

Git integration

If your vault is inside a Git worktree, init finds the actual repository root (even when the vault is nested below it) and adds an anchored ignore block:

# BEGIN obsidian-code-atlas: <stable-id>
/path/relative/to/repo/My Vault/Code Atlas/
# END obsidian-code-atlas: <stable-id>

This leaves unrelated .gitignore content untouched. Because the whole output directory is ignored, generated notes and output-local configuration will not be tracked by the parent repository. Use --no-gitignore (or its alias --track-generated) to skip this step. When the output directory is the worktree root there is no rule that could ignore it, so init and doctor say so instead of writing one.

Diagnosing the setup

obsidian-code-atlas doctor --output "/path/to/My Vault/Code Atlas"

doctor checks:

  • package and Python version;
  • whether the output directory exists and is writable;
  • whether the output is inside an Obsidian vault;
  • gh availability and gh auth status;
  • effective configuration file and JSON validity;
  • installed scheduler status;
  • parent Git worktree and whether the output is ignored.

It exits with status 1 if a condition prevents refresh from working. Warnings that do not block refresh keep a zero status. doctor never prints tokens or credentials.

Refreshing content

Every package invocation needs an output directory. This prevents generated files from silently going into the current working directory or package installation:

obsidian-code-atlas refresh all --output "/path/to/My Vault/Code Atlas"
obsidian-code-atlas refresh activity --output "/path/to/My Vault/Code Atlas"
obsidian-code-atlas refresh repos --output "/path/to/My Vault/Code Atlas"
obsidian-code-atlas refresh scripts --output "/path/to/My Vault/Code Atlas"
obsidian-code-atlas refresh issues --output "/path/to/My Vault/Code Atlas"

The section defaults to all, so obsidian-code-atlas refresh --output PATH is also valid. Paths containing spaces are supported. OBSIDIAN_CODE_ATLAS_OUTPUT may supply the output path, but an explicit --output takes precedence. The command resolves the path to an absolute path and creates it when the refresh starts.

The same interface is available through Python:

python3 -m obsidian_code_atlas --version
python3 -m obsidian_code_atlas refresh all --output "/path/to/My Vault/Code Atlas"

Scheduling

Installed-package users can manage a daily 08:00 refresh without depending on repository scripts:

obsidian-code-atlas scheduler install --launchd --output "/path/to/My Vault/Code Atlas"  # macOS
obsidian-code-atlas scheduler install --cron --output "/path/to/My Vault/Code Atlas"     # Unix cron
obsidian-code-atlas scheduler status --output "/path/to/My Vault/Code Atlas"
obsidian-code-atlas scheduler uninstall --output "/path/to/My Vault/Code Atlas"

Pass --config PATH to scheduler install to preserve an explicit configuration path in the scheduled command. The generated job uses the absolute interpreter running Obsidian Code Atlas, refresh all, and the absolute output path. Different output directories receive different identifiers, so multiple vaults can coexist. --launchd is rejected outside macOS with a recommendation to use cron.

launchd runs both at login and daily at 08:00. Cron runs daily at 08:00. Cron output is appended to refresh.log in the selected output directory; launchd writes launchd.out.log and launchd.err.log there. The install command creates the output directory before scheduling the first run.

scheduler status prints the expected identifier, installed scheduler types, schedule, and command. It returns status 1 when neither matching job is installed and 0 when at least one is found. Uninstall removes only jobs belonging to the selected output directory.

Configuring language support

Create obsidian-code-atlas.json in the output directory using this structure (repository checkouts also include obsidian-code-atlas.json.example):

{
  "excluded_repos": [
    "owner/private-repo",
    "organization/archived-repo"
  ],
  "script_extensions": {
    ".ex": {"label": "Elixir", "fence": "elixir"},
    ".exs": {"label": "Elixir Script", "fence": "elixir"},
    ".yml": null
  }
}

excluded_repos contains case-insensitive owner/repository names. Excluded repositories are omitted from activity, repository, script, and issue output. A script_extensions value of null removes an extension. A configuration file that cannot be parsed or validated aborts the command with an error instead of falling back to the defaults. Configuration is selected in this exact order:

  1. explicit --config PATH;
  2. OBSIDIAN_CODE_ATLAS_CONFIG;
  3. obsidian-code-atlas.json in the output directory;
  4. built-in defaults.

Extension environment overrides are applied after the selected file:

OBSIDIAN_CODE_ATLAS_EXTENSIONS=".ex:Elixir:elixir,.exs:Elixir:elixir,-.yml" \
  obsidian-code-atlas refresh all --output "/path/to/My Vault/Code Atlas"

The format is .ext:Label:fence; two parts (.ext:Label) and one part (.ext) are also accepted, and a leading - removes an extension.

File layout

|.
├── pyproject.toml
├── src/obsidian_code_atlas/      # installable package
│   ├── __init__.py
│   ├── __main__.py
│   ├── cli.py
│   ├── doctor.py
│   ├── init.py
│   └── scheduler.py
└── obsidian-code-atlas.json.example

Uninstall

Remove the scheduler first, then uninstall the package. Generated notes are retained unless you delete the output folder manually.

obsidian-code-atlas scheduler uninstall --output "/path/to/My Vault/Code Atlas"
python3 -m pip uninstall obsidian-code-atlas
# or, for pipx:
pipx uninstall obsidian-code-atlas

License

MIT © Michael Tisza

Metadata

Release files for obsidian-code-atlas 0.5.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for obsidian-code-atlas 0.5.1
File Size Uploaded
obsidian_code_atlas-0.5.1.tar.gz 37.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for obsidian-code-atlas 0.5.1
File Interpreter ABI Platform
obsidian_code_atlas-0.5.1-py3-none-any.whl Python 3 none any Details

Total release size: 64.0 kB

Release files / obsidian_code_atlas-0.5.1.tar.gz

Download URL obsidian_code_atlas-0.5.1.tar.gz
Size 37.6 kB
Tags Source
SHA-256 checksum
How to use checksums
09ec12fb49d09742f2b4e43dcd2cbde367db56a45aae5abb32d751a1b79e9ab1
BLAKE2b-256 checksum
How to use checksums
ad645f85a458802cf3569d38b7c5c2ca11ceec4fdc9fcd9a2760f61849842fc3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 8, 2026.

Transparency log

Release files / obsidian_code_atlas-0.5.1-py3-none-any.whl

Download URL obsidian_code_atlas-0.5.1-py3-none-any.whl
Size 26.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
72b8ac9235c9df73b9e6d0c307e8cd9d7ae08c2da1b2c1f9123a6fb6e10f03f4
BLAKE2b-256 checksum
How to use checksums
a51840e771b3620d5586158a8e889e724a84e3a45ae440f3d9e9509875e1565a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 8, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.5.1 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page