Skip to main content

Didimlog

English | 한국어

Didimlog is a local-first CLI with an optional loopback web reader. It stores lessons, observations, experiments, and evidence gathered while working with Claude Code in local files, then lets you browse existing books and lessons or retrieve only what is needed for the next task.

It is well suited for the following use cases:

  • Preserve verified lessons by project so you do not solve the same problem twice.
  • Link experiment results and raw artifacts to a Git project for traceability.
  • Load only relevant material instead of placing the entire knowledge base in the AI context.
  • Use a local-first storage model that never overwrites source content.

The project is currently Pre-Alpha. It supports macOS and Linux with Python 3.11–3.14. Windows has not yet been verified.

Requirements

  • macOS or Linux
  • Python 3.11–3.14
  • uv, the recommended installation tool
  • A Git repository when storing project records
  • A Claude configuration directory created by running Claude Code at least once when integrating with Claude Code (default: ~/.claude)

If you do not use Claude Code or have not configured it yet, you can use --skip-claude during initial setup.

Quick Start

This walkthrough installs Didimlog, prepares storage in a Git project, saves the first lesson, and checks the index status.

1. Install

uv tool install didimlog
didim --version

If you use pipx, install it with pipx install didimlog.

2. Review the Change Plan and Set Up

Run these commands from the top-level directory of the target Git project.

cd /path/to/your-project
didim setup --dry-run
didim setup --yes

--dry-run shows the planned changes to personal knowledge, project evidence, and the Claude integration without modifying any files. When the actual setup finishes, the final line prints:

Didimlog 준비를 마쳤습니다.

If you run the same command again, items that are already prepared are shown as 변경 없음.

3. Check Readiness

didim status

If setup completed successfully, you can verify the following status. The project name is the name of the current Git top-level directory.

개인 지식: 최신
현재 프로젝트: <프로젝트 이름>
프로젝트 근거: 최신
Claude 연결: 정상

4. Save Your First Lesson

Lessons accept Markdown source through standard input. The following example includes the execution time in the slug, so repeated runs do not overwrite an existing lesson.

today="$(date +%F)"
slug="didimlog-quick-start-$(date +%Y%m%d-%H%M%S)"
cat > /tmp/didimlog-quick-start.md <<EOF
---
topic: didimlog-quick-start
title: 같은 문제를 다시 풀지 않는다
summary: 검증한 해결 방법을 저장하고 다음 작업에서 다시 찾는다
tags: [didimlog, quick-start]
date: $today
---
## 상황
반복되는 작업에서 이미 검증한 해결 방법이 필요했다.

## 교훈
작업이 끝난 뒤 재사용할 조건과 절차를 교훈으로 저장한다.

## 근거
Didimlog로 교훈을 저장하고 index 상태를 확인했다.
EOF

didim add lesson "$slug" --date "$today" < /tmp/didimlog-quick-start.md
didim index --check

On success, Didimlog prints the lesson path and the current status of both indexes.

lessons/<프로젝트 이름>/didimlog-quick-start-<실행 시각>.md
개인 지식: PERSONAL_INDEX_CURRENT
프로젝트 근거: PROJECT_INDEX_CURRENT

The lesson source now remains in ~/knowledge/lessons/<프로젝트 이름>/. During the next task, Claude Code searches the index first and reads only the relevant source content.

Next Steps

Common Tasks

Browse Books and Lessons in the Local GUI

Start the read-only local web app from any directory:

didim gui --open

didim gui binds only to IPv4 loopback (127.0.0.1) and chooses an available port. Every launch creates a new private browser capability. With --open, stdout contains only the non-secret base URL; the capability is handed to the browser in a URL fragment, moved into same-origin sessionStorage, and removed from the address bar immediately. To request a specific loopback port, use didim gui --port 8765 --open.

Without --open, the terminal prints the private handoff URL once, marked sensitive, so you can open it manually. Do not share, record, or paste that line. If automatic browser opening fails, Didimlog prints a token-free instruction to relaunch without --open; it never prints the failed private URL as a fallback.

The first screen is the Bookshelf. It groups validated canonical books by scope and opens each book through Didimlog's safe in-memory Markdown renderer. Lesson detail uses the same safe Markdown feature set for headings, lists, emphasis, and code while retaining the canonical source as the source of truth. Raw HTML is displayed as document text, and lesson images are shown as non-fetching alternative text.

The lesson filters compare the stored metadata exactly. “Topic included in a book” and “Topic not yet included in a book” explain the internal booked/unbooked states: they mean that the lesson topic was or was not reflected in a book, not that a particular book passage came from that lesson. “Review reference date” is the date recorded in review_by for deciding when to revisit the lesson; the GUI neither generates the date nor infers an overdue state. The health panel reports the personal index, current project index, and Claude connection separately. If the personal index is stale, missing, extra, or has an invalid source, the GUI never labels it current.

Milestone A performs no book, lesson, index, setup, or Claude configuration writes. It has no remote binding, hosted service, account, telemetry, cloud sync, book authoring, or new-lesson form. Static shell assets contain no personal data and remain anonymous; every private API read and write attempt requires the per-launch Bearer capability after loopback Host and Origin checks. The browser receives logical paths and opaque resource IDs rather than absolute filesystem paths, and it cannot submit arbitrary file paths.

GUI book rendering retains the existing 4 MiB source limit and also limits each image to 16 MiB, aggregate raw images to 64 MiB, rendered UTF-8 body HTML to 96 MiB, and the serialized book response to 128 MiB. Rendered lesson body HTML is limited to 24 MiB. Bookshelf discovery accepts at most 10,000 source entries and items, retains at most 8 MiB of metadata without lesson bodies, and incrementally limits its serialized response to 16 MiB. Oversized books, lesson renderings, and libraries fail with redacted BOOK_RENDER_TOO_LARGE, LESSON_RENDER_TOO_LARGE, and GUI_LIBRARY_TOO_LARGE responses without stopping later requests.

Share Project Knowledge with the Team

By default, the project's knowledge/ directory is used only on this computer. To include it in Git, reapply the setup with the following command.

didim setup --yes --project-knowledge shared

shared removes only the Didimlog-managed block from the local Git exclude file. It does not modify .gitignore, global exclude settings, or other user-defined exclusion rules. If the command reports that exclusion rules remain, you must inspect those rules yourself.

To switch back to local-only storage, use:

didim setup --yes --project-knowledge local

Record a Project Observation

An observation is a reusable fact that you have directly verified. Include only body in the JSON body.

today="$(date +%F)"
printf '%s' '{"body":"setup 뒤 status의 네 항목이 모두 정상 또는 최신으로 표시됐다."}' |
  didim add observation \
    --date "$today" \
    --title "초기 설정 상태 확인" \
    --tags "setup,status"

On success, Didimlog assigns an ID and prints a path in the following form.

<git-root>/knowledge/records/observation/OBS-YYYYMMDD-NN.md

Record Experiment Results

An experiment stores the hypothesis, method, result, contradiction signal, and interpretation together. result must be one of success, failure, or inconclusive. Set contradicts to none when there is no contradiction.

today="$(date +%F)"
printf '%s' '{"hypothesis":"index를 다시 만들면 저장 직후 상태를 유지한다.","method":"didim index를 실행한 뒤 didim index --check를 실행했다.","result":"success","contradicts":"none","interpretation":"두 index가 최신이므로 현재 기록 트리와 일치한다."}' |
  didim add experiment \
    --date "$today" \
    --title "index 재생성 확인" \
    --tags "index"

On success, Didimlog prints a path in the following form.

<git-root>/knowledge/records/experiment/EXP-YYYYMMDD-NN.md

Register Evidence

To register a local file as evidence, first create it under knowledge/raw/ and submit its SHA-256 digest. The following example uses a unique filename.

today="$(date +%F)"
artifact="knowledge/raw/setup-status-$(date +%Y%m%d-%H%M%S).txt"
printf 'setup status: current\n' > "$artifact"
digest="$(python3 -c 'import hashlib, pathlib, sys; print(hashlib.sha256(pathlib.Path(sys.argv[1]).read_bytes()).hexdigest())' "$artifact")"
printf '{"artifact":"%s","origin":"didim status output","collection":"captured after setup","artifact_sha256":"%s"}' "$artifact" "$digest" |
  didim add evidence \
    --date "$today" \
    --title "설정 상태 원본" \
    --tags "setup,status"

On success, Didimlog prints a path in the following form.

<git-root>/knowledge/records/evidence/EVD-YYYYMMDD-NN.md

For an artifact included in a Git commit, put the full commit object ID in artifact_git instead of artifact_sha256. For path constraints, Git verification behavior, and the record lifecycle, refer to the installed copy of knowledge/README.md created during setup.

Rebuild the Indexes

Rebuild the indexes for every personal knowledge scope and the current Git project.

didim index

The personal index treats only these Markdown paths as source content. <scope> is a name that groups related personal knowledge:

lessons/<scope>/*.md
docs/<scope>/**/*.md
book/<scope>/*.md

Entries outside these patterns, such as .DS_Store, images, and editor temporary files, are ignored. Each scope directory directly below lessons/, docs/, or book/ may be a single symlink to an external directory.

lessons/my-project -> /path/to/external-lessons

Symlinks for individual Markdown files or nested scope directories are rejected. Indexes and CLI output use logical paths such as lessons/my-scope/... even when the source is external. If a source is invalid, didim --explain-errors index shows the logical path under 무엇: and the cause under 이유:.

To verify that the source content and indexes match without changing files, use:

didim index --check

When both indexes are current, the command returns exit 0 and the following tokens.

개인 지식: PERSONAL_INDEX_CURRENT
프로젝트 근거: PROJECT_INDEX_CURRENT

Diagnose Problems

didim status
didim doctor

status summarizes the version, personal knowledge, current project, project evidence, and Claude integration. doctor shows the impact of each detected problem together with the next command to run.

If you also need error explanations in automation logs, place the global option before the command.

didim --explain-errors index --check

Check for Updates

After a successful interactive command, Didimlog checks PyPI for a newer stable release. A successful check suppresses another request for 24 hours; a failed check may be retried by the next eligible command. When an update is available, Didimlog appends one line to stderr without changing stdout or the exit code.

Didimlog X.Y.Z 업데이트 가능 — uv tool upgrade didimlog

Help, --version, didim hook session-start, didim gui, didim setup --dry-run, failed commands, and non-interactive output do not perform the automatic check.

The request is limited to https://pypi.org/pypi/didimlog/json; it contains no knowledge content, local path, project name, credential, or user identifier. Only the last successful check time and confirmed stable version are cached in $XDG_CACHE_HOME/didimlog/update.json when XDG_CACHE_HOME is absolute, or ~/.cache/didimlog/update.json otherwise. To disable both the request and cache write, set:

export DIDIM_NO_UPDATE_CHECK=1

Command Summary

The following table summarizes commands intended to be run directly by users. See didim <command> --help in the installed version for every available option.

Command Result Main options or input
didim setup Prepare personal and project storage and the Claude integration --dry-run, --yes, --skip-claude, --project-knowledge local|shared, --config-dir
didim connect claude Add the Claude Code integration --yes, --config-dir
didim disconnect claude Remove the Claude integration managed by Didimlog --config-dir
didim add lesson <slug> Save a personal lesson as create-only Markdown stdin, --date, --project, --global
didim add observation Save a project observation record JSON stdin, common record options
didim add experiment Save a project experiment record JSON stdin, common record options
didim add evidence Link project evidence with its artifact JSON stdin, common record options
didim gui Start the loopback-only, read-only Bookshelf and lesson reader --open, --port
didim index Rebuild personal and project indexes --check
didim status Summarize the current status --config-dir
didim doctor Diagnose problems and remediation steps --config-dir

The global options are --version and --explain-errors. didim hook session-start is an internal command used by the Claude Code integration.

Common Record Options

observation, experiment, and evidence share the following options.

Option Meaning
--date YYYY-MM-DD Creation date. Required for non-interactive execution using standard input
--title Record title. Required
--scope project or task:<name>. Default: project
--tags Comma-separated tags
--sources Comma-separated EVD or EXP IDs

The exact fields accepted through JSON stdin are listed below. Non-string values and unknown fields are rejected.

Type Required fields
observation body
experiment hypothesis, method, result, contradicts, interpretation
evidence artifact, origin, collection, and exactly one of artifact_sha256 or artifact_git

CLI standard input is limited to 64 KiB. Generated project records are limited to 12,000 UTF-8 bytes and 200 LF characters. For the authoritative format and validation rules, refer to knowledge/README.md and knowledge/schema/record.schema.json in the installed project.

Errors and Exit Codes

The English token on the first error line and the exit code are stable behaviors that can be used in automation. In an interactive terminal or when using --explain-errors, a Korean 도움말: line is appended.

Exit code Meaning
2 Command usage or input format error
3 Violation of a knowledge integrity policy involving a path, artifact, index, or similar input
5 Content resembling a secret was detected in a lesson
7 The Git repository or object cannot be verified

LESSON_SECRET rejects the lesson without printing the detected value. KNOWLEDGE_INDEX_STALE or PROJECT_INDEX_STALE means that the source content was saved successfully but the index update failed. Recover by running didim index.

Storage Model and Safety Rules

Personal knowledge is stored in named scopes under the home directory.

~/knowledge/
├── lessons/<scope>/
├── docs/<scope>/
├── book/<scope>/
├── lessons/_global/
├── docs/_global/
├── book/_global/
├── index/<scope>.md
└── index/_global.md
  • scope: A user-selected group of related knowledge, such as personal, network, or career
  • lessons: Verified lessons that should change behavior in future tasks
  • docs: Precise procedures, plans, and research results
  • book: Explanations that connect background information and examples from multiple sources
  • _global: Material that applies unchanged across multiple scopes
  • index: A regenerable list containing only titles, when-to-use guidance, and detailed file paths

A scope does not have to match a Git repository name. Scope names use letters, digits, and single hyphens. If you do not specify one, Didimlog uses the current Git top-level directory name. Save a lesson to an explicit scope with:

didim add lesson <slug> --project <scope>

The --project option name is retained for compatibility; its value can be any valid scope. There is no didim add doc or didim add book command. Create those Markdown files directly under docs/<scope>/ or book/<scope>/, include the metadata required by the index, and rebuild it:

---
title: Document title
find_when: [search term, trigger]
---
didim index

Project knowledge is stored at the top level of the Git repository.

<git-root>/knowledge/
├── POINTER.md
├── README.md
├── records/
├── raw/
├── schema/record.schema.json
├── index/INDEX.md
└── active/harness.md

records/ is the source of truth for project knowledge, and INDEX.md can be regenerated by revalidating every record. The default local configuration adds /knowledge/ to the current local repository's info/exclude without modifying .gitignore. Linked worktrees share this file, so configuration in one worktree also applies to other linked worktrees.

Didimlog enforces the following safety rules:

  • Lesson and record source files are create-only. Existing source files are never overwritten or deleted.
  • Before setup, Didimlog checks the complete change plan. If a path or file changes after approval, it stops writing.
  • Symlinks and parent-path traversal are rejected.
  • If setup fails, Didimlog rolls back only content created by the current run that remains unchanged. Concurrent user changes are not modified.
  • If only the index update fails after creating a record file, Didimlog preserves the source content and provides a recovery command.
  • Evidence backed by Git objects is verified only against the object database of the repository identified when the command starts. Didimlog does not use the current shell's Git environment variables or external alternates to locate other objects.
  • The local GUI binds only to 127.0.0.1, validates the HTTP host/origin before a constant-time per-launch capability check, accepts only opaque IDs for book and lesson reads, applies finite render/response limits, and exposes no authenticated write methods.

Claude Code Integration

didim setup --yes prepares both storage and the Claude Code integration. To prepare storage only, use:

didim setup --yes --skip-claude

You can also manage the integration separately.

didim connect claude --yes
didim disconnect claude

A newly connected Claude session automatically reads only the short retrieval procedure in KNOWLEDGE_USAGE.md. When the user names a knowledge scope, Claude searches that scope and _global; otherwise it searches the current Git project scope and _global. A missing explicitly named scope is not replaced with the current project. Claude reads up to five relevant source documents and does not load complete indexes or every lesson body into the session-start context.

Uninstallation

First disconnect Claude Code, then uninstall the tool.

didim disconnect claude
uv tool uninstall didimlog

Uninstallation leaves ~/knowledge and the source content under each project's knowledge/ directory intact.

Development and Verification

Install locked dependencies and run the full test suite.

uv sync --locked
uv run --project . python -m unittest discover -s tests -v

Verify the distribution files and public allowlist.

uv build
uv run --project . python -m unittest tests.didimlog_tests.test_release -v

Release

Before using release automation, a repository administrator must apply the following settings manually. Merging the workflow file alone does not create these settings.

  • Set GitHub Actions Workflow permissions to Read and write permissions.
  • Create the release:none, release:patch, release:minor, release:major, and release:ready labels.
  • Configure main to require PRs, CI, and release-state, and require PR branches to include the latest main before they can be merged. Allow only merge commits, and block squash merges, rebases, and direct pushes.
  • Allow GitHub Actions to push preparation and cancellation commits to develop.
  • Create the pypi environment, and do not assign required reviewers if fully automated deployment is desired.
  • Register a PyPI Trusted Publisher with owner zhsks311, repository didimlog, workflow release.yml, and environment pypi.
  • Enable GitHub Release immutability so releases cannot be modified after publication.

A develop → main PR is not released if it has no release label or has release:none. To release it, apply exactly one of the following version labels:

  • release:patch: Prepare a bug-fix release
  • release:minor: Prepare a backward-compatible feature release
  • release:major: Prepare a release with breaking changes

The automation updates pyproject.toml, uv.lock, and CHANGELOG.md, then runs the full test suite and build. When preparation finishes, it applies release:ready, but this label is only an indicator of the current state. The actual required merge condition is that the Git history of the current PR commit contains a valid preparation record and the release-state check passes for that exact commit.

If a commit is added to the PR after preparation, the automation cancels the previous preparation and prepares again from the new commit. If main advances in the meantime, it cancels the previous preparation and waits until the PR branch includes the latest main. It then prepares the release again automatically.

Only a merge commit on main with two parents is recognized as a release target. Squash merges, rebases, and direct pushes are not released and cause the release workflow to finish with an error.

If deployment fails, select Run workflow in GitHub Actions under Publish prepared main release, then enter the failed merge commit SHA. The automation verifies that the commit is still a valid release contained in the current main, and resumes publication of the same version only when it does not conflict with existing tags or files.

A hotfix/* → main PR supports only release:patch. After a successful patch release, the automation merges main directly into develop. If protection rules or conflicts prevent the direct update, it creates or updates a main → develop synchronization PR.

See CONTRIBUTING.md for contribution instructions, SECURITY.md for reporting security issues, and CHANGELOG.md for user-visible changes.

License

Didimlog is distributed under the MIT License. Licenses for Python-Markdown and the vendored Mermaid are listed in THIRD_PARTY_NOTICES.md.

Release files for didimlog 0.1.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 didimlog 0.1.1
File Size Uploaded
didimlog-0.1.1.tar.gz 1.1 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for didimlog 0.1.1
File Interpreter ABI Platform
didimlog-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 2.2 MB

Release files / didimlog-0.1.1.tar.gz

Download URL didimlog-0.1.1.tar.gz
Size 1.1 MB
Tags Source
SHA-256 checksum
How to use checksums
f3d934a22dc2bb0c150fa498e1bd59e34619f6c357f3d1eef748fec8fd2c07f1
BLAKE2b-256 checksum
How to use checksums
25032d7ddccabf5298b74c3dfedd2d6eb6d759045138dca4856d382397583d83
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 4, 2026.

Transparency log

Release files / didimlog-0.1.1-py3-none-any.whl

Download URL didimlog-0.1.1-py3-none-any.whl
Size 1.1 MB
Tags Python 3
SHA-256 checksum
How to use checksums
778ba0c6063e96df1cfda4efced7bbc98f6307ac808fa7786c7f47898d04eaca
BLAKE2b-256 checksum
How to use checksums
4677e175e9c96bf7e1b1a3d1d3c5fbe54fc19bc15f73408be061787bacec2135
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 4, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

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