{"id":37360647,"url":"https://github.com/wesley-dean/docme","last_synced_at":"2026-04-02T19:20:39.575Z","repository":{"id":332226025,"uuid":"1133124451","full_name":"wesley-dean/docme","owner":"wesley-dean","description":"Tool to document and comment source code via LLM","archived":false,"fork":false,"pushed_at":"2026-03-31T01:43:12.000Z","size":112,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-31T04:53:22.383Z","etag":null,"topics":["comments","documentation"],"latest_commit_sha":null,"homepage":"https://github.com/wesley-dean/docme","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"cc0-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wesley-dean.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":"SECURITY.md","support":"SUPPORT.md","governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["wesley-dean"]}},"created_at":"2026-01-12T23:13:20.000Z","updated_at":"2026-03-31T01:42:49.000Z","dependencies_parsed_at":"2026-03-31T04:02:11.559Z","dependency_job_id":null,"html_url":"https://github.com/wesley-dean/docme","commit_stats":null,"previous_names":["wesley-dean/docme"],"tags_count":18,"template":false,"template_full_name":"wesley-dean/template","purl":"pkg:github/wesley-dean/docme","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wesley-dean%2Fdocme","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wesley-dean%2Fdocme/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wesley-dean%2Fdocme/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wesley-dean%2Fdocme/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wesley-dean","download_url":"https://codeload.github.com/wesley-dean/docme/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wesley-dean%2Fdocme/sbom","scorecard":{"id":1241359,"data":{"date":"2026-01-13T03:55:51Z","repo":{"name":"github.com/wesley-dean/docme","commit":"e9a139e8f53242e9966388c20a2f9e284c8b6724"},"scorecard":{"version":"v5.3.0","commit":"c22063e786c11f9dd714d777a687ff7c4599b600"},"score":7.3,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/9 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#dangerous-workflow"}},{"name":"Dependency-Update-Tool","score":10,"reason":"update tool detected","details":["Info: detected update tool: Dependabot: .github/dependabot.yml:1"],"documentation":{"short":"Determines if the project uses a dependency update tool.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#dependency-update-tool"}},{"name":"Maintained","score":0,"reason":"project was created within the last 90 days. Please review its contents carefully","details":["Warn: Repository was created within the last 90 days."],"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#maintained"}},{"name":"Security-Policy","score":10,"reason":"security policy file detected","details":["Info: security policy file detected: SECURITY.md:1","Info: Found linked content: SECURITY.md:1","Info: Found disclosure, vulnerability, and/or timelines in security policy: SECURITY.md:1","Info: Found text in security policy: SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#security-policy"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":10,"reason":"all dependencies are pinned","details":["Info:  11 out of  11 GitHub-owned GitHubAction dependencies pinned","Info:  11 out of  11 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#pinned-dependencies"}},{"name":"Token-Permissions","score":10,"reason":"GitHub workflow tokens follow principle of least privilege","details":["Info: jobLevel 'packages' permission set to 'read': .github/workflows/codeql.yml:25","Info: jobLevel 'actions' permission set to 'read': .github/workflows/codeql.yml:28","Info: jobLevel 'contents' permission set to 'read': .github/workflows/codeql.yml:29","Warn: jobLevel 'contents' permission set to 'write': .github/workflows/create_issue_branches.yml:27","Warn: jobLevel 'contents' permission set to 'write': .github/workflows/dependabot_automerge.yml:12","Warn: jobLevel 'contents' permission set to 'write': .github/workflows/megalinter.yml:64","Warn: jobLevel 'checks' permission set to 'write': .github/workflows/megalinter.yml:68","Warn: jobLevel 'contents' permission set to 'write': .github/workflows/semver.yml:21","Info: topLevel permissions set to 'read-all': .github/workflows/codeql.yml:14","Info: topLevel 'contents' permission set to 'read': .github/workflows/create_issue_branches.yml:17","Info: topLevel 'contents' permission set to 'read': .github/workflows/dependabot_automerge.yml:7","Info: topLevel 'contents' permission set to 'read': .github/workflows/megalinter.yml:23","Info: topLevel permissions set to 'read-all': .github/workflows/scorecard.yml:22","Info: topLevel 'contents' permission set to 'read': .github/workflows/semver.yml:11","Info: topLevel 'contents' permission set to 'read': .github/workflows/stale_issues.yml:10"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Creative Commons Zero v1.0 Universal: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#signed-releases"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#fuzzing"}},{"name":"SAST","score":10,"reason":"SAST tool is run on all commits","details":["Info: SAST configuration detected: CodeQL","Info: all commits (2) are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#sast"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#branch-protection"}},{"name":"Contributors","score":-1,"reason":"internal error: Client.Repositories.ListContributors: error during contributorsHandler.setup: error during ParseFile: line 1: invalid owner format 'wesley-dean' at position 3","details":null,"documentation":{"short":"Determines if the project has a set of contributors from multiple organizations (e.g., companies).","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#contributors"}},{"name":"CI-Tests","score":10,"reason":"1 out of 1 merged PRs checked by a CI test -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project runs tests before pull requests are merged.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#ci-tests"}}]},"last_synced_at":"2026-01-13T05:15:38.920Z","repository_id":332226025,"created_at":"2026-01-13T05:15:38.932Z","updated_at":"2026-01-13T05:15:38.932Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31314375,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-02T12:59:32.332Z","status":"ssl_error","status_checked_at":"2026-04-02T12:54:48.875Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["comments","documentation"],"created_at":"2026-01-16T04:45:41.772Z","updated_at":"2026-04-02T19:20:39.554Z","avatar_url":"https://github.com/wesley-dean.png","language":"Shell","funding_links":["https://github.com/sponsors/wesley-dean"],"categories":[],"sub_categories":[],"readme":"# docme — Documentation-First, Non-Destructive Code Commenting with LLMs\n\n## Overview\n\nThis project exists to solve a very specific, deliberately constrained problem:\n\n**How do we use Large Language Models (LLMs) to improve source code documentation\nwithout risking silent, destructive changes to executable code?**\n\nThe tools in this repository enable *documentation-only* updates to existing\nsource files, driven by a strict documentation standard (ADR-026) and reinforced\nby tooling that assumes LLM output is *untrusted* until verified.\n\nThis project is intentionally conservative.\n\nIt prioritizes:\n- human comprehension under stress,\n- non-destructive automation,\n- and explicit guardrails around AI-assisted changes.\n\nThe result is a workflow that favors *fewer incidents* over cleverness.\n\n---\n\n## Why This Project Exists\n\nModern LLMs are extremely capable, but they exhibit well-documented failure\nmodes when asked to “just add comments”:\n\n- rewriting entire files,\n- altering control flow,\n- replacing logic with stubs,\n- inventing rationale,\n- or silently dropping edge cases.\n\nADR-026 (Documentation-First Source Code Commenting Standard) exists to counter\nthese tendencies by treating documentation as a **first-class architectural\nartifact**, not decoration.\n\nThis repository provides:\n- a repeatable prompt construction mechanism,\n- strict output sanitization,\n- and safe, auditable application of changes,\n\nso that documentation can be improved *without modifying behavior*.\n\nIf a change cannot be proven safe, it is rejected.\n\n---\n\n## Quick Start\n\n### Prerequisites\n\nYou will need:\n\n- `sh` (POSIX-compliant shell)\n- `jq`\n- `awk`, `sed`, `grep` (BSD or GNU)\n- [`llm`](https://pypi.org/project/llm/) CLI\n- Either:\n  - `jinja2-cli`, **or**\n  - Docker (for the Jinja2 CLI fallback image)\n\n### Basic Usage\n\n```bash\ndocme path/to/source_file.sh\n```\n\nThis will:\n\n1. Render a documentation-only prompt using `comment_code_prompt.sh`\n2. Send the prompt to an LLM (default: `gpt-5.2`)\n3. Sanitize the output to remove Markdown fencing\n4. Overwrite the original file **after creating a backup**\n\nA backup is written as:\n\n```text\npath/to/source_file.sh~\n```\n\n### Using STDIN / STDOUT\n\n```bash\ncat source.py | docme \u003e source.documented.py\n```\n\nNo backups are created when operating as a stream.\n\n---\n\n## Selecting a Model\n\nBy default, `docme` uses:\n\n```text\ngpt-5.2\n```\n\nTo use a different model, set the `model` environment variable:\n\n```bash\nmodel=gpt-4o-mini docme script.sh\nmodel=qwen2.5-coder:7b docme script.sh\n```\n\nThis design allows experimentation while keeping the default path aligned with\nthe most reliable behavior observed during testing.\n\n---\n\n## Tools in This Repository\n\n### `docme`\n\n**Primary user-facing command.**\n\n`docme` orchestrates the full workflow:\n- prompt generation,\n- LLM invocation,\n- output sanitization,\n- and safe file replacement.\n\n#### Behavior\n\n- Accepts 0 or more filenames\n- Iterates over files when multiple are provided\n- Creates `~` backups before overwriting\n- Uses STDIN/STDOUT when no filenames are given\n\n#### Environment Variables\n\n- `model` — LLM model name (default: `gpt-5.2`)\n\n---\n\n### `comment_code_prompt.sh`\n\nGenerates a **single, deterministic prompt** on stdout.\n\nIt:\n- reads an ADR describing the documentation standard,\n- reads source code verbatim,\n- JSON-encodes both safely using `jq`,\n- renders a Jinja2 template.\n\nIt does *not* call an LLM.\n\n#### Usage\n\n```bash\ncomment_code_prompt.sh source_file\ncomment_code_prompt.sh -a custom_adr.md source_file\ncomment_code_prompt.sh -t custom_template.j2 source_file\ncomment_code_prompt.sh - source_from_stdin\n```\n\n#### Options\n\n- `-a ADR.md` — path to ADR file\n  Default: `ADR-026-documentation-first-source-code-commenting-standard.md`\n- `-t TEMPLATE.j2` — Jinja2 template path\n- `-h` — help\n\n#### Environment Overrides\n\n- `ADR_PATH`\n- `TEMPLATE_PATH`\n- `JINJA2_CMD`\n- `JINJA2_DOCKER_IMAGE` (default: `wesleydean/jinja2-cli:latest`)\n\n---\n\n### `sanitize_llm_output.sh`\n\nA **strict POSIX filter** that removes a single outer Markdown code fence and\nrejects output that still contains fencing.\n\nIt is intentionally conservative.\n\n#### Sourced Usage\n\n```bash\n. ./sanitize_llm_output.sh\nrender | sanitize_llm_output_helper\n```\n\n#### Executed Usage\n\n```bash\nsanitize_llm_output.sh \u003c llm_output.txt\n```\n\nIf fencing remains after sanitization, the script fails loudly.\n\nThis behavior is by design.\n\n---\n\n## Architecture Decision Record (ADR-026)\n\nADR-026 defines the documentation standard enforced by this project.\n\nIts core principles:\n\n- Documentation is architecture\n- Comments exist for tired, stressed humans\n- Verbosity is a feature, not a flaw\n- Ambiguity must be marked explicitly (`@TODO`)\n- AI-assisted documentation **must not** modify executable code\n\nThis ADR is included in the repository and is intended to be reusable across\nprojects.\n\n---\n\n## Safety and Design Philosophy\n\nThis project deliberately separates concerns:\n\n- Prompt construction is deterministic\n- LLMs propose changes\n- Tooling enforces constraints\n\nLLMs are treated as **suggestion engines**, not authorities.\n\nAll enforcement happens outside the model.\n\nThis design choice is informed by extensive experimentation across:\n- cloud-hosted models,\n- local models via Ollama,\n- and varying hardware constraints.\n\nThe conclusions from those experiments are documented separately to preserve\ninstitutional memory.\n\n## Frequently Anticipated Questions\n\n### Why ADR-026 and not ADR-001\n\nBecause the ADR was copied out of another project where it was, in fact,\nADR-026.\n\n### Why sanitize to remove the Markdown code fences\n\nBecause some of the local LLM tools (e.g., ollama) with certain models proved\nto be \"too helpful\" and not follow all of the instructions, particularly those\nthat relate to how the code is spit out at the end.  The sanitize script looks\nto see if the output starts with a Markdown fence, it removes that line; if\nit ends with the end of a code fence, remove that, too.\n\n### Why all of the POSIX nonsense?\n\nBecause I'm pedantic and I want this to work in a variety of environments,\nincluding when I run it under Linux as well as OpenBSD and FreeBSD, not to\nmention situations where non-current versions of Bash are used.\n\n#### But you use Bash everywhere?\n\nYes.  Yes I do.\n\n### But why so much documentation\n\nBecause, again, pedantic.  More importantly, because I work on a bunch of\nprojects and stuff gets confusing, because I forget stuff, because good\ndocumentation is important by itself, not to mention as a signal of someone\ntaking their craft seriously.\n\n#### Could you just send it to ChatGPT, Copilot, etc. and ask it what's up\n\nYes.  Yes I could.  I would rather the documentation live with the source\ncode and not require external tooling.\n\n### Won't the documentation get out of date\n\nIt may very well become outdated.  Regenerate the documentation.  Dependencies\nbecome outdated, too.\n\n### Could this be used in a CI/CD pipeline\n\nSure, why not.  I suspect that LLM calls may become expensive when large\nnumbers of files are included in PRs and/or changed often.\n\nI would recommend reviewing the changes before merging them into a repo.\n\n### Can I run this locally with something like ollama\n\nYes.  Absolutely.  That said, I've found that smaller models tend to not do\na very good job of following directions, documenting entire files (even when\nvery small), etc..\n\nThe results of my experimenting are found in:\n[llm-assisted-documentation-experiments.md](./llm-assisted-documentation-experiments.md)\n\n---\n\n## License\n\nCreative Commons License 1.0 Universal.\nSee [LICENSE](LICENSE).\n\n---\n\n## Contributing\n\nContributions are welcome.\n\nPlease preserve the conservative, safety-first posture of this project.\nIf a feature increases convenience at the expense of correctness or auditability,\nit is likely out of scope.\n\n---\n\n## Author\n\nWes Dean\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwesley-dean%2Fdocme","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwesley-dean%2Fdocme","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwesley-dean%2Fdocme/lists"}