Merged
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
10 changes: 5 additions & 5 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -123,13 +123,13 @@ Subscription-based providers that authenticate via OAuth device flow (e.g. `chat
OpenKB ships a bundled web UI, served by the REST API at `/`. Install the API extra and start the server — no configuration needed:

```bash
pip install "openkb[api]"
openkb-api # serves the API + Workbench at http://127.0.0.1:8000/
pip install "openkb[web]"
openkb-web # serves the API + Workbench at http://127.0.0.1:7566/
```

Open `http://127.0.0.1:8000/` for the Workbench. Auth is off by default (local-first); set `OPENKB_API_TOKEN` to require a bearer token before exposing the server. See the [full Web UI guide](examples/rest-api/README.md#knowledge-workbench-web-ui).
Open `http://127.0.0.1:7566/` for the Workbench. Auth is off by default (local-first); set `OPENKB_API_TOKEN` to require a bearer token before exposing the server. See the [full Web UI guide](examples/rest-api/README.md#knowledge-workbench-web-ui).

> Working on the UI itself? Run the Vite dev server with `cd frontend && npm install && npm run dev` (it proxies `/api` to a running `openkb-api`), or `npm run build` to regenerate the bundled `openkb/web/`.
> Working on the UI itself? Run the Vite dev server with `cd frontend && npm install && npm run dev` (it proxies `/api` to a running `openkb-web`), or `npm run build` to regenerate the bundled `openkb/web/`.

# 🧩 How OpenKB Works

Expand DownExpand Up@@ -341,7 +341,7 @@ The skill is read-only. It won't run `openkb add`, `remove`, or `lint --fix` wit

# REST API

OpenKB ships a FastAPI service for HTTP clients. Install with `pip install -e ".[api]"`, then start with `python -m openkb.api`. The interactive API reference is at [`/docs`](http://127.0.0.1:8000/docs) (importable into Postman).
OpenKB ships a FastAPI service for HTTP clients. Install with `pip install -e ".[web]"`, then start with `python -m openkb.api`. The interactive API reference is at [`/docs`](http://127.0.0.1:7566/docs) (importable into Postman).

See the [full REST API reference](examples/rest-api/README.md#rest-api) for endpoints, auth, and SSE streaming.

Expand Down
20 changes: 10 additions & 10 deletions examples/rest-api/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@

This guide covers the OpenKB REST API (FastAPI) and the bundled Knowledge Workbench web UI.

> The interactive API reference is served live at [`/docs`](http://127.0.0.1:8000/docs) (OpenAPI/Swagger) once the server is running — you can import `/openapi.json` directly into Postman.
> The interactive API reference is served live at [`/docs`](http://127.0.0.1:7566/docs) (OpenAPI/Swagger) once the server is running — you can import `/openapi.json` directly into Postman.

## Knowledge Workbench (Web UI)

Expand All@@ -11,20 +11,20 @@ OpenKB ships a bundled web single-page app — the **Knowledge Workbench** — s

```bash
# 1. Install with the API extra (the built UI ships inside the package)
pip install "openkb[api]"
pip install "openkb[web]"

# 2. Start the server — no config needed for local use
openkb-api --host 127.0.0.1 --port 8000 # serves the API + Workbench at http://127.0.0.1:8000/
openkb-web --host 127.0.0.1 --port 7566 # serves the API + Workbench at http://127.0.0.1:7566/
```

Optional environment variables:

- `OPENKB_KB_ROOT` — where REST-created knowledge bases are stored (default `~/.config/openkb/kbs`).
- `OPENKB_API_TOKEN` — set it to require bearer auth (see [Authentication](#authentication-and-common-behavior)); leave unset for open local use.

> **From a source checkout?** The built bundle (`openkb/web/`) is git-ignored, so an editable install (`pip install -e ".[api]"`) has no UI until you build it once: `cd frontend && npm install && npm run build` (outputs to `openkb/web/`). Or run the Vite dev server with `npm run dev` (it proxies `/api` to a running `openkb-api`). Without the bundle, `openkb-api` serves only the REST API under `/api/v1` and `/` returns a 404.
> **From a source checkout?** The built bundle (`openkb/web/`) is git-ignored, so an editable install (`pip install -e ".[web]"`) has no UI until you build it once: `cd frontend && npm install && npm run build` (outputs to `openkb/web/`). Or run the Vite dev server with `npm run dev` (it proxies `/api` to a running `openkb-web`). Without the bundle, `openkb-web` serves only the REST API under `/api/v1` and `/` returns a 404.

Open `http://127.0.0.1:8000/` in your browser. With no `OPENKB_API_TOKEN` set it connects to the local API immediately — no prompt. (If a token is configured, a **Connection** dialog asks for it once and caches it in the browser; you can also open it manually to point the UI at a remote API base.) The Workbench then provides:
Open `http://127.0.0.1:7566/` in your browser. With no `OPENKB_API_TOKEN` set it connects to the local API immediately — no prompt. (If a token is configured, a **Connection** dialog asks for it once and caches it in the browser; you can also open it manually to point the UI at a remote API base.) The Workbench then provides:

- **Overview** — index/concept/summary/report stat cards, clickable concept chips, recent documents, and last-compile/lint activity.
- **Documents** — drag-and-drop multi-file upload with per-file SSE progress, hash table, and delete with confirmation.
Expand All@@ -44,15 +44,15 @@ frontends, or other HTTP clients.
Install the API dependencies if needed:

```bash
pip install -e ".[api]"
pip install -e ".[web]"
```

Start the API server:

```powershell
$env:OPENKB_API_TOKEN="test-token"
$env:OPENKB_KB_ROOT="D:\project\OpenKB\kbs"
.\.venv\Scripts\python.exe -m openkb.api --host 127.0.0.1 --port 8000
.\.venv\Scripts\python.exe -m openkb.api --host 127.0.0.1 --port 7566
```

### Authentication and common behavior
Expand All@@ -61,7 +61,7 @@ Auth is **opt-in**, controlled by the `OPENKB_API_TOKEN` server environment
variable:

- **Unset (default)** — the API is unauthenticated. This is the local-first
default, so `openkb-api` and the Workbench work with no configuration.
default, so `openkb-web` and the Workbench work with no configuration.
- **Set** — every request must carry the token, and the Workbench prompts for
it once (cached in the browser):

Expand All@@ -73,7 +73,7 @@ variable:

> **Exposing the server?** Always set `OPENKB_API_TOKEN` when binding to a
> non-loopback host (e.g. `--host 0.0.0.0`) — otherwise the API, and every KB
> it can reach, is world-open. `openkb-api` prints a warning in that case.
> it can reach, is world-open. `openkb-web` prints a warning in that case.

`OPENKB_KB_ROOT` is optional. It controls where REST-created knowledge bases
are stored. If unset, OpenKB uses `~/.config/openkb/kbs`.
Expand DownExpand Up@@ -419,4 +419,4 @@ no watcher is active for that KB.
stop after this many seconds). Stream events: `start`, the watcher's own events
(e.g. `added`, `updated`, `failed`, `final`), `error`, `done`.

The full OpenAPI schema is at [`/openapi.json`](http://127.0.0.1:8000/openapi.json) — importable into Postman or any OpenAPI-compatible client.
The full OpenAPI schema is at [`/openapi.json`](http://127.0.0.1:7566/openapi.json) — importable into Postman or any OpenAPI-compatible client.
2 changes: 1 addition & 1 deletion frontend/src/App.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -107,7 +107,7 @@ function ConnectionDialog({
<input
value={base}
onChange={(e) => setBase(e.target.value)}
placeholder="http://127.0.0.1:8000"
placeholder="http://127.0.0.1:7566"
className={inputCls}
/>
</div>
Expand Down
7 changes: 5 additions & 2 deletions frontend/src/components/ArtifactPanel.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -222,8 +222,11 @@ export default function ArtifactPanel({
className="absolute left-0 top-0 z-10 h-full w-1.5 -translate-x-1/2 cursor-col-resize hover:bg-accent-brand/30"
/>

{/* header */}
<div className="shrink-0 h-12 flex items-center gap-2 px-3 border-b border-[hsl(var(--glass-border))]">
{/* header — pr-28 reserves the global top-right chrome lane (theme + i18n
pills in App.tsx, absolute right-3 z-40) so the panel's action buttons
(open / download / close) never sit UNDER it. Same reserve convention
as KbList's header row and KbDetail's gear row. */}
<div className="shrink-0 h-12 flex items-center gap-2 pl-3 pr-28 border-b border-[hsl(var(--glass-border))]">
<HeaderIcon className="w-4 h-4 text-accent-brand shrink-0" />
<span className="min-w-0 truncate text-[13px] font-semibold text-foreground">
{artifactLabel(active, t)}
Expand Down
4 changes: 2 additions & 2 deletions frontend/vite.config.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ import path from "path"
import react from "@vitejs/plugin-react"
import { defineConfig } from "vite"

// Dev server proxies /api to the OpenKB REST API on :8000; production
// Dev server proxies /api to the OpenKB REST API on :7566; production
// serves the built bundle from the same origin via FastAPI StaticFiles.
// outDir MUST stay ../openkb/web — the wheel packages it from there
// (see pyproject.toml [tool.hatch.build] artifacts).
Expand All@@ -22,7 +22,7 @@ export default defineConfig({
port: 5173,
proxy: {
"/api": {
target: "http://127.0.0.1:8000",
target: "http://127.0.0.1:7566",
changeOrigin: true,
},
},
Expand Down
2 changes: 1 addition & 1 deletion openkb/api.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -776,7 +776,7 @@ async def api_not_found(path: str) -> Any:
def main() -> None:
parser = argparse.ArgumentParser(description="Run the OpenKB REST API.")
parser.add_argument("--host", default="127.0.0.1")
parser.add_argument("--port", type=int, default=8000)
parser.add_argument("--port", type=int, default=7566)
parser.add_argument("--reload", action="store_true")
args = parser.parse_args()

Expand Down
4 changes: 2 additions & 2 deletions openkb/api_helpers.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -69,8 +69,8 @@ def _configure_cors(app: FastAPI) -> None:
origins = [o.strip() for o in raw.split(",") if o.strip()] or [
"http://localhost:5173",
"http://127.0.0.1:5173",
"http://localhost:8000",
"http://127.0.0.1:8000",
"http://localhost:7566",
"http://127.0.0.1:7566",
]
# A wildcard origin with credentials is insecure: any site can issue
# credentialed cross-origin requests. Reject this combination by forcing
Expand Down
8 changes: 7 additions & 1 deletion pyproject.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -59,6 +59,8 @@ Issues = "https://github.com/VectifyAI/OpenKB/issues"

[project.scripts]
openkb = "openkb.cli:cli"
openkb-web = "openkb.api:main"
# Backwards-compatible alias for the historical name; same entry point.
openkb-api = "openkb.api:main"

[tool.pytest.ini_options]
Expand All@@ -73,7 +75,11 @@ dev = [
"mypy==1.15.0",
"types-PyYAML==6.0.12.20260518",
]
api = ["fastapi", "uvicorn", "python-multipart"]
# The Knowledge Workbench Web UI is served by this FastAPI server. `web` is the
# canonical extra; `api` is a backwards-compatible alias so an existing
# `pip install "openkb[api]"` keeps working.
web = ["fastapi", "uvicorn", "python-multipart"]
api = ["openkb[web]"]

[tool.hatch.version]
source = "vcs"
Expand Down
10 changes: 9 additions & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
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
10 changes: 5 additions & 5 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -123,13 +123,13 @@ Subscription-based providers that authenticate via OAuth device flow (e.g. `chat
OpenKB ships a bundled web UI, served by the REST API at `/`. Install the API extra and start the server — no configuration needed:

```bash
pip install "openkb[api]"
openkb-api # serves the API + Workbench at http://127.0.0.1:8000/
pip install "openkb[web]"
openkb-web # serves the API + Workbench at http://127.0.0.1:7566/
```

Open `http://127.0.0.1:8000/` for the Workbench. Auth is off by default (local-first); set `OPENKB_API_TOKEN` to require a bearer token before exposing the server. See the [full Web UI guide](examples/rest-api/README.md#knowledge-workbench-web-ui).
Open `http://127.0.0.1:7566/` for the Workbench. Auth is off by default (local-first); set `OPENKB_API_TOKEN` to require a bearer token before exposing the server. See the [full Web UI guide](examples/rest-api/README.md#knowledge-workbench-web-ui).

> Working on the UI itself? Run the Vite dev server with `cd frontend && npm install && npm run dev` (it proxies `/api` to a running `openkb-api`), or `npm run build` to regenerate the bundled `openkb/web/`.
> Working on the UI itself? Run the Vite dev server with `cd frontend && npm install && npm run dev` (it proxies `/api` to a running `openkb-web`), or `npm run build` to regenerate the bundled `openkb/web/`.

# 🧩 How OpenKB Works

Expand DownExpand Up@@ -341,7 +341,7 @@ The skill is read-only. It won't run `openkb add`, `remove`, or `lint --fix` wit

# REST API

OpenKB ships a FastAPI service for HTTP clients. Install with `pip install -e ".[api]"`, then start with `python -m openkb.api`. The interactive API reference is at [`/docs`](http://127.0.0.1:8000/docs) (importable into Postman).
OpenKB ships a FastAPI service for HTTP clients. Install with `pip install -e ".[web]"`, then start with `python -m openkb.api`. The interactive API reference is at [`/docs`](http://127.0.0.1:7566/docs) (importable into Postman).

See the [full REST API reference](examples/rest-api/README.md#rest-api) for endpoints, auth, and SSE streaming.

Expand Down
20 changes: 10 additions & 10 deletions examples/rest-api/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@

This guide covers the OpenKB REST API (FastAPI) and the bundled Knowledge Workbench web UI.

> The interactive API reference is served live at [`/docs`](http://127.0.0.1:8000/docs) (OpenAPI/Swagger) once the server is running — you can import `/openapi.json` directly into Postman.
> The interactive API reference is served live at [`/docs`](http://127.0.0.1:7566/docs) (OpenAPI/Swagger) once the server is running — you can import `/openapi.json` directly into Postman.

## Knowledge Workbench (Web UI)

Expand All@@ -11,20 +11,20 @@ OpenKB ships a bundled web single-page app — the **Knowledge Workbench** — s

```bash
# 1. Install with the API extra (the built UI ships inside the package)
pip install "openkb[api]"
pip install "openkb[web]"

# 2. Start the server — no config needed for local use
openkb-api --host 127.0.0.1 --port 8000 # serves the API + Workbench at http://127.0.0.1:8000/
openkb-web --host 127.0.0.1 --port 7566 # serves the API + Workbench at http://127.0.0.1:7566/
```

Optional environment variables:

- `OPENKB_KB_ROOT` — where REST-created knowledge bases are stored (default `~/.config/openkb/kbs`).
- `OPENKB_API_TOKEN` — set it to require bearer auth (see [Authentication](#authentication-and-common-behavior)); leave unset for open local use.

> **From a source checkout?** The built bundle (`openkb/web/`) is git-ignored, so an editable install (`pip install -e ".[api]"`) has no UI until you build it once: `cd frontend && npm install && npm run build` (outputs to `openkb/web/`). Or run the Vite dev server with `npm run dev` (it proxies `/api` to a running `openkb-api`). Without the bundle, `openkb-api` serves only the REST API under `/api/v1` and `/` returns a 404.
> **From a source checkout?** The built bundle (`openkb/web/`) is git-ignored, so an editable install (`pip install -e ".[web]"`) has no UI until you build it once: `cd frontend && npm install && npm run build` (outputs to `openkb/web/`). Or run the Vite dev server with `npm run dev` (it proxies `/api` to a running `openkb-web`). Without the bundle, `openkb-web` serves only the REST API under `/api/v1` and `/` returns a 404.

Open `http://127.0.0.1:8000/` in your browser. With no `OPENKB_API_TOKEN` set it connects to the local API immediately — no prompt. (If a token is configured, a **Connection** dialog asks for it once and caches it in the browser; you can also open it manually to point the UI at a remote API base.) The Workbench then provides:
Open `http://127.0.0.1:7566/` in your browser. With no `OPENKB_API_TOKEN` set it connects to the local API immediately — no prompt. (If a token is configured, a **Connection** dialog asks for it once and caches it in the browser; you can also open it manually to point the UI at a remote API base.) The Workbench then provides:

- **Overview** — index/concept/summary/report stat cards, clickable concept chips, recent documents, and last-compile/lint activity.
- **Documents** — drag-and-drop multi-file upload with per-file SSE progress, hash table, and delete with confirmation.
Expand All@@ -44,15 +44,15 @@ frontends, or other HTTP clients.
Install the API dependencies if needed:

```bash
pip install -e ".[api]"
pip install -e ".[web]"
```

Start the API server:

```powershell
$env:OPENKB_API_TOKEN="test-token"
$env:OPENKB_KB_ROOT="D:\project\OpenKB\kbs"
.\.venv\Scripts\python.exe -m openkb.api --host 127.0.0.1 --port 8000
.\.venv\Scripts\python.exe -m openkb.api --host 127.0.0.1 --port 7566
```

### Authentication and common behavior
Expand All@@ -61,7 +61,7 @@ Auth is **opt-in**, controlled by the `OPENKB_API_TOKEN` server environment
variable:

- **Unset (default)** — the API is unauthenticated. This is the local-first
default, so `openkb-api` and the Workbench work with no configuration.
default, so `openkb-web` and the Workbench work with no configuration.
- **Set** — every request must carry the token, and the Workbench prompts for
it once (cached in the browser):

Expand All@@ -73,7 +73,7 @@ variable:

> **Exposing the server?** Always set `OPENKB_API_TOKEN` when binding to a
> non-loopback host (e.g. `--host 0.0.0.0`) — otherwise the API, and every KB
> it can reach, is world-open. `openkb-api` prints a warning in that case.
> it can reach, is world-open. `openkb-web` prints a warning in that case.

`OPENKB_KB_ROOT` is optional. It controls where REST-created knowledge bases
are stored. If unset, OpenKB uses `~/.config/openkb/kbs`.
Expand DownExpand Up@@ -419,4 +419,4 @@ no watcher is active for that KB.
stop after this many seconds). Stream events: `start`, the watcher's own events
(e.g. `added`, `updated`, `failed`, `final`), `error`, `done`.

The full OpenAPI schema is at [`/openapi.json`](http://127.0.0.1:8000/openapi.json) — importable into Postman or any OpenAPI-compatible client.
The full OpenAPI schema is at [`/openapi.json`](http://127.0.0.1:7566/openapi.json) — importable into Postman or any OpenAPI-compatible client.
2 changes: 1 addition & 1 deletion frontend/src/App.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -107,7 +107,7 @@ function ConnectionDialog({
<input
value={base}
onChange={(e) => setBase(e.target.value)}
placeholder="http://127.0.0.1:8000"
placeholder="http://127.0.0.1:7566"
className={inputCls}
/>
</div>
Expand Down
7 changes: 5 additions & 2 deletions frontend/src/components/ArtifactPanel.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -222,8 +222,11 @@ export default function ArtifactPanel({
className="absolute left-0 top-0 z-10 h-full w-1.5 -translate-x-1/2 cursor-col-resize hover:bg-accent-brand/30"
/>

{/* header */}
<div className="shrink-0 h-12 flex items-center gap-2 px-3 border-b border-[hsl(var(--glass-border))]">
{/* header — pr-28 reserves the global top-right chrome lane (theme + i18n
pills in App.tsx, absolute right-3 z-40) so the panel's action buttons
(open / download / close) never sit UNDER it. Same reserve convention
as KbList's header row and KbDetail's gear row. */}
<div className="shrink-0 h-12 flex items-center gap-2 pl-3 pr-28 border-b border-[hsl(var(--glass-border))]">
<HeaderIcon className="w-4 h-4 text-accent-brand shrink-0" />
<span className="min-w-0 truncate text-[13px] font-semibold text-foreground">
{artifactLabel(active, t)}
Expand Down
4 changes: 2 additions & 2 deletions frontend/vite.config.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ import path from "path"
import react from "@vitejs/plugin-react"
import { defineConfig } from "vite"

// Dev server proxies /api to the OpenKB REST API on :8000; production
// Dev server proxies /api to the OpenKB REST API on :7566; production
// serves the built bundle from the same origin via FastAPI StaticFiles.
// outDir MUST stay ../openkb/web — the wheel packages it from there
// (see pyproject.toml [tool.hatch.build] artifacts).
Expand All@@ -22,7 +22,7 @@ export default defineConfig({
port: 5173,
proxy: {
"/api": {
target: "http://127.0.0.1:8000",
target: "http://127.0.0.1:7566",
changeOrigin: true,
},
},
Expand Down
2 changes: 1 addition & 1 deletion openkb/api.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -776,7 +776,7 @@ async def api_not_found(path: str) -> Any:
def main() -> None:
parser = argparse.ArgumentParser(description="Run the OpenKB REST API.")
parser.add_argument("--host", default="127.0.0.1")
parser.add_argument("--port", type=int, default=8000)
parser.add_argument("--port", type=int, default=7566)
parser.add_argument("--reload", action="store_true")
args = parser.parse_args()

Expand Down
4 changes: 2 additions & 2 deletions openkb/api_helpers.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -69,8 +69,8 @@ def _configure_cors(app: FastAPI) -> None:
origins = [o.strip() for o in raw.split(",") if o.strip()] or [
"http://localhost:5173",
"http://127.0.0.1:5173",
"http://localhost:8000",
"http://127.0.0.1:8000",
"http://localhost:7566",
"http://127.0.0.1:7566",
]
# A wildcard origin with credentials is insecure: any site can issue
# credentialed cross-origin requests. Reject this combination by forcing
Expand Down
8 changes: 7 additions & 1 deletion pyproject.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -59,6 +59,8 @@ Issues = "https://github.com/VectifyAI/OpenKB/issues"

[project.scripts]
openkb = "openkb.cli:cli"
openkb-web = "openkb.api:main"
# Backwards-compatible alias for the historical name; same entry point.
openkb-api = "openkb.api:main"

[tool.pytest.ini_options]
Expand All@@ -73,7 +75,11 @@ dev = [
"mypy==1.15.0",
"types-PyYAML==6.0.12.20260518",
]
api = ["fastapi", "uvicorn", "python-multipart"]
# The Knowledge Workbench Web UI is served by this FastAPI server. `web` is the
# canonical extra; `api` is a backwards-compatible alias so an existing
# `pip install "openkb[api]"` keeps working.
web = ["fastapi", "uvicorn", "python-multipart"]
api = ["openkb[web]"]

[tool.hatch.version]
source = "vcs"
Expand Down
10 changes: 9 additions & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
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
10 changes: 5 additions & 5 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -123,13 +123,13 @@ Subscription-based providers that authenticate via OAuth device flow (e.g. `chat
OpenKB ships a bundled web UI, served by the REST API at `/`. Install the API extra and start the server — no configuration needed:

```bash
pip install "openkb[api]"
openkb-api # serves the API + Workbench at http://127.0.0.1:8000/
pip install "openkb[web]"
openkb-web # serves the API + Workbench at http://127.0.0.1:7566/
```

Open `http://127.0.0.1:8000/` for the Workbench. Auth is off by default (local-first); set `OPENKB_API_TOKEN` to require a bearer token before exposing the server. See the [full Web UI guide](examples/rest-api/README.md#knowledge-workbench-web-ui).
Open `http://127.0.0.1:7566/` for the Workbench. Auth is off by default (local-first); set `OPENKB_API_TOKEN` to require a bearer token before exposing the server. See the [full Web UI guide](examples/rest-api/README.md#knowledge-workbench-web-ui).

> Working on the UI itself? Run the Vite dev server with `cd frontend && npm install && npm run dev` (it proxies `/api` to a running `openkb-api`), or `npm run build` to regenerate the bundled `openkb/web/`.
> Working on the UI itself? Run the Vite dev server with `cd frontend && npm install && npm run dev` (it proxies `/api` to a running `openkb-web`), or `npm run build` to regenerate the bundled `openkb/web/`.

# 🧩 How OpenKB Works

Expand DownExpand Up@@ -341,7 +341,7 @@ The skill is read-only. It won't run `openkb add`, `remove`, or `lint --fix` wit

# REST API

OpenKB ships a FastAPI service for HTTP clients. Install with `pip install -e ".[api]"`, then start with `python -m openkb.api`. The interactive API reference is at [`/docs`](http://127.0.0.1:8000/docs) (importable into Postman).
OpenKB ships a FastAPI service for HTTP clients. Install with `pip install -e ".[web]"`, then start with `python -m openkb.api`. The interactive API reference is at [`/docs`](http://127.0.0.1:7566/docs) (importable into Postman).

See the [full REST API reference](examples/rest-api/README.md#rest-api) for endpoints, auth, and SSE streaming.

Expand Down
20 changes: 10 additions & 10 deletions examples/rest-api/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@

This guide covers the OpenKB REST API (FastAPI) and the bundled Knowledge Workbench web UI.

> The interactive API reference is served live at [`/docs`](http://127.0.0.1:8000/docs) (OpenAPI/Swagger) once the server is running — you can import `/openapi.json` directly into Postman.
> The interactive API reference is served live at [`/docs`](http://127.0.0.1:7566/docs) (OpenAPI/Swagger) once the server is running — you can import `/openapi.json` directly into Postman.

## Knowledge Workbench (Web UI)

Expand All@@ -11,20 +11,20 @@ OpenKB ships a bundled web single-page app — the **Knowledge Workbench** — s

```bash
# 1. Install with the API extra (the built UI ships inside the package)
pip install "openkb[api]"
pip install "openkb[web]"

# 2. Start the server — no config needed for local use
openkb-api --host 127.0.0.1 --port 8000 # serves the API + Workbench at http://127.0.0.1:8000/
openkb-web --host 127.0.0.1 --port 7566 # serves the API + Workbench at http://127.0.0.1:7566/
```

Optional environment variables:

- `OPENKB_KB_ROOT` — where REST-created knowledge bases are stored (default `~/.config/openkb/kbs`).
- `OPENKB_API_TOKEN` — set it to require bearer auth (see [Authentication](#authentication-and-common-behavior)); leave unset for open local use.

> **From a source checkout?** The built bundle (`openkb/web/`) is git-ignored, so an editable install (`pip install -e ".[api]"`) has no UI until you build it once: `cd frontend && npm install && npm run build` (outputs to `openkb/web/`). Or run the Vite dev server with `npm run dev` (it proxies `/api` to a running `openkb-api`). Without the bundle, `openkb-api` serves only the REST API under `/api/v1` and `/` returns a 404.
> **From a source checkout?** The built bundle (`openkb/web/`) is git-ignored, so an editable install (`pip install -e ".[web]"`) has no UI until you build it once: `cd frontend && npm install && npm run build` (outputs to `openkb/web/`). Or run the Vite dev server with `npm run dev` (it proxies `/api` to a running `openkb-web`). Without the bundle, `openkb-web` serves only the REST API under `/api/v1` and `/` returns a 404.

Open `http://127.0.0.1:8000/` in your browser. With no `OPENKB_API_TOKEN` set it connects to the local API immediately — no prompt. (If a token is configured, a **Connection** dialog asks for it once and caches it in the browser; you can also open it manually to point the UI at a remote API base.) The Workbench then provides:
Open `http://127.0.0.1:7566/` in your browser. With no `OPENKB_API_TOKEN` set it connects to the local API immediately — no prompt. (If a token is configured, a **Connection** dialog asks for it once and caches it in the browser; you can also open it manually to point the UI at a remote API base.) The Workbench then provides:

- **Overview** — index/concept/summary/report stat cards, clickable concept chips, recent documents, and last-compile/lint activity.
- **Documents** — drag-and-drop multi-file upload with per-file SSE progress, hash table, and delete with confirmation.
Expand All@@ -44,15 +44,15 @@ frontends, or other HTTP clients.
Install the API dependencies if needed:

```bash
pip install -e ".[api]"
pip install -e ".[web]"
```

Start the API server:

```powershell
$env:OPENKB_API_TOKEN="test-token"
$env:OPENKB_KB_ROOT="D:\project\OpenKB\kbs"
.\.venv\Scripts\python.exe -m openkb.api --host 127.0.0.1 --port 8000
.\.venv\Scripts\python.exe -m openkb.api --host 127.0.0.1 --port 7566
```

### Authentication and common behavior
Expand All@@ -61,7 +61,7 @@ Auth is **opt-in**, controlled by the `OPENKB_API_TOKEN` server environment
variable:

- **Unset (default)** — the API is unauthenticated. This is the local-first
default, so `openkb-api` and the Workbench work with no configuration.
default, so `openkb-web` and the Workbench work with no configuration.
- **Set** — every request must carry the token, and the Workbench prompts for
it once (cached in the browser):

Expand All@@ -73,7 +73,7 @@ variable:

> **Exposing the server?** Always set `OPENKB_API_TOKEN` when binding to a
> non-loopback host (e.g. `--host 0.0.0.0`) — otherwise the API, and every KB
> it can reach, is world-open. `openkb-api` prints a warning in that case.
> it can reach, is world-open. `openkb-web` prints a warning in that case.

`OPENKB_KB_ROOT` is optional. It controls where REST-created knowledge bases
are stored. If unset, OpenKB uses `~/.config/openkb/kbs`.
Expand DownExpand Up@@ -419,4 +419,4 @@ no watcher is active for that KB.
stop after this many seconds). Stream events: `start`, the watcher's own events
(e.g. `added`, `updated`, `failed`, `final`), `error`, `done`.

The full OpenAPI schema is at [`/openapi.json`](http://127.0.0.1:8000/openapi.json) — importable into Postman or any OpenAPI-compatible client.
The full OpenAPI schema is at [`/openapi.json`](http://127.0.0.1:7566/openapi.json) — importable into Postman or any OpenAPI-compatible client.
2 changes: 1 addition & 1 deletion frontend/src/App.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -107,7 +107,7 @@ function ConnectionDialog({
<input
value={base}
onChange={(e) => setBase(e.target.value)}
placeholder="http://127.0.0.1:8000"
placeholder="http://127.0.0.1:7566"
className={inputCls}
/>
</div>
Expand Down
7 changes: 5 additions & 2 deletions frontend/src/components/ArtifactPanel.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -222,8 +222,11 @@ export default function ArtifactPanel({
className="absolute left-0 top-0 z-10 h-full w-1.5 -translate-x-1/2 cursor-col-resize hover:bg-accent-brand/30"
/>

{/* header */}
<div className="shrink-0 h-12 flex items-center gap-2 px-3 border-b border-[hsl(var(--glass-border))]">
{/* header — pr-28 reserves the global top-right chrome lane (theme + i18n
pills in App.tsx, absolute right-3 z-40) so the panel's action buttons
(open / download / close) never sit UNDER it. Same reserve convention
as KbList's header row and KbDetail's gear row. */}
<div className="shrink-0 h-12 flex items-center gap-2 pl-3 pr-28 border-b border-[hsl(var(--glass-border))]">
<HeaderIcon className="w-4 h-4 text-accent-brand shrink-0" />
<span className="min-w-0 truncate text-[13px] font-semibold text-foreground">
{artifactLabel(active, t)}
Expand Down
4 changes: 2 additions & 2 deletions frontend/vite.config.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ import path from "path"
import react from "@vitejs/plugin-react"
import { defineConfig } from "vite"

// Dev server proxies /api to the OpenKB REST API on :8000; production
// Dev server proxies /api to the OpenKB REST API on :7566; production
// serves the built bundle from the same origin via FastAPI StaticFiles.
// outDir MUST stay ../openkb/web — the wheel packages it from there
// (see pyproject.toml [tool.hatch.build] artifacts).
Expand All@@ -22,7 +22,7 @@ export default defineConfig({
port: 5173,
proxy: {
"/api": {
target: "http://127.0.0.1:8000",
target: "http://127.0.0.1:7566",
changeOrigin: true,
},
},
Expand Down
2 changes: 1 addition & 1 deletion openkb/api.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -776,7 +776,7 @@ async def api_not_found(path: str) -> Any:
def main() -> None:
parser = argparse.ArgumentParser(description="Run the OpenKB REST API.")
parser.add_argument("--host", default="127.0.0.1")
parser.add_argument("--port", type=int, default=8000)
parser.add_argument("--port", type=int, default=7566)
parser.add_argument("--reload", action="store_true")
args = parser.parse_args()

Expand Down
4 changes: 2 additions & 2 deletions openkb/api_helpers.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -69,8 +69,8 @@ def _configure_cors(app: FastAPI) -> None:
origins = [o.strip() for o in raw.split(",") if o.strip()] or [
"http://localhost:5173",
"http://127.0.0.1:5173",
"http://localhost:8000",
"http://127.0.0.1:8000",
"http://localhost:7566",
"http://127.0.0.1:7566",
]
# A wildcard origin with credentials is insecure: any site can issue
# credentialed cross-origin requests. Reject this combination by forcing
Expand Down
8 changes: 7 additions & 1 deletion pyproject.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -59,6 +59,8 @@ Issues = "https://github.com/VectifyAI/OpenKB/issues"

[project.scripts]
openkb = "openkb.cli:cli"
openkb-web = "openkb.api:main"
# Backwards-compatible alias for the historical name; same entry point.
openkb-api = "openkb.api:main"

[tool.pytest.ini_options]
Expand All@@ -73,7 +75,11 @@ dev = [
"mypy==1.15.0",
"types-PyYAML==6.0.12.20260518",
]
api = ["fastapi", "uvicorn", "python-multipart"]
# The Knowledge Workbench Web UI is served by this FastAPI server. `web` is the
# canonical extra; `api` is a backwards-compatible alias so an existing
# `pip install "openkb[api]"` keeps working.
web = ["fastapi", "uvicorn", "python-multipart"]
api = ["openkb[web]"]

[tool.hatch.version]
source = "vcs"
Expand Down
10 changes: 9 additions & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
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
10 changes: 5 additions & 5 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -123,13 +123,13 @@ Subscription-based providers that authenticate via OAuth device flow (e.g. `chat
OpenKB ships a bundled web UI, served by the REST API at `/`. Install the API extra and start the server — no configuration needed:

```bash
pip install "openkb[api]"
openkb-api # serves the API + Workbench at http://127.0.0.1:8000/
pip install "openkb[web]"
openkb-web # serves the API + Workbench at http://127.0.0.1:7566/
```

Open `http://127.0.0.1:8000/` for the Workbench. Auth is off by default (local-first); set `OPENKB_API_TOKEN` to require a bearer token before exposing the server. See the [full Web UI guide](examples/rest-api/README.md#knowledge-workbench-web-ui).
Open `http://127.0.0.1:7566/` for the Workbench. Auth is off by default (local-first); set `OPENKB_API_TOKEN` to require a bearer token before exposing the server. See the [full Web UI guide](examples/rest-api/README.md#knowledge-workbench-web-ui).

> Working on the UI itself? Run the Vite dev server with `cd frontend && npm install && npm run dev` (it proxies `/api` to a running `openkb-api`), or `npm run build` to regenerate the bundled `openkb/web/`.
> Working on the UI itself? Run the Vite dev server with `cd frontend && npm install && npm run dev` (it proxies `/api` to a running `openkb-web`), or `npm run build` to regenerate the bundled `openkb/web/`.

# 🧩 How OpenKB Works

Expand DownExpand Up@@ -341,7 +341,7 @@ The skill is read-only. It won't run `openkb add`, `remove`, or `lint --fix` wit

# REST API

OpenKB ships a FastAPI service for HTTP clients. Install with `pip install -e ".[api]"`, then start with `python -m openkb.api`. The interactive API reference is at [`/docs`](http://127.0.0.1:8000/docs) (importable into Postman).
OpenKB ships a FastAPI service for HTTP clients. Install with `pip install -e ".[web]"`, then start with `python -m openkb.api`. The interactive API reference is at [`/docs`](http://127.0.0.1:7566/docs) (importable into Postman).

See the [full REST API reference](examples/rest-api/README.md#rest-api) for endpoints, auth, and SSE streaming.

Expand Down
20 changes: 10 additions & 10 deletions examples/rest-api/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@

This guide covers the OpenKB REST API (FastAPI) and the bundled Knowledge Workbench web UI.

> The interactive API reference is served live at [`/docs`](http://127.0.0.1:8000/docs) (OpenAPI/Swagger) once the server is running — you can import `/openapi.json` directly into Postman.
> The interactive API reference is served live at [`/docs`](http://127.0.0.1:7566/docs) (OpenAPI/Swagger) once the server is running — you can import `/openapi.json` directly into Postman.

## Knowledge Workbench (Web UI)

Expand All@@ -11,20 +11,20 @@ OpenKB ships a bundled web single-page app — the **Knowledge Workbench** — s

```bash
# 1. Install with the API extra (the built UI ships inside the package)
pip install "openkb[api]"
pip install "openkb[web]"

# 2. Start the server — no config needed for local use
openkb-api --host 127.0.0.1 --port 8000 # serves the API + Workbench at http://127.0.0.1:8000/
openkb-web --host 127.0.0.1 --port 7566 # serves the API + Workbench at http://127.0.0.1:7566/
```

Optional environment variables:

- `OPENKB_KB_ROOT` — where REST-created knowledge bases are stored (default `~/.config/openkb/kbs`).
- `OPENKB_API_TOKEN` — set it to require bearer auth (see [Authentication](#authentication-and-common-behavior)); leave unset for open local use.

> **From a source checkout?** The built bundle (`openkb/web/`) is git-ignored, so an editable install (`pip install -e ".[api]"`) has no UI until you build it once: `cd frontend && npm install && npm run build` (outputs to `openkb/web/`). Or run the Vite dev server with `npm run dev` (it proxies `/api` to a running `openkb-api`). Without the bundle, `openkb-api` serves only the REST API under `/api/v1` and `/` returns a 404.
> **From a source checkout?** The built bundle (`openkb/web/`) is git-ignored, so an editable install (`pip install -e ".[web]"`) has no UI until you build it once: `cd frontend && npm install && npm run build` (outputs to `openkb/web/`). Or run the Vite dev server with `npm run dev` (it proxies `/api` to a running `openkb-web`). Without the bundle, `openkb-web` serves only the REST API under `/api/v1` and `/` returns a 404.

Open `http://127.0.0.1:8000/` in your browser. With no `OPENKB_API_TOKEN` set it connects to the local API immediately — no prompt. (If a token is configured, a **Connection** dialog asks for it once and caches it in the browser; you can also open it manually to point the UI at a remote API base.) The Workbench then provides:
Open `http://127.0.0.1:7566/` in your browser. With no `OPENKB_API_TOKEN` set it connects to the local API immediately — no prompt. (If a token is configured, a **Connection** dialog asks for it once and caches it in the browser; you can also open it manually to point the UI at a remote API base.) The Workbench then provides:

- **Overview** — index/concept/summary/report stat cards, clickable concept chips, recent documents, and last-compile/lint activity.
- **Documents** — drag-and-drop multi-file upload with per-file SSE progress, hash table, and delete with confirmation.
Expand All@@ -44,15 +44,15 @@ frontends, or other HTTP clients.
Install the API dependencies if needed:

```bash
pip install -e ".[api]"
pip install -e ".[web]"
```

Start the API server:

```powershell
$env:OPENKB_API_TOKEN="test-token"
$env:OPENKB_KB_ROOT="D:\project\OpenKB\kbs"
.\.venv\Scripts\python.exe -m openkb.api --host 127.0.0.1 --port 8000
.\.venv\Scripts\python.exe -m openkb.api --host 127.0.0.1 --port 7566
```

### Authentication and common behavior
Expand All@@ -61,7 +61,7 @@ Auth is **opt-in**, controlled by the `OPENKB_API_TOKEN` server environment
variable:

- **Unset (default)** — the API is unauthenticated. This is the local-first
default, so `openkb-api` and the Workbench work with no configuration.
default, so `openkb-web` and the Workbench work with no configuration.
- **Set** — every request must carry the token, and the Workbench prompts for
it once (cached in the browser):

Expand All@@ -73,7 +73,7 @@ variable:

> **Exposing the server?** Always set `OPENKB_API_TOKEN` when binding to a
> non-loopback host (e.g. `--host 0.0.0.0`) — otherwise the API, and every KB
> it can reach, is world-open. `openkb-api` prints a warning in that case.
> it can reach, is world-open. `openkb-web` prints a warning in that case.

`OPENKB_KB_ROOT` is optional. It controls where REST-created knowledge bases
are stored. If unset, OpenKB uses `~/.config/openkb/kbs`.
Expand DownExpand Up@@ -419,4 +419,4 @@ no watcher is active for that KB.
stop after this many seconds). Stream events: `start`, the watcher's own events
(e.g. `added`, `updated`, `failed`, `final`), `error`, `done`.

The full OpenAPI schema is at [`/openapi.json`](http://127.0.0.1:8000/openapi.json) — importable into Postman or any OpenAPI-compatible client.
The full OpenAPI schema is at [`/openapi.json`](http://127.0.0.1:7566/openapi.json) — importable into Postman or any OpenAPI-compatible client.
2 changes: 1 addition & 1 deletion frontend/src/App.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -107,7 +107,7 @@ function ConnectionDialog({
<input
value={base}
onChange={(e) => setBase(e.target.value)}
placeholder="http://127.0.0.1:8000"
placeholder="http://127.0.0.1:7566"
className={inputCls}
/>
</div>
Expand Down
7 changes: 5 additions & 2 deletions frontend/src/components/ArtifactPanel.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -222,8 +222,11 @@ export default function ArtifactPanel({
className="absolute left-0 top-0 z-10 h-full w-1.5 -translate-x-1/2 cursor-col-resize hover:bg-accent-brand/30"
/>

{/* header */}
<div className="shrink-0 h-12 flex items-center gap-2 px-3 border-b border-[hsl(var(--glass-border))]">
{/* header — pr-28 reserves the global top-right chrome lane (theme + i18n
pills in App.tsx, absolute right-3 z-40) so the panel's action buttons
(open / download / close) never sit UNDER it. Same reserve convention
as KbList's header row and KbDetail's gear row. */}
<div className="shrink-0 h-12 flex items-center gap-2 pl-3 pr-28 border-b border-[hsl(var(--glass-border))]">
<HeaderIcon className="w-4 h-4 text-accent-brand shrink-0" />
<span className="min-w-0 truncate text-[13px] font-semibold text-foreground">
{artifactLabel(active, t)}
Expand Down
4 changes: 2 additions & 2 deletions frontend/vite.config.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ import path from "path"
import react from "@vitejs/plugin-react"
import { defineConfig } from "vite"

// Dev server proxies /api to the OpenKB REST API on :8000; production
// Dev server proxies /api to the OpenKB REST API on :7566; production
// serves the built bundle from the same origin via FastAPI StaticFiles.
// outDir MUST stay ../openkb/web — the wheel packages it from there
// (see pyproject.toml [tool.hatch.build] artifacts).
Expand All@@ -22,7 +22,7 @@ export default defineConfig({
port: 5173,
proxy: {
"/api": {
target: "http://127.0.0.1:8000",
target: "http://127.0.0.1:7566",
changeOrigin: true,
},
},
Expand Down
2 changes: 1 addition & 1 deletion openkb/api.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -776,7 +776,7 @@ async def api_not_found(path: str) -> Any:
def main() -> None:
parser = argparse.ArgumentParser(description="Run the OpenKB REST API.")
parser.add_argument("--host", default="127.0.0.1")
parser.add_argument("--port", type=int, default=8000)
parser.add_argument("--port", type=int, default=7566)
parser.add_argument("--reload", action="store_true")
args = parser.parse_args()

Expand Down
4 changes: 2 additions & 2 deletions openkb/api_helpers.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -69,8 +69,8 @@ def _configure_cors(app: FastAPI) -> None:
origins = [o.strip() for o in raw.split(",") if o.strip()] or [
"http://localhost:5173",
"http://127.0.0.1:5173",
"http://localhost:8000",
"http://127.0.0.1:8000",
"http://localhost:7566",
"http://127.0.0.1:7566",
]
# A wildcard origin with credentials is insecure: any site can issue
# credentialed cross-origin requests. Reject this combination by forcing
Expand Down
8 changes: 7 additions & 1 deletion pyproject.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -59,6 +59,8 @@ Issues = "https://github.com/VectifyAI/OpenKB/issues"

[project.scripts]
openkb = "openkb.cli:cli"
openkb-web = "openkb.api:main"
# Backwards-compatible alias for the historical name; same entry point.
openkb-api = "openkb.api:main"

[tool.pytest.ini_options]
Expand All@@ -73,7 +75,11 @@ dev = [
"mypy==1.15.0",
"types-PyYAML==6.0.12.20260518",
]
api = ["fastapi", "uvicorn", "python-multipart"]
# The Knowledge Workbench Web UI is served by this FastAPI server. `web` is the
# canonical extra; `api` is a backwards-compatible alias so an existing
# `pip install "openkb[api]"` keeps working.
web = ["fastapi", "uvicorn", "python-multipart"]
api = ["openkb[web]"]

[tool.hatch.version]
source = "vcs"
Expand Down
10 changes: 9 additions & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
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
10 changes: 5 additions & 5 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -123,13 +123,13 @@ Subscription-based providers that authenticate via OAuth device flow (e.g. `chat
OpenKB ships a bundled web UI, served by the REST API at `/`. Install the API extra and start the server — no configuration needed:

```bash
pip install "openkb[api]"
openkb-api # serves the API + Workbench at http://127.0.0.1:8000/
pip install "openkb[web]"
openkb-web # serves the API + Workbench at http://127.0.0.1:7566/
```

Open `http://127.0.0.1:8000/` for the Workbench. Auth is off by default (local-first); set `OPENKB_API_TOKEN` to require a bearer token before exposing the server. See the [full Web UI guide](examples/rest-api/README.md#knowledge-workbench-web-ui).
Open `http://127.0.0.1:7566/` for the Workbench. Auth is off by default (local-first); set `OPENKB_API_TOKEN` to require a bearer token before exposing the server. See the [full Web UI guide](examples/rest-api/README.md#knowledge-workbench-web-ui).

> Working on the UI itself? Run the Vite dev server with `cd frontend && npm install && npm run dev` (it proxies `/api` to a running `openkb-api`), or `npm run build` to regenerate the bundled `openkb/web/`.
> Working on the UI itself? Run the Vite dev server with `cd frontend && npm install && npm run dev` (it proxies `/api` to a running `openkb-web`), or `npm run build` to regenerate the bundled `openkb/web/`.

# 🧩 How OpenKB Works

Expand DownExpand Up@@ -341,7 +341,7 @@ The skill is read-only. It won't run `openkb add`, `remove`, or `lint --fix` wit

# REST API

OpenKB ships a FastAPI service for HTTP clients. Install with `pip install -e ".[api]"`, then start with `python -m openkb.api`. The interactive API reference is at [`/docs`](http://127.0.0.1:8000/docs) (importable into Postman).
OpenKB ships a FastAPI service for HTTP clients. Install with `pip install -e ".[web]"`, then start with `python -m openkb.api`. The interactive API reference is at [`/docs`](http://127.0.0.1:7566/docs) (importable into Postman).

See the [full REST API reference](examples/rest-api/README.md#rest-api) for endpoints, auth, and SSE streaming.

Expand Down
20 changes: 10 additions & 10 deletions examples/rest-api/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@

This guide covers the OpenKB REST API (FastAPI) and the bundled Knowledge Workbench web UI.

> The interactive API reference is served live at [`/docs`](http://127.0.0.1:8000/docs) (OpenAPI/Swagger) once the server is running — you can import `/openapi.json` directly into Postman.
> The interactive API reference is served live at [`/docs`](http://127.0.0.1:7566/docs) (OpenAPI/Swagger) once the server is running — you can import `/openapi.json` directly into Postman.

## Knowledge Workbench (Web UI)

Expand All@@ -11,20 +11,20 @@ OpenKB ships a bundled web single-page app — the **Knowledge Workbench** — s

```bash
# 1. Install with the API extra (the built UI ships inside the package)
pip install "openkb[api]"
pip install "openkb[web]"

# 2. Start the server — no config needed for local use
openkb-api --host 127.0.0.1 --port 8000 # serves the API + Workbench at http://127.0.0.1:8000/
openkb-web --host 127.0.0.1 --port 7566 # serves the API + Workbench at http://127.0.0.1:7566/
```

Optional environment variables:

- `OPENKB_KB_ROOT` — where REST-created knowledge bases are stored (default `~/.config/openkb/kbs`).
- `OPENKB_API_TOKEN` — set it to require bearer auth (see [Authentication](#authentication-and-common-behavior)); leave unset for open local use.

> **From a source checkout?** The built bundle (`openkb/web/`) is git-ignored, so an editable install (`pip install -e ".[api]"`) has no UI until you build it once: `cd frontend && npm install && npm run build` (outputs to `openkb/web/`). Or run the Vite dev server with `npm run dev` (it proxies `/api` to a running `openkb-api`). Without the bundle, `openkb-api` serves only the REST API under `/api/v1` and `/` returns a 404.
> **From a source checkout?** The built bundle (`openkb/web/`) is git-ignored, so an editable install (`pip install -e ".[web]"`) has no UI until you build it once: `cd frontend && npm install && npm run build` (outputs to `openkb/web/`). Or run the Vite dev server with `npm run dev` (it proxies `/api` to a running `openkb-web`). Without the bundle, `openkb-web` serves only the REST API under `/api/v1` and `/` returns a 404.

Open `http://127.0.0.1:8000/` in your browser. With no `OPENKB_API_TOKEN` set it connects to the local API immediately — no prompt. (If a token is configured, a **Connection** dialog asks for it once and caches it in the browser; you can also open it manually to point the UI at a remote API base.) The Workbench then provides:
Open `http://127.0.0.1:7566/` in your browser. With no `OPENKB_API_TOKEN` set it connects to the local API immediately — no prompt. (If a token is configured, a **Connection** dialog asks for it once and caches it in the browser; you can also open it manually to point the UI at a remote API base.) The Workbench then provides:

- **Overview** — index/concept/summary/report stat cards, clickable concept chips, recent documents, and last-compile/lint activity.
- **Documents** — drag-and-drop multi-file upload with per-file SSE progress, hash table, and delete with confirmation.
Expand All@@ -44,15 +44,15 @@ frontends, or other HTTP clients.
Install the API dependencies if needed:

```bash
pip install -e ".[api]"
pip install -e ".[web]"
```

Start the API server:

```powershell
$env:OPENKB_API_TOKEN="test-token"
$env:OPENKB_KB_ROOT="D:\project\OpenKB\kbs"
.\.venv\Scripts\python.exe -m openkb.api --host 127.0.0.1 --port 8000
.\.venv\Scripts\python.exe -m openkb.api --host 127.0.0.1 --port 7566
```

### Authentication and common behavior
Expand All@@ -61,7 +61,7 @@ Auth is **opt-in**, controlled by the `OPENKB_API_TOKEN` server environment
variable:

- **Unset (default)** — the API is unauthenticated. This is the local-first
default, so `openkb-api` and the Workbench work with no configuration.
default, so `openkb-web` and the Workbench work with no configuration.
- **Set** — every request must carry the token, and the Workbench prompts for
it once (cached in the browser):

Expand All@@ -73,7 +73,7 @@ variable:

> **Exposing the server?** Always set `OPENKB_API_TOKEN` when binding to a
> non-loopback host (e.g. `--host 0.0.0.0`) — otherwise the API, and every KB
> it can reach, is world-open. `openkb-api` prints a warning in that case.
> it can reach, is world-open. `openkb-web` prints a warning in that case.

`OPENKB_KB_ROOT` is optional. It controls where REST-created knowledge bases
are stored. If unset, OpenKB uses `~/.config/openkb/kbs`.
Expand DownExpand Up@@ -419,4 +419,4 @@ no watcher is active for that KB.
stop after this many seconds). Stream events: `start`, the watcher's own events
(e.g. `added`, `updated`, `failed`, `final`), `error`, `done`.

The full OpenAPI schema is at [`/openapi.json`](http://127.0.0.1:8000/openapi.json) — importable into Postman or any OpenAPI-compatible client.
The full OpenAPI schema is at [`/openapi.json`](http://127.0.0.1:7566/openapi.json) — importable into Postman or any OpenAPI-compatible client.
2 changes: 1 addition & 1 deletion frontend/src/App.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -107,7 +107,7 @@ function ConnectionDialog({
<input
value={base}
onChange={(e) => setBase(e.target.value)}
placeholder="http://127.0.0.1:8000"
placeholder="http://127.0.0.1:7566"
className={inputCls}
/>
</div>
Expand Down
7 changes: 5 additions & 2 deletions frontend/src/components/ArtifactPanel.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -222,8 +222,11 @@ export default function ArtifactPanel({
className="absolute left-0 top-0 z-10 h-full w-1.5 -translate-x-1/2 cursor-col-resize hover:bg-accent-brand/30"
/>

{/* header */}
<div className="shrink-0 h-12 flex items-center gap-2 px-3 border-b border-[hsl(var(--glass-border))]">
{/* header — pr-28 reserves the global top-right chrome lane (theme + i18n
pills in App.tsx, absolute right-3 z-40) so the panel's action buttons
(open / download / close) never sit UNDER it. Same reserve convention
as KbList's header row and KbDetail's gear row. */}
<div className="shrink-0 h-12 flex items-center gap-2 pl-3 pr-28 border-b border-[hsl(var(--glass-border))]">
<HeaderIcon className="w-4 h-4 text-accent-brand shrink-0" />
<span className="min-w-0 truncate text-[13px] font-semibold text-foreground">
{artifactLabel(active, t)}
Expand Down
4 changes: 2 additions & 2 deletions frontend/vite.config.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ import path from "path"
import react from "@vitejs/plugin-react"
import { defineConfig } from "vite"

// Dev server proxies /api to the OpenKB REST API on :8000; production
// Dev server proxies /api to the OpenKB REST API on :7566; production
// serves the built bundle from the same origin via FastAPI StaticFiles.
// outDir MUST stay ../openkb/web — the wheel packages it from there
// (see pyproject.toml [tool.hatch.build] artifacts).
Expand All@@ -22,7 +22,7 @@ export default defineConfig({
port: 5173,
proxy: {
"/api": {
target: "http://127.0.0.1:8000",
target: "http://127.0.0.1:7566",
changeOrigin: true,
},
},
Expand Down
2 changes: 1 addition & 1 deletion openkb/api.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -776,7 +776,7 @@ async def api_not_found(path: str) -> Any:
def main() -> None:
parser = argparse.ArgumentParser(description="Run the OpenKB REST API.")
parser.add_argument("--host", default="127.0.0.1")
parser.add_argument("--port", type=int, default=8000)
parser.add_argument("--port", type=int, default=7566)
parser.add_argument("--reload", action="store_true")
args = parser.parse_args()

Expand Down
4 changes: 2 additions & 2 deletions openkb/api_helpers.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -69,8 +69,8 @@ def _configure_cors(app: FastAPI) -> None:
origins = [o.strip() for o in raw.split(",") if o.strip()] or [
"http://localhost:5173",
"http://127.0.0.1:5173",
"http://localhost:8000",
"http://127.0.0.1:8000",
"http://localhost:7566",
"http://127.0.0.1:7566",
]
# A wildcard origin with credentials is insecure: any site can issue
# credentialed cross-origin requests. Reject this combination by forcing
Expand Down
8 changes: 7 additions & 1 deletion pyproject.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -59,6 +59,8 @@ Issues = "https://github.com/VectifyAI/OpenKB/issues"

[project.scripts]
openkb = "openkb.cli:cli"
openkb-web = "openkb.api:main"
# Backwards-compatible alias for the historical name; same entry point.
openkb-api = "openkb.api:main"

[tool.pytest.ini_options]
Expand All@@ -73,7 +75,11 @@ dev = [
"mypy==1.15.0",
"types-PyYAML==6.0.12.20260518",
]
api = ["fastapi", "uvicorn", "python-multipart"]
# The Knowledge Workbench Web UI is served by this FastAPI server. `web` is the
# canonical extra; `api` is a backwards-compatible alias so an existing
# `pip install "openkb[api]"` keeps working.
web = ["fastapi", "uvicorn", "python-multipart"]
api = ["openkb[web]"]

[tool.hatch.version]
source = "vcs"
Expand Down
10 changes: 9 additions & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
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
10 changes: 5 additions & 5 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -123,13 +123,13 @@ Subscription-based providers that authenticate via OAuth device flow (e.g. `chat
OpenKB ships a bundled web UI, served by the REST API at `/`. Install the API extra and start the server — no configuration needed:

```bash
pip install "openkb[api]"
openkb-api # serves the API + Workbench at http://127.0.0.1:8000/
pip install "openkb[web]"
openkb-web # serves the API + Workbench at http://127.0.0.1:7566/
```

Open `http://127.0.0.1:8000/` for the Workbench. Auth is off by default (local-first); set `OPENKB_API_TOKEN` to require a bearer token before exposing the server. See the [full Web UI guide](examples/rest-api/README.md#knowledge-workbench-web-ui).
Open `http://127.0.0.1:7566/` for the Workbench. Auth is off by default (local-first); set `OPENKB_API_TOKEN` to require a bearer token before exposing the server. See the [full Web UI guide](examples/rest-api/README.md#knowledge-workbench-web-ui).

> Working on the UI itself? Run the Vite dev server with `cd frontend && npm install && npm run dev` (it proxies `/api` to a running `openkb-api`), or `npm run build` to regenerate the bundled `openkb/web/`.
> Working on the UI itself? Run the Vite dev server with `cd frontend && npm install && npm run dev` (it proxies `/api` to a running `openkb-web`), or `npm run build` to regenerate the bundled `openkb/web/`.

# 🧩 How OpenKB Works

Expand DownExpand Up@@ -341,7 +341,7 @@ The skill is read-only. It won't run `openkb add`, `remove`, or `lint --fix` wit

# REST API

OpenKB ships a FastAPI service for HTTP clients. Install with `pip install -e ".[api]"`, then start with `python -m openkb.api`. The interactive API reference is at [`/docs`](http://127.0.0.1:8000/docs) (importable into Postman).
OpenKB ships a FastAPI service for HTTP clients. Install with `pip install -e ".[web]"`, then start with `python -m openkb.api`. The interactive API reference is at [`/docs`](http://127.0.0.1:7566/docs) (importable into Postman).

See the [full REST API reference](examples/rest-api/README.md#rest-api) for endpoints, auth, and SSE streaming.

Expand Down
20 changes: 10 additions & 10 deletions examples/rest-api/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@

This guide covers the OpenKB REST API (FastAPI) and the bundled Knowledge Workbench web UI.

> The interactive API reference is served live at [`/docs`](http://127.0.0.1:8000/docs) (OpenAPI/Swagger) once the server is running — you can import `/openapi.json` directly into Postman.
> The interactive API reference is served live at [`/docs`](http://127.0.0.1:7566/docs) (OpenAPI/Swagger) once the server is running — you can import `/openapi.json` directly into Postman.

## Knowledge Workbench (Web UI)

Expand All@@ -11,20 +11,20 @@ OpenKB ships a bundled web single-page app — the **Knowledge Workbench** — s

```bash
# 1. Install with the API extra (the built UI ships inside the package)
pip install "openkb[api]"
pip install "openkb[web]"

# 2. Start the server — no config needed for local use
openkb-api --host 127.0.0.1 --port 8000 # serves the API + Workbench at http://127.0.0.1:8000/
openkb-web --host 127.0.0.1 --port 7566 # serves the API + Workbench at http://127.0.0.1:7566/
```

Optional environment variables:

- `OPENKB_KB_ROOT` — where REST-created knowledge bases are stored (default `~/.config/openkb/kbs`).
- `OPENKB_API_TOKEN` — set it to require bearer auth (see [Authentication](#authentication-and-common-behavior)); leave unset for open local use.

> **From a source checkout?** The built bundle (`openkb/web/`) is git-ignored, so an editable install (`pip install -e ".[api]"`) has no UI until you build it once: `cd frontend && npm install && npm run build` (outputs to `openkb/web/`). Or run the Vite dev server with `npm run dev` (it proxies `/api` to a running `openkb-api`). Without the bundle, `openkb-api` serves only the REST API under `/api/v1` and `/` returns a 404.
> **From a source checkout?** The built bundle (`openkb/web/`) is git-ignored, so an editable install (`pip install -e ".[web]"`) has no UI until you build it once: `cd frontend && npm install && npm run build` (outputs to `openkb/web/`). Or run the Vite dev server with `npm run dev` (it proxies `/api` to a running `openkb-web`). Without the bundle, `openkb-web` serves only the REST API under `/api/v1` and `/` returns a 404.

Open `http://127.0.0.1:8000/` in your browser. With no `OPENKB_API_TOKEN` set it connects to the local API immediately — no prompt. (If a token is configured, a **Connection** dialog asks for it once and caches it in the browser; you can also open it manually to point the UI at a remote API base.) The Workbench then provides:
Open `http://127.0.0.1:7566/` in your browser. With no `OPENKB_API_TOKEN` set it connects to the local API immediately — no prompt. (If a token is configured, a **Connection** dialog asks for it once and caches it in the browser; you can also open it manually to point the UI at a remote API base.) The Workbench then provides:

- **Overview** — index/concept/summary/report stat cards, clickable concept chips, recent documents, and last-compile/lint activity.
- **Documents** — drag-and-drop multi-file upload with per-file SSE progress, hash table, and delete with confirmation.
Expand All@@ -44,15 +44,15 @@ frontends, or other HTTP clients.
Install the API dependencies if needed:

```bash
pip install -e ".[api]"
pip install -e ".[web]"
```

Start the API server:

```powershell
$env:OPENKB_API_TOKEN="test-token"
$env:OPENKB_KB_ROOT="D:\project\OpenKB\kbs"
.\.venv\Scripts\python.exe -m openkb.api --host 127.0.0.1 --port 8000
.\.venv\Scripts\python.exe -m openkb.api --host 127.0.0.1 --port 7566
```

### Authentication and common behavior
Expand All@@ -61,7 +61,7 @@ Auth is **opt-in**, controlled by the `OPENKB_API_TOKEN` server environment
variable:

- **Unset (default)** — the API is unauthenticated. This is the local-first
default, so `openkb-api` and the Workbench work with no configuration.
default, so `openkb-web` and the Workbench work with no configuration.
- **Set** — every request must carry the token, and the Workbench prompts for
it once (cached in the browser):

Expand All@@ -73,7 +73,7 @@ variable:

> **Exposing the server?** Always set `OPENKB_API_TOKEN` when binding to a
> non-loopback host (e.g. `--host 0.0.0.0`) — otherwise the API, and every KB
> it can reach, is world-open. `openkb-api` prints a warning in that case.
> it can reach, is world-open. `openkb-web` prints a warning in that case.

`OPENKB_KB_ROOT` is optional. It controls where REST-created knowledge bases
are stored. If unset, OpenKB uses `~/.config/openkb/kbs`.
Expand DownExpand Up@@ -419,4 +419,4 @@ no watcher is active for that KB.
stop after this many seconds). Stream events: `start`, the watcher's own events
(e.g. `added`, `updated`, `failed`, `final`), `error`, `done`.

The full OpenAPI schema is at [`/openapi.json`](http://127.0.0.1:8000/openapi.json) — importable into Postman or any OpenAPI-compatible client.
The full OpenAPI schema is at [`/openapi.json`](http://127.0.0.1:7566/openapi.json) — importable into Postman or any OpenAPI-compatible client.
2 changes: 1 addition & 1 deletion frontend/src/App.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -107,7 +107,7 @@ function ConnectionDialog({
<input
value={base}
onChange={(e) => setBase(e.target.value)}
placeholder="http://127.0.0.1:8000"
placeholder="http://127.0.0.1:7566"
className={inputCls}
/>
</div>
Expand Down
7 changes: 5 additions & 2 deletions frontend/src/components/ArtifactPanel.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -222,8 +222,11 @@ export default function ArtifactPanel({
className="absolute left-0 top-0 z-10 h-full w-1.5 -translate-x-1/2 cursor-col-resize hover:bg-accent-brand/30"
/>

{/* header */}
<div className="shrink-0 h-12 flex items-center gap-2 px-3 border-b border-[hsl(var(--glass-border))]">
{/* header — pr-28 reserves the global top-right chrome lane (theme + i18n
pills in App.tsx, absolute right-3 z-40) so the panel's action buttons
(open / download / close) never sit UNDER it. Same reserve convention
as KbList's header row and KbDetail's gear row. */}
<div className="shrink-0 h-12 flex items-center gap-2 pl-3 pr-28 border-b border-[hsl(var(--glass-border))]">
<HeaderIcon className="w-4 h-4 text-accent-brand shrink-0" />
<span className="min-w-0 truncate text-[13px] font-semibold text-foreground">
{artifactLabel(active, t)}
Expand Down
4 changes: 2 additions & 2 deletions frontend/vite.config.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ import path from "path"
import react from "@vitejs/plugin-react"
import { defineConfig } from "vite"

// Dev server proxies /api to the OpenKB REST API on :8000; production
// Dev server proxies /api to the OpenKB REST API on :7566; production
// serves the built bundle from the same origin via FastAPI StaticFiles.
// outDir MUST stay ../openkb/web — the wheel packages it from there
// (see pyproject.toml [tool.hatch.build] artifacts).
Expand All@@ -22,7 +22,7 @@ export default defineConfig({
port: 5173,
proxy: {
"/api": {
target: "http://127.0.0.1:8000",
target: "http://127.0.0.1:7566",
changeOrigin: true,
},
},
Expand Down
2 changes: 1 addition & 1 deletion openkb/api.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -776,7 +776,7 @@ async def api_not_found(path: str) -> Any:
def main() -> None:
parser = argparse.ArgumentParser(description="Run the OpenKB REST API.")
parser.add_argument("--host", default="127.0.0.1")
parser.add_argument("--port", type=int, default=8000)
parser.add_argument("--port", type=int, default=7566)
parser.add_argument("--reload", action="store_true")
args = parser.parse_args()

Expand Down
4 changes: 2 additions & 2 deletions openkb/api_helpers.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -69,8 +69,8 @@ def _configure_cors(app: FastAPI) -> None:
origins = [o.strip() for o in raw.split(",") if o.strip()] or [
"http://localhost:5173",
"http://127.0.0.1:5173",
"http://localhost:8000",
"http://127.0.0.1:8000",
"http://localhost:7566",
"http://127.0.0.1:7566",
]
# A wildcard origin with credentials is insecure: any site can issue
# credentialed cross-origin requests. Reject this combination by forcing
Expand Down
8 changes: 7 additions & 1 deletion pyproject.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -59,6 +59,8 @@ Issues = "https://github.com/VectifyAI/OpenKB/issues"

[project.scripts]
openkb = "openkb.cli:cli"
openkb-web = "openkb.api:main"
# Backwards-compatible alias for the historical name; same entry point.
openkb-api = "openkb.api:main"

[tool.pytest.ini_options]
Expand All@@ -73,7 +75,11 @@ dev = [
"mypy==1.15.0",
"types-PyYAML==6.0.12.20260518",
]
api = ["fastapi", "uvicorn", "python-multipart"]
# The Knowledge Workbench Web UI is served by this FastAPI server. `web` is the
# canonical extra; `api` is a backwards-compatible alias so an existing
# `pip install "openkb[api]"` keeps working.
web = ["fastapi", "uvicorn", "python-multipart"]
api = ["openkb[web]"]

[tool.hatch.version]
source = "vcs"
Expand Down
10 changes: 9 additions & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
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
10 changes: 5 additions & 5 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -123,13 +123,13 @@ Subscription-based providers that authenticate via OAuth device flow (e.g. `chat
OpenKB ships a bundled web UI, served by the REST API at `/`. Install the API extra and start the server — no configuration needed:

```bash
pip install "openkb[api]"
openkb-api # serves the API + Workbench at http://127.0.0.1:8000/
pip install "openkb[web]"
openkb-web # serves the API + Workbench at http://127.0.0.1:7566/
```

Open `http://127.0.0.1:8000/` for the Workbench. Auth is off by default (local-first); set `OPENKB_API_TOKEN` to require a bearer token before exposing the server. See the [full Web UI guide](examples/rest-api/README.md#knowledge-workbench-web-ui).
Open `http://127.0.0.1:7566/` for the Workbench. Auth is off by default (local-first); set `OPENKB_API_TOKEN` to require a bearer token before exposing the server. See the [full Web UI guide](examples/rest-api/README.md#knowledge-workbench-web-ui).

> Working on the UI itself? Run the Vite dev server with `cd frontend && npm install && npm run dev` (it proxies `/api` to a running `openkb-api`), or `npm run build` to regenerate the bundled `openkb/web/`.
> Working on the UI itself? Run the Vite dev server with `cd frontend && npm install && npm run dev` (it proxies `/api` to a running `openkb-web`), or `npm run build` to regenerate the bundled `openkb/web/`.

# 🧩 How OpenKB Works

Expand DownExpand Up@@ -341,7 +341,7 @@ The skill is read-only. It won't run `openkb add`, `remove`, or `lint --fix` wit

# REST API

OpenKB ships a FastAPI service for HTTP clients. Install with `pip install -e ".[api]"`, then start with `python -m openkb.api`. The interactive API reference is at [`/docs`](http://127.0.0.1:8000/docs) (importable into Postman).
OpenKB ships a FastAPI service for HTTP clients. Install with `pip install -e ".[web]"`, then start with `python -m openkb.api`. The interactive API reference is at [`/docs`](http://127.0.0.1:7566/docs) (importable into Postman).

See the [full REST API reference](examples/rest-api/README.md#rest-api) for endpoints, auth, and SSE streaming.

Expand Down
20 changes: 10 additions & 10 deletions examples/rest-api/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@

This guide covers the OpenKB REST API (FastAPI) and the bundled Knowledge Workbench web UI.

> The interactive API reference is served live at [`/docs`](http://127.0.0.1:8000/docs) (OpenAPI/Swagger) once the server is running — you can import `/openapi.json` directly into Postman.
> The interactive API reference is served live at [`/docs`](http://127.0.0.1:7566/docs) (OpenAPI/Swagger) once the server is running — you can import `/openapi.json` directly into Postman.

## Knowledge Workbench (Web UI)

Expand All@@ -11,20 +11,20 @@ OpenKB ships a bundled web single-page app — the **Knowledge Workbench** — s

```bash
# 1. Install with the API extra (the built UI ships inside the package)
pip install "openkb[api]"
pip install "openkb[web]"

# 2. Start the server — no config needed for local use
openkb-api --host 127.0.0.1 --port 8000 # serves the API + Workbench at http://127.0.0.1:8000/
openkb-web --host 127.0.0.1 --port 7566 # serves the API + Workbench at http://127.0.0.1:7566/
```

Optional environment variables:

- `OPENKB_KB_ROOT` — where REST-created knowledge bases are stored (default `~/.config/openkb/kbs`).
- `OPENKB_API_TOKEN` — set it to require bearer auth (see [Authentication](#authentication-and-common-behavior)); leave unset for open local use.

> **From a source checkout?** The built bundle (`openkb/web/`) is git-ignored, so an editable install (`pip install -e ".[api]"`) has no UI until you build it once: `cd frontend && npm install && npm run build` (outputs to `openkb/web/`). Or run the Vite dev server with `npm run dev` (it proxies `/api` to a running `openkb-api`). Without the bundle, `openkb-api` serves only the REST API under `/api/v1` and `/` returns a 404.
> **From a source checkout?** The built bundle (`openkb/web/`) is git-ignored, so an editable install (`pip install -e ".[web]"`) has no UI until you build it once: `cd frontend && npm install && npm run build` (outputs to `openkb/web/`). Or run the Vite dev server with `npm run dev` (it proxies `/api` to a running `openkb-web`). Without the bundle, `openkb-web` serves only the REST API under `/api/v1` and `/` returns a 404.

Open `http://127.0.0.1:8000/` in your browser. With no `OPENKB_API_TOKEN` set it connects to the local API immediately — no prompt. (If a token is configured, a **Connection** dialog asks for it once and caches it in the browser; you can also open it manually to point the UI at a remote API base.) The Workbench then provides:
Open `http://127.0.0.1:7566/` in your browser. With no `OPENKB_API_TOKEN` set it connects to the local API immediately — no prompt. (If a token is configured, a **Connection** dialog asks for it once and caches it in the browser; you can also open it manually to point the UI at a remote API base.) The Workbench then provides:

- **Overview** — index/concept/summary/report stat cards, clickable concept chips, recent documents, and last-compile/lint activity.
- **Documents** — drag-and-drop multi-file upload with per-file SSE progress, hash table, and delete with confirmation.
Expand All@@ -44,15 +44,15 @@ frontends, or other HTTP clients.
Install the API dependencies if needed:

```bash
pip install -e ".[api]"
pip install -e ".[web]"
```

Start the API server:

```powershell
$env:OPENKB_API_TOKEN="test-token"
$env:OPENKB_KB_ROOT="D:\project\OpenKB\kbs"
.\.venv\Scripts\python.exe -m openkb.api --host 127.0.0.1 --port 8000
.\.venv\Scripts\python.exe -m openkb.api --host 127.0.0.1 --port 7566
```

### Authentication and common behavior
Expand All@@ -61,7 +61,7 @@ Auth is **opt-in**, controlled by the `OPENKB_API_TOKEN` server environment
variable:

- **Unset (default)** — the API is unauthenticated. This is the local-first
default, so `openkb-api` and the Workbench work with no configuration.
default, so `openkb-web` and the Workbench work with no configuration.
- **Set** — every request must carry the token, and the Workbench prompts for
it once (cached in the browser):

Expand All@@ -73,7 +73,7 @@ variable:

> **Exposing the server?** Always set `OPENKB_API_TOKEN` when binding to a
> non-loopback host (e.g. `--host 0.0.0.0`) — otherwise the API, and every KB
> it can reach, is world-open. `openkb-api` prints a warning in that case.
> it can reach, is world-open. `openkb-web` prints a warning in that case.

`OPENKB_KB_ROOT` is optional. It controls where REST-created knowledge bases
are stored. If unset, OpenKB uses `~/.config/openkb/kbs`.
Expand DownExpand Up@@ -419,4 +419,4 @@ no watcher is active for that KB.
stop after this many seconds). Stream events: `start`, the watcher's own events
(e.g. `added`, `updated`, `failed`, `final`), `error`, `done`.

The full OpenAPI schema is at [`/openapi.json`](http://127.0.0.1:8000/openapi.json) — importable into Postman or any OpenAPI-compatible client.
The full OpenAPI schema is at [`/openapi.json`](http://127.0.0.1:7566/openapi.json) — importable into Postman or any OpenAPI-compatible client.
2 changes: 1 addition & 1 deletion frontend/src/App.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -107,7 +107,7 @@ function ConnectionDialog({
<input
value={base}
onChange={(e) => setBase(e.target.value)}
placeholder="http://127.0.0.1:8000"
placeholder="http://127.0.0.1:7566"
className={inputCls}
/>
</div>
Expand Down
7 changes: 5 additions & 2 deletions frontend/src/components/ArtifactPanel.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -222,8 +222,11 @@ export default function ArtifactPanel({
className="absolute left-0 top-0 z-10 h-full w-1.5 -translate-x-1/2 cursor-col-resize hover:bg-accent-brand/30"
/>

{/* header */}
<div className="shrink-0 h-12 flex items-center gap-2 px-3 border-b border-[hsl(var(--glass-border))]">
{/* header — pr-28 reserves the global top-right chrome lane (theme + i18n
pills in App.tsx, absolute right-3 z-40) so the panel's action buttons
(open / download / close) never sit UNDER it. Same reserve convention
as KbList's header row and KbDetail's gear row. */}
<div className="shrink-0 h-12 flex items-center gap-2 pl-3 pr-28 border-b border-[hsl(var(--glass-border))]">
<HeaderIcon className="w-4 h-4 text-accent-brand shrink-0" />
<span className="min-w-0 truncate text-[13px] font-semibold text-foreground">
{artifactLabel(active, t)}
Expand Down
4 changes: 2 additions & 2 deletions frontend/vite.config.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ import path from "path"
import react from "@vitejs/plugin-react"
import { defineConfig } from "vite"

// Dev server proxies /api to the OpenKB REST API on :8000; production
// Dev server proxies /api to the OpenKB REST API on :7566; production
// serves the built bundle from the same origin via FastAPI StaticFiles.
// outDir MUST stay ../openkb/web — the wheel packages it from there
// (see pyproject.toml [tool.hatch.build] artifacts).
Expand All@@ -22,7 +22,7 @@ export default defineConfig({
port: 5173,
proxy: {
"/api": {
target: "http://127.0.0.1:8000",
target: "http://127.0.0.1:7566",
changeOrigin: true,
},
},
Expand Down
2 changes: 1 addition & 1 deletion openkb/api.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -776,7 +776,7 @@ async def api_not_found(path: str) -> Any:
def main() -> None:
parser = argparse.ArgumentParser(description="Run the OpenKB REST API.")
parser.add_argument("--host", default="127.0.0.1")
parser.add_argument("--port", type=int, default=8000)
parser.add_argument("--port", type=int, default=7566)
parser.add_argument("--reload", action="store_true")
args = parser.parse_args()

Expand Down
4 changes: 2 additions & 2 deletions openkb/api_helpers.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -69,8 +69,8 @@ def _configure_cors(app: FastAPI) -> None:
origins = [o.strip() for o in raw.split(",") if o.strip()] or [
"http://localhost:5173",
"http://127.0.0.1:5173",
"http://localhost:8000",
"http://127.0.0.1:8000",
"http://localhost:7566",
"http://127.0.0.1:7566",
]
# A wildcard origin with credentials is insecure: any site can issue
# credentialed cross-origin requests. Reject this combination by forcing
Expand Down
8 changes: 7 additions & 1 deletion pyproject.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -59,6 +59,8 @@ Issues = "https://github.com/VectifyAI/OpenKB/issues"

[project.scripts]
openkb = "openkb.cli:cli"
openkb-web = "openkb.api:main"
# Backwards-compatible alias for the historical name; same entry point.
openkb-api = "openkb.api:main"

[tool.pytest.ini_options]
Expand All@@ -73,7 +75,11 @@ dev = [
"mypy==1.15.0",
"types-PyYAML==6.0.12.20260518",
]
api = ["fastapi", "uvicorn", "python-multipart"]
# The Knowledge Workbench Web UI is served by this FastAPI server. `web` is the
# canonical extra; `api` is a backwards-compatible alias so an existing
# `pip install "openkb[api]"` keeps working.
web = ["fastapi", "uvicorn", "python-multipart"]
api = ["openkb[web]"]

[tool.hatch.version]
source = "vcs"
Expand Down
10 changes: 9 additions & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
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
10 changes: 5 additions & 5 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -123,13 +123,13 @@ Subscription-based providers that authenticate via OAuth device flow (e.g. `chat
OpenKB ships a bundled web UI, served by the REST API at `/`. Install the API extra and start the server — no configuration needed:

```bash
pip install "openkb[api]"
openkb-api # serves the API + Workbench at http://127.0.0.1:8000/
pip install "openkb[web]"
openkb-web # serves the API + Workbench at http://127.0.0.1:7566/
```

Open `http://127.0.0.1:8000/` for the Workbench. Auth is off by default (local-first); set `OPENKB_API_TOKEN` to require a bearer token before exposing the server. See the [full Web UI guide](examples/rest-api/README.md#knowledge-workbench-web-ui).
Open `http://127.0.0.1:7566/` for the Workbench. Auth is off by default (local-first); set `OPENKB_API_TOKEN` to require a bearer token before exposing the server. See the [full Web UI guide](examples/rest-api/README.md#knowledge-workbench-web-ui).

> Working on the UI itself? Run the Vite dev server with `cd frontend && npm install && npm run dev` (it proxies `/api` to a running `openkb-api`), or `npm run build` to regenerate the bundled `openkb/web/`.
> Working on the UI itself? Run the Vite dev server with `cd frontend && npm install && npm run dev` (it proxies `/api` to a running `openkb-web`), or `npm run build` to regenerate the bundled `openkb/web/`.

# 🧩 How OpenKB Works

Expand DownExpand Up@@ -341,7 +341,7 @@ The skill is read-only. It won't run `openkb add`, `remove`, or `lint --fix` wit

# REST API

OpenKB ships a FastAPI service for HTTP clients. Install with `pip install -e ".[api]"`, then start with `python -m openkb.api`. The interactive API reference is at [`/docs`](http://127.0.0.1:8000/docs) (importable into Postman).
OpenKB ships a FastAPI service for HTTP clients. Install with `pip install -e ".[web]"`, then start with `python -m openkb.api`. The interactive API reference is at [`/docs`](http://127.0.0.1:7566/docs) (importable into Postman).

See the [full REST API reference](examples/rest-api/README.md#rest-api) for endpoints, auth, and SSE streaming.

Expand Down
20 changes: 10 additions & 10 deletions examples/rest-api/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@

This guide covers the OpenKB REST API (FastAPI) and the bundled Knowledge Workbench web UI.

> The interactive API reference is served live at [`/docs`](http://127.0.0.1:8000/docs) (OpenAPI/Swagger) once the server is running — you can import `/openapi.json` directly into Postman.
> The interactive API reference is served live at [`/docs`](http://127.0.0.1:7566/docs) (OpenAPI/Swagger) once the server is running — you can import `/openapi.json` directly into Postman.

## Knowledge Workbench (Web UI)

Expand All@@ -11,20 +11,20 @@ OpenKB ships a bundled web single-page app — the **Knowledge Workbench** — s

```bash
# 1. Install with the API extra (the built UI ships inside the package)
pip install "openkb[api]"
pip install "openkb[web]"

# 2. Start the server — no config needed for local use
openkb-api --host 127.0.0.1 --port 8000 # serves the API + Workbench at http://127.0.0.1:8000/
openkb-web --host 127.0.0.1 --port 7566 # serves the API + Workbench at http://127.0.0.1:7566/
```

Optional environment variables:

- `OPENKB_KB_ROOT` — where REST-created knowledge bases are stored (default `~/.config/openkb/kbs`).
- `OPENKB_API_TOKEN` — set it to require bearer auth (see [Authentication](#authentication-and-common-behavior)); leave unset for open local use.

> **From a source checkout?** The built bundle (`openkb/web/`) is git-ignored, so an editable install (`pip install -e ".[api]"`) has no UI until you build it once: `cd frontend && npm install && npm run build` (outputs to `openkb/web/`). Or run the Vite dev server with `npm run dev` (it proxies `/api` to a running `openkb-api`). Without the bundle, `openkb-api` serves only the REST API under `/api/v1` and `/` returns a 404.
> **From a source checkout?** The built bundle (`openkb/web/`) is git-ignored, so an editable install (`pip install -e ".[web]"`) has no UI until you build it once: `cd frontend && npm install && npm run build` (outputs to `openkb/web/`). Or run the Vite dev server with `npm run dev` (it proxies `/api` to a running `openkb-web`). Without the bundle, `openkb-web` serves only the REST API under `/api/v1` and `/` returns a 404.

Open `http://127.0.0.1:8000/` in your browser. With no `OPENKB_API_TOKEN` set it connects to the local API immediately — no prompt. (If a token is configured, a **Connection** dialog asks for it once and caches it in the browser; you can also open it manually to point the UI at a remote API base.) The Workbench then provides:
Open `http://127.0.0.1:7566/` in your browser. With no `OPENKB_API_TOKEN` set it connects to the local API immediately — no prompt. (If a token is configured, a **Connection** dialog asks for it once and caches it in the browser; you can also open it manually to point the UI at a remote API base.) The Workbench then provides:

- **Overview** — index/concept/summary/report stat cards, clickable concept chips, recent documents, and last-compile/lint activity.
- **Documents** — drag-and-drop multi-file upload with per-file SSE progress, hash table, and delete with confirmation.
Expand All@@ -44,15 +44,15 @@ frontends, or other HTTP clients.
Install the API dependencies if needed:

```bash
pip install -e ".[api]"
pip install -e ".[web]"
```

Start the API server:

```powershell
$env:OPENKB_API_TOKEN="test-token"
$env:OPENKB_KB_ROOT="D:\project\OpenKB\kbs"
.\.venv\Scripts\python.exe -m openkb.api --host 127.0.0.1 --port 8000
.\.venv\Scripts\python.exe -m openkb.api --host 127.0.0.1 --port 7566
```

### Authentication and common behavior
Expand All@@ -61,7 +61,7 @@ Auth is **opt-in**, controlled by the `OPENKB_API_TOKEN` server environment
variable:

- **Unset (default)** — the API is unauthenticated. This is the local-first
default, so `openkb-api` and the Workbench work with no configuration.
default, so `openkb-web` and the Workbench work with no configuration.
- **Set** — every request must carry the token, and the Workbench prompts for
it once (cached in the browser):

Expand All@@ -73,7 +73,7 @@ variable:

> **Exposing the server?** Always set `OPENKB_API_TOKEN` when binding to a
> non-loopback host (e.g. `--host 0.0.0.0`) — otherwise the API, and every KB
> it can reach, is world-open. `openkb-api` prints a warning in that case.
> it can reach, is world-open. `openkb-web` prints a warning in that case.

`OPENKB_KB_ROOT` is optional. It controls where REST-created knowledge bases
are stored. If unset, OpenKB uses `~/.config/openkb/kbs`.
Expand DownExpand Up@@ -419,4 +419,4 @@ no watcher is active for that KB.
stop after this many seconds). Stream events: `start`, the watcher's own events
(e.g. `added`, `updated`, `failed`, `final`), `error`, `done`.

The full OpenAPI schema is at [`/openapi.json`](http://127.0.0.1:8000/openapi.json) — importable into Postman or any OpenAPI-compatible client.
The full OpenAPI schema is at [`/openapi.json`](http://127.0.0.1:7566/openapi.json) — importable into Postman or any OpenAPI-compatible client.
2 changes: 1 addition & 1 deletion frontend/src/App.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -107,7 +107,7 @@ function ConnectionDialog({
<input
value={base}
onChange={(e) => setBase(e.target.value)}
placeholder="http://127.0.0.1:8000"
placeholder="http://127.0.0.1:7566"
className={inputCls}
/>
</div>
Expand Down
7 changes: 5 additions & 2 deletions frontend/src/components/ArtifactPanel.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -222,8 +222,11 @@ export default function ArtifactPanel({
className="absolute left-0 top-0 z-10 h-full w-1.5 -translate-x-1/2 cursor-col-resize hover:bg-accent-brand/30"
/>

{/* header */}
<div className="shrink-0 h-12 flex items-center gap-2 px-3 border-b border-[hsl(var(--glass-border))]">
{/* header — pr-28 reserves the global top-right chrome lane (theme + i18n
pills in App.tsx, absolute right-3 z-40) so the panel's action buttons
(open / download / close) never sit UNDER it. Same reserve convention
as KbList's header row and KbDetail's gear row. */}
<div className="shrink-0 h-12 flex items-center gap-2 pl-3 pr-28 border-b border-[hsl(var(--glass-border))]">
<HeaderIcon className="w-4 h-4 text-accent-brand shrink-0" />
<span className="min-w-0 truncate text-[13px] font-semibold text-foreground">
{artifactLabel(active, t)}
Expand Down
4 changes: 2 additions & 2 deletions frontend/vite.config.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ import path from "path"
import react from "@vitejs/plugin-react"
import { defineConfig } from "vite"

// Dev server proxies /api to the OpenKB REST API on :8000; production
// Dev server proxies /api to the OpenKB REST API on :7566; production
// serves the built bundle from the same origin via FastAPI StaticFiles.
// outDir MUST stay ../openkb/web — the wheel packages it from there
// (see pyproject.toml [tool.hatch.build] artifacts).
Expand All@@ -22,7 +22,7 @@ export default defineConfig({
port: 5173,
proxy: {
"/api": {
target: "http://127.0.0.1:8000",
target: "http://127.0.0.1:7566",
changeOrigin: true,
},
},
Expand Down
2 changes: 1 addition & 1 deletion openkb/api.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -776,7 +776,7 @@ async def api_not_found(path: str) -> Any:
def main() -> None:
parser = argparse.ArgumentParser(description="Run the OpenKB REST API.")
parser.add_argument("--host", default="127.0.0.1")
parser.add_argument("--port", type=int, default=8000)
parser.add_argument("--port", type=int, default=7566)
parser.add_argument("--reload", action="store_true")
args = parser.parse_args()

Expand Down
4 changes: 2 additions & 2 deletions openkb/api_helpers.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -69,8 +69,8 @@ def _configure_cors(app: FastAPI) -> None:
origins = [o.strip() for o in raw.split(",") if o.strip()] or [
"http://localhost:5173",
"http://127.0.0.1:5173",
"http://localhost:8000",
"http://127.0.0.1:8000",
"http://localhost:7566",
"http://127.0.0.1:7566",
]
# A wildcard origin with credentials is insecure: any site can issue
# credentialed cross-origin requests. Reject this combination by forcing
Expand Down
8 changes: 7 additions & 1 deletion pyproject.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -59,6 +59,8 @@ Issues = "https://github.com/VectifyAI/OpenKB/issues"

[project.scripts]
openkb = "openkb.cli:cli"
openkb-web = "openkb.api:main"
# Backwards-compatible alias for the historical name; same entry point.
openkb-api = "openkb.api:main"

[tool.pytest.ini_options]
Expand All@@ -73,7 +75,11 @@ dev = [
"mypy==1.15.0",
"types-PyYAML==6.0.12.20260518",
]
api = ["fastapi", "uvicorn", "python-multipart"]
# The Knowledge Workbench Web UI is served by this FastAPI server. `web` is the
# canonical extra; `api` is a backwards-compatible alias so an existing
# `pip install "openkb[api]"` keeps working.
web = ["fastapi", "uvicorn", "python-multipart"]
api = ["openkb[web]"]

[tool.hatch.version]
source = "vcs"
Expand Down
10 changes: 9 additions & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading