Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ Bare `openwiki --init` and `openwiki --update` run in code mode. Use
`openwiki personal --init` or `openwiki personal --update` for the local
personal brain wiki.

Then to ensure your documentation stays up-to-date, add the CI workflow for your Git provider to automatically open a PR or merge request with documentation updates:
During interactive code-mode setup, OpenWiki asks whether to create a GitHub
Actions workflow, a GitLab CI/CD pipeline, or no CI file. The generated workflow
automatically opens a pull request or merge request with documentation updates.
You can also add one of the examples manually:

- GitHub Actions: copy [openwiki-update.yml](./examples/openwiki-update.yml) into `.github/workflows/openwiki-update.yml`.
- GitLab CI: copy [openwiki-update.gitlab-ci.yml](./examples/openwiki-update.gitlab-ci.yml) into `.gitlab-ci.yml` or include it from your existing GitLab pipeline.
Expand Down Expand Up @@ -171,7 +174,7 @@ Bare `openwiki` runs in code mode for the current repository. It creates initial

Bare `openwiki --init` and `openwiki --update` default to code mode and operate on repository documentation. Use the `personal` positional mode or `--mode personal` to initialize or update the local personal brain wiki.

On each `code` run, `openwiki` maintains both an `AGENTS.md` and a `CLAUDE.md` at the repository root, adding prompting that instructs your coding agent to reference the wiki when searching for context. Each file is created if it does not already exist. If a file is present, OpenWiki only rewrites its own `<!-- OPENWIKI:START -->…<!-- OPENWIKI:END -->` block and leaves the rest of your content untouched (appending the block the first time). The scheduled GitHub Actions workflow includes these files, along with the workflow itself, in the documentation pull request.
On each `code` run, `openwiki` maintains both an `AGENTS.md` and a `CLAUDE.md` at the repository root, adding prompting that instructs your coding agent to reference the wiki when searching for context. Each file is created if it does not already exist. If a file is present, OpenWiki only rewrites its own `<!-- OPENWIKI:START -->…<!-- OPENWIKI:END -->` block and leaves the rest of your content untouched (appending the block the first time). If you opt into GitHub Actions or GitLab CI/CD during setup, the generated CI file includes these agent files in its documentation update.

Repository-specific wiki instructions are stored separately in
`openwiki/INSTRUCTIONS.md`. This file is a shared, user-authored brief for the
Expand Down
6 changes: 3 additions & 3 deletions examples/openwiki-update.gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@ openwiki_update:
- if: '$CI_PIPELINE_SOURCE == "web"'
before_script:
- apt-get update && apt-get install -y git curl
- npm install --global openwiki
- npm install --global openwiki@0.2.2
- git config user.name "${GITLAB_USER_NAME:-OpenWiki Bot}"
- git config user.email "${GITLAB_USER_EMAIL:-openwiki@example.com}"
script:
- openwiki code --update --print
- |
if git diff --quiet -- openwiki AGENTS.md CLAUDE.md .github/workflows/openwiki-update.yml; then
if git diff --quiet -- openwiki AGENTS.md CLAUDE.md .gitlab-ci.yml; then
echo "OpenWiki is already up to date."
exit 0
fi
- export OPENWIKI_BRANCH="openwiki/update-${CI_PIPELINE_ID}"
- git checkout -b "$OPENWIKI_BRANCH"
- git add openwiki AGENTS.md CLAUDE.md .github/workflows/openwiki-update.yml
- git add openwiki AGENTS.md CLAUDE.md .gitlab-ci.yml
- git commit -m "docs: update OpenWiki"
- git push "https://oauth2:${OPENWIKI_GITLAB_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git" "$OPENWIKI_BRANCH"
- |
Expand Down
6 changes: 3 additions & 3 deletions examples/openwiki-update.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,17 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v4
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: true

- name: Set up Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: "22"

- name: Install OpenWiki
run: npm install --global openwiki
run: npm install --global openwiki@0.2.2

- name: Run OpenWiki
# --update also handles the first run for code docs when env vars are set.
Expand Down
95 changes: 85 additions & 10 deletions src/code-mode.ts
Original file line number Diff line number Diff line change
@@ -1,47 +1,82 @@
import { mkdir, readFile, writeFile } from "node:fs/promises";
import path from "node:path";
import { OPENWIKI_VERSION } from "./constants.js";
import { isFileNotFoundError } from "./fs-errors.js";

const OPENWIKI_AGENTS_SNIPPET_START = "<!-- OPENWIKI:START -->";
const OPENWIKI_AGENTS_SNIPPET_END = "<!-- OPENWIKI:END -->";
const DEFAULT_CODE_MODE_CRON = "0 8 * * *";

export type CodeModeAutomation = "github" | "gitlab" | "none";

// Root agent-instruction files OpenWiki keeps pointed at the generated wiki.
// Each is created when missing and refreshed in place when already present.
const CODE_MODE_AGENT_FILES = ["AGENTS.md", "CLAUDE.md"];

export async function ensureCodeModeRepoSetup(
cwd: string,
automation: CodeModeAutomation = "none",
cronExpression = DEFAULT_CODE_MODE_CRON,
): Promise<void> {
await writeCodeModeWorkflow(cwd, cronExpression);
if (automation === "github") {
await writeGitHubActionsWorkflow(cwd, cronExpression);
} else if (automation === "gitlab") {
await writeGitLabCiWorkflow(cwd);
}

await writeCodeModeAgentSnippets(cwd);
}

async function writeCodeModeWorkflow(
async function writeGitHubActionsWorkflow(
cwd: string,
cronExpression: string,
): Promise<void> {
const workflowPath = path.join(
const workflowPath = resolveRepoPath(
cwd,
".github",
"workflows",
"openwiki-update.yml",
);
await mkdir(path.dirname(workflowPath), { recursive: true });
await writeFile(workflowPath, createCodeModeWorkflow(cronExpression), "utf8");
await writeFile(
workflowPath,
createGitHubActionsWorkflow(cronExpression),
"utf8",
);
}

async function writeGitLabCiWorkflow(cwd: string): Promise<void> {
await writeFile(
resolveRepoPath(cwd, ".gitlab-ci.yml"),
createGitLabCiWorkflow(),
"utf8",
);
}

async function writeCodeModeAgentSnippets(cwd: string): Promise<void> {
const snippet = createCodeModeAgentsSnippet();

await Promise.all(
CODE_MODE_AGENT_FILES.map((fileName) =>
writeCodeModeAgentSnippet(path.join(cwd, fileName), snippet),
writeCodeModeAgentSnippet(resolveRepoPath(cwd, fileName), snippet),
),
);
}

function resolveRepoPath(cwd: string, ...segments: string[]): string {
const repoRoot = path.resolve(cwd);
const targetPath = path.resolve(repoRoot, ...segments);

if (
targetPath !== repoRoot &&
!targetPath.startsWith(`${repoRoot}${path.sep}`)
) {
throw new Error(`Refusing to write outside repository root: ${targetPath}`);
}

return targetPath;
}

async function writeCodeModeAgentSnippet(
agentsPath: string,
snippet: string,
Expand All @@ -66,7 +101,7 @@ async function writeCodeModeAgentSnippet(
await writeFile(agentsPath, nextContent, "utf8");
}

function createCodeModeWorkflow(cronExpression: string): string {
function createGitHubActionsWorkflow(cronExpression: string): string {
return `name: OpenWiki Update

on:
Expand All @@ -83,15 +118,15 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v4
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Set up Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: "22"

- name: Install OpenWiki
run: npm install --global openwiki
run: npm install --global openwiki@${OPENWIKI_VERSION}

- name: Run OpenWiki
run: openwiki code --update --print
Expand Down Expand Up @@ -121,14 +156,54 @@ jobs:
`;
}

function createGitLabCiWorkflow(): string {
return `openwiki_update:
image: node:22
stage: deploy
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
- if: '$CI_PIPELINE_SOURCE == "web"'
before_script:
- apt-get update && apt-get install -y git curl
- npm install --global openwiki@${OPENWIKI_VERSION}
- git config user.name "\${GITLAB_USER_NAME:-OpenWiki Bot}"
- git config user.email "\${GITLAB_USER_EMAIL:-openwiki@example.com}"
script:
- openwiki code --update --print
- |
if git diff --quiet -- openwiki AGENTS.md CLAUDE.md .gitlab-ci.yml; then
echo "OpenWiki is already up to date."
exit 0
fi
- export OPENWIKI_BRANCH="openwiki/update-\${CI_PIPELINE_ID}"
- git checkout -b "$OPENWIKI_BRANCH"
- git add openwiki AGENTS.md CLAUDE.md .gitlab-ci.yml
- git commit -m "docs: update OpenWiki"
- git push "https://oauth2:\${OPENWIKI_GITLAB_TOKEN}@\${CI_SERVER_HOST}/\${CI_PROJECT_PATH}.git" "$OPENWIKI_BRANCH"
- |
curl --fail --request POST \\
--header "PRIVATE-TOKEN: \${OPENWIKI_GITLAB_TOKEN}" \\
--form "source_branch=\${OPENWIKI_BRANCH}" \\
--form "target_branch=\${CI_DEFAULT_BRANCH}" \\
--form "title=docs: update OpenWiki" \\
--form "description=Automated OpenWiki documentation update generated by the scheduled GitLab pipeline." \\
"\${CI_API_V4_URL}/projects/\${CI_PROJECT_ID}/merge_requests"
variables:
OPENWIKI_PROVIDER: openrouter
OPENWIKI_MODEL_ID: z-ai/glm-5.2
LANGCHAIN_PROJECT: openwiki
LANGCHAIN_TRACING_V2: "true"
`;
}

function createCodeModeAgentsSnippet(): string {
return `${OPENWIKI_AGENTS_SNIPPET_START}

## OpenWiki

This repository uses OpenWiki for recurring code documentation. Start with \`openwiki/quickstart.md\`, then follow its links to architecture, workflows, domain concepts, operations, integrations, testing guidance, and source maps.

The scheduled OpenWiki GitHub Actions workflow refreshes the repository wiki. Do not hand-edit generated OpenWiki pages unless explicitly asked; prefer updating source code/docs and letting OpenWiki regenerate.
The scheduled OpenWiki CI workflow refreshes the repository wiki when configured. Do not hand-edit generated OpenWiki pages unless explicitly asked; prefer updating source code/docs and letting OpenWiki regenerate.

${OPENWIKI_AGENTS_SNIPPET_END}`;
}
2 changes: 1 addition & 1 deletion src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,7 @@ export const helpContent: HelpContent = {
{
label: "openwiki code",
description:
"Run OpenWiki for the current repository, writing docs under repo openwiki/ and using GitHub Actions for recurrence.",
"Run OpenWiki for the current repository, writing docs under repo openwiki/ with optional GitHub Actions or GitLab CI/CD recurrence.",
},
{
label: "openwiki personal",
Expand Down
Loading