zbook 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- zbook-0.1.0/.editorconfig +11 -0
- zbook-0.1.0/.gitattributes +1 -0
- zbook-0.1.0/.github/workflows/release.yml +115 -0
- zbook-0.1.0/.gitignore +9 -0
- zbook-0.1.0/LICENSE +21 -0
- zbook-0.1.0/PKG-INFO +170 -0
- zbook-0.1.0/README.md +146 -0
- zbook-0.1.0/frontend/index.html +13 -0
- zbook-0.1.0/frontend/package-lock.json +2819 -0
- zbook-0.1.0/frontend/package.json +35 -0
- zbook-0.1.0/frontend/public/font-licenses.txt +98 -0
- zbook-0.1.0/frontend/src/App.tsx +1874 -0
- zbook-0.1.0/frontend/src/components/CellEditor.tsx +132 -0
- zbook-0.1.0/frontend/src/components/CodexPanel.tsx +1261 -0
- zbook-0.1.0/frontend/src/components/CommandPalette.tsx +164 -0
- zbook-0.1.0/frontend/src/components/EnvironmentPanel.tsx +206 -0
- zbook-0.1.0/frontend/src/components/FileTree.tsx +201 -0
- zbook-0.1.0/frontend/src/components/Notebook.tsx +375 -0
- zbook-0.1.0/frontend/src/components/icons.tsx +81 -0
- zbook-0.1.0/frontend/src/editor/theme.ts +66 -0
- zbook-0.1.0/frontend/src/main.tsx +14 -0
- zbook-0.1.0/frontend/src/model/notebook.ts +143 -0
- zbook-0.1.0/frontend/src/model/notebookTools.ts +178 -0
- zbook-0.1.0/frontend/src/services/contents.ts +120 -0
- zbook-0.1.0/frontend/src/services/environment.ts +75 -0
- zbook-0.1.0/frontend/src/services/http.ts +76 -0
- zbook-0.1.0/frontend/src/services/kernel.ts +272 -0
- zbook-0.1.0/frontend/src/styles.css +781 -0
- zbook-0.1.0/frontend/src/vite-env.d.ts +1 -0
- zbook-0.1.0/frontend/tsconfig.json +21 -0
- zbook-0.1.0/frontend/vite.config.ts +17 -0
- zbook-0.1.0/pyproject.toml +60 -0
- zbook-0.1.0/src/zbook/__init__.py +24 -0
- zbook-0.1.0/src/zbook/__main__.py +4 -0
- zbook-0.1.0/src/zbook/app.py +210 -0
- zbook-0.1.0/src/zbook/cli.py +383 -0
- zbook-0.1.0/src/zbook/codex.py +446 -0
- zbook-0.1.0/src/zbook/codex_handler.py +655 -0
- zbook-0.1.0/src/zbook/config.py +79 -0
- zbook-0.1.0/src/zbook/environments.py +160 -0
- zbook-0.1.0/src/zbook/handlers.py +229 -0
- zbook-0.1.0/src/zbook/kernel_spec.py +84 -0
- zbook-0.1.0/src/zbook/static/assets/index-whrSZ2Mg.js +118 -0
- zbook-0.1.0/src/zbook/static/assets/index-xmz5a47X.css +1 -0
- zbook-0.1.0/src/zbook/static/assets/inter-cyrillic-ext-wght-italic-B5xAaiFk.woff2 +0 -0
- zbook-0.1.0/src/zbook/static/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
- zbook-0.1.0/src/zbook/static/assets/inter-cyrillic-wght-italic-DzZdc28x.woff2 +0 -0
- zbook-0.1.0/src/zbook/static/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
- zbook-0.1.0/src/zbook/static/assets/inter-greek-ext-wght-italic-DcOpz6Lw.woff2 +0 -0
- zbook-0.1.0/src/zbook/static/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
- zbook-0.1.0/src/zbook/static/assets/inter-greek-wght-italic-CILZdfAp.woff2 +0 -0
- zbook-0.1.0/src/zbook/static/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
- zbook-0.1.0/src/zbook/static/assets/inter-latin-ext-wght-italic-0pjOp8NU.woff2 +0 -0
- zbook-0.1.0/src/zbook/static/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
- zbook-0.1.0/src/zbook/static/assets/inter-latin-wght-italic-DpCbqKDY.woff2 +0 -0
- zbook-0.1.0/src/zbook/static/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
- zbook-0.1.0/src/zbook/static/assets/inter-vietnamese-wght-italic-K3WlGtc8.woff2 +0 -0
- zbook-0.1.0/src/zbook/static/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
- zbook-0.1.0/src/zbook/static/assets/jetbrains-mono-cyrillic-wght-italic-CfQkWpeR.woff2 +0 -0
- zbook-0.1.0/src/zbook/static/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
- zbook-0.1.0/src/zbook/static/assets/jetbrains-mono-greek-wght-italic-Dmq-fBVQ.woff2 +0 -0
- zbook-0.1.0/src/zbook/static/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
- zbook-0.1.0/src/zbook/static/assets/jetbrains-mono-latin-ext-wght-italic-BrDczivE.woff2 +0 -0
- zbook-0.1.0/src/zbook/static/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
- zbook-0.1.0/src/zbook/static/assets/jetbrains-mono-latin-wght-italic-B2M6KQje.woff2 +0 -0
- zbook-0.1.0/src/zbook/static/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
- zbook-0.1.0/src/zbook/static/assets/jetbrains-mono-vietnamese-wght-italic-Dcombn6O.woff2 +0 -0
- zbook-0.1.0/src/zbook/static/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
- zbook-0.1.0/src/zbook/static/font-licenses.txt +98 -0
- zbook-0.1.0/src/zbook/static/index.html +14 -0
- zbook-0.1.0/src/zbook/uv_env.py +185 -0
- zbook-0.1.0/tests/smoke_test.py +78 -0
- zbook-0.1.0/tests/test_cli.py +257 -0
- zbook-0.1.0/tests/test_codex_protocol.py +316 -0
- zbook-0.1.0/tests/test_config.py +68 -0
- zbook-0.1.0/tests/test_environments.py +81 -0
- zbook-0.1.0/tests/test_handlers.py +16 -0
- zbook-0.1.0/tests/test_uv_env.py +58 -0
- zbook-0.1.0/uv.lock +1232 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
src/zbook/static/assets/* -diff linguist-generated=true
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
name: Publish release to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v[0-9]+.[0-9]+.[0-9]+"
|
|
7
|
+
- "v[0-9]+.[0-9]+.[0-9]+rc[0-9]+"
|
|
8
|
+
- "v[0-9]+.[0-9]+.[0-9]+[ab][0-9]+"
|
|
9
|
+
|
|
10
|
+
concurrency:
|
|
11
|
+
group: pypi-${{ github.ref }}
|
|
12
|
+
cancel-in-progress: false
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
build:
|
|
16
|
+
name: Build and verify distributions
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
permissions:
|
|
19
|
+
contents: read
|
|
20
|
+
steps:
|
|
21
|
+
- name: Check out source
|
|
22
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
23
|
+
with:
|
|
24
|
+
persist-credentials: false
|
|
25
|
+
|
|
26
|
+
- name: Install uv
|
|
27
|
+
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
|
28
|
+
with:
|
|
29
|
+
enable-cache: false
|
|
30
|
+
version: "0.12.5"
|
|
31
|
+
|
|
32
|
+
- name: Install Node.js
|
|
33
|
+
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
|
34
|
+
with:
|
|
35
|
+
node-version: 24
|
|
36
|
+
cache: npm
|
|
37
|
+
cache-dependency-path: frontend/package-lock.json
|
|
38
|
+
|
|
39
|
+
- name: Verify release tag
|
|
40
|
+
shell: bash
|
|
41
|
+
run: |
|
|
42
|
+
package_version="$(uv version --short)"
|
|
43
|
+
if [[ "v${package_version}" != "${GITHUB_REF_NAME}" ]]; then
|
|
44
|
+
echo "::error::Tag ${GITHUB_REF_NAME} does not match package version ${package_version}"
|
|
45
|
+
exit 1
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
- name: Install Python dependencies
|
|
49
|
+
run: uv sync --locked --dev
|
|
50
|
+
|
|
51
|
+
- name: Check Python
|
|
52
|
+
run: uv run ruff check .
|
|
53
|
+
|
|
54
|
+
- name: Test Python
|
|
55
|
+
run: uv run pytest -q
|
|
56
|
+
|
|
57
|
+
- name: Build web client
|
|
58
|
+
working-directory: frontend
|
|
59
|
+
run: |
|
|
60
|
+
npm ci
|
|
61
|
+
npm run build
|
|
62
|
+
|
|
63
|
+
- name: Verify committed web client
|
|
64
|
+
shell: bash
|
|
65
|
+
run: |
|
|
66
|
+
if [[ -n "$(git status --porcelain -- src/zbook/static)" ]]; then
|
|
67
|
+
git status --short -- src/zbook/static
|
|
68
|
+
echo "::error::Frontend build output is not committed"
|
|
69
|
+
exit 1
|
|
70
|
+
fi
|
|
71
|
+
|
|
72
|
+
- name: Build wheel and source distribution
|
|
73
|
+
run: uv build --no-sources
|
|
74
|
+
|
|
75
|
+
- name: Smoke-test wheel
|
|
76
|
+
run: uv run --isolated --no-project --with dist/*.whl tests/smoke_test.py
|
|
77
|
+
|
|
78
|
+
- name: Smoke-test source distribution
|
|
79
|
+
run: uv run --isolated --no-project --with dist/*.tar.gz tests/smoke_test.py
|
|
80
|
+
|
|
81
|
+
- name: Upload distributions
|
|
82
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
83
|
+
with:
|
|
84
|
+
name: distributions
|
|
85
|
+
path: dist/
|
|
86
|
+
if-no-files-found: error
|
|
87
|
+
retention-days: 7
|
|
88
|
+
|
|
89
|
+
publish:
|
|
90
|
+
name: Publish to PyPI
|
|
91
|
+
needs: build
|
|
92
|
+
runs-on: ubuntu-latest
|
|
93
|
+
environment:
|
|
94
|
+
name: pypi
|
|
95
|
+
url: https://pypi.org/project/zbook/
|
|
96
|
+
permissions:
|
|
97
|
+
id-token: write
|
|
98
|
+
steps:
|
|
99
|
+
- name: Install uv
|
|
100
|
+
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
|
101
|
+
with:
|
|
102
|
+
enable-cache: false
|
|
103
|
+
version: "0.12.5"
|
|
104
|
+
|
|
105
|
+
- name: Download distributions
|
|
106
|
+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
107
|
+
with:
|
|
108
|
+
name: distributions
|
|
109
|
+
path: dist/
|
|
110
|
+
|
|
111
|
+
- name: Generate publish attestations
|
|
112
|
+
uses: astral-sh/attest-action@f589a42a7efb6fe400b4f400de60b4bc90390027 # v0.0.6
|
|
113
|
+
|
|
114
|
+
- name: Publish distributions
|
|
115
|
+
run: uv publish --trusted-publishing always dist/*
|
zbook-0.1.0/.gitignore
ADDED
zbook-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Zbook contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
zbook-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: zbook
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A small, keyboard-first notebook with uv and Codex integration
|
|
5
|
+
Project-URL: Homepage, https://github.com/honglu2875/zbook
|
|
6
|
+
Project-URL: Repository, https://github.com/honglu2875/zbook
|
|
7
|
+
Project-URL: Issues, https://github.com/honglu2875/zbook/issues
|
|
8
|
+
Author: honglu2875
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: codex,ipython,jupyter,notebook,uv
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Web Environment
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering
|
|
19
|
+
Requires-Python: >=3.11
|
|
20
|
+
Requires-Dist: jupyter-server<3,>=2.15
|
|
21
|
+
Requires-Dist: nbformat<6,>=5.10
|
|
22
|
+
Requires-Dist: traitlets<6,>=5.14
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
|
|
25
|
+
# Zbook
|
|
26
|
+
|
|
27
|
+
Zbook is an intentionally small, keyboard-first notebook application. It keeps the useful core of Jupyter—real `.ipynb` files, IPython kernels, markdown, rich outputs, and a workspace tree—then adds a first-class local Codex panel and a focused `uv` environment workflow.
|
|
28
|
+
|
|
29
|
+
The design target is closer to Zed than JupyterLab: flat surfaces, restrained color, minimal persistent chrome, fast keyboard navigation, and no extension ecosystem to carry.
|
|
30
|
+
|
|
31
|
+
## Working checkpoint
|
|
32
|
+
|
|
33
|
+
The main notebook loop is functional:
|
|
34
|
+
|
|
35
|
+
- the file tree is served by Jupyter's Contents API and is rooted at the configured workspace;
|
|
36
|
+
- notebooks can be created, opened in closable tabs, renamed inline by double-clicking a tab, deleted, uploaded, autosaved, and exported as `.ipynb`;
|
|
37
|
+
- open tabs, the active notebook, selected cell, panel visibility, and Vim preference are restored per workspace;
|
|
38
|
+
- `Ctrl/Cmd-P` opens a workspace file picker and `Ctrl/Cmd-Shift-P` opens the command palette;
|
|
39
|
+
- the workspace and Codex panes are draggable, keyboard-resizable, and remember their widths across reloads;
|
|
40
|
+
- refreshing the workspace also reloads the active notebook from disk (after confirming before discarding local unsaved changes);
|
|
41
|
+
- folders can be selected and created, and arbitrary files can be uploaded;
|
|
42
|
+
- code cells execute on a real IPython kernel with streamed text, errors, HTML, and PNG output;
|
|
43
|
+
- Markdown cells render in place; code and Markdown editors have syntax highlighting, bundled JetBrains Mono typography, and optional Vim bindings; the UI and prose use bundled Inter;
|
|
44
|
+
- long outputs can be height-limited from the gutter without shrinking their code, scaled images expand to their native resolution on double-click with two-axis scrolling, and `#@title …` gives a code cell a dedicated title row above its execution gutter and a whole-cell collapse toggle; these view preferences persist per workspace without changing the notebook file;
|
|
45
|
+
- **Run all**, execution counts, interrupt, and keyboard execution commands work;
|
|
46
|
+
- the environment panel lists packages and installs or uninstalls them through serialized `uv` operations;
|
|
47
|
+
- a fresh launch defaults to a scratch uv environment under `/tmp`, prepares `ipykernel`, and removes the scratch environment on shutdown;
|
|
48
|
+
- workspace `.venv` folders are detected and can be selected live; a project folder or uv-venv path can also be entered manually;
|
|
49
|
+
- the Codex panel uses the locally signed-in Codex CLI and ChatGPT subscription—no application API key—and streams turns through Codex App Server;
|
|
50
|
+
- Codex receives optional notebook/cell context and exposes live command/file activity plus any required approvals;
|
|
51
|
+
- Codex gets dedicated read/lock/apply cell tools: the read response advertises the current action inventory, relevant cells become visibly read-only across the full reasoning-and-editing turn, remaining locks release automatically at turn end, and edits are revision-checked, atomic, undoable, and saved without a shell/edit/refresh round trip; source-light reads plus `move_after` and `swap` operations make reordering inexpensive;
|
|
52
|
+
- each Codex cell edit gets an in-notebook review marker and a safe one-step undo until the notebook changes again;
|
|
53
|
+
- the Codex pane reads the installed CLI's model catalog and subscription rate limits, defaults to GPT-5.6-Luna with medium reasoning when available, and provides model/effort pickers, quota refresh, sign-in, and sign-out.
|
|
54
|
+
- Zbook-created Codex threads persist through App Server, are remembered per workspace, and can be resumed from the compact thread switcher with command/file/notebook activity restored and Zbook's private context augmentation kept out of the visible transcript.
|
|
55
|
+
|
|
56
|
+
This is still a focused checkpoint, not a JupyterLab replacement. Tabs share one workspace kernel and save before switching; non-notebook files are managed but not edited; and Jupyter widgets and arbitrary JavaScript outputs are not supported.
|
|
57
|
+
|
|
58
|
+
## Architecture
|
|
59
|
+
|
|
60
|
+
```text
|
|
61
|
+
React + CodeMirror 6
|
|
62
|
+
├─ Jupyter Contents / Kernel WebSocket APIs
|
|
63
|
+
├─ Zbook package-management API ── uv ── selected .venv
|
|
64
|
+
└─ Zbook Codex WebSocket ── codex app-server (stdio JSONL)
|
|
65
|
+
└─ dynamic cell tools ── revision-locked React notebook state
|
|
66
|
+
|
|
67
|
+
Jupyter Server ExtensionApp
|
|
68
|
+
├─ file boundary: configured workspace
|
|
69
|
+
├─ kernel: exact <venv>/bin/python
|
|
70
|
+
└─ static production frontend
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Python owns processes, filesystem boundaries, and Jupyter integration. TypeScript owns interaction state and rendering. The selected notebook environment is deliberately separate from the app's own environment so installing a package cannot destabilize the server. Codex runs with workspace-write scope, while commands that need broader filesystem or network access still use the CLI's approval flow. The bridge follows the official [Codex App Server](https://developers.openai.com/codex/app-server) protocol over a private authenticated WebSocket.
|
|
74
|
+
|
|
75
|
+
## Run the checks
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
uv run ruff check src tests
|
|
79
|
+
uv run pytest -q
|
|
80
|
+
cd frontend && npm run build
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Build the web client
|
|
84
|
+
|
|
85
|
+
Use Node.js 20.19 or newer:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
cd frontend
|
|
89
|
+
npm install
|
|
90
|
+
npm run build
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The Vite build is emitted into `src/zbook/static/`, where the Python application serves it.
|
|
94
|
+
|
|
95
|
+
## Install and launch
|
|
96
|
+
|
|
97
|
+
Build the web client once, then install the local package as a uv tool:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
uv sync --dev
|
|
101
|
+
cd frontend && npm install && npm run build && cd ..
|
|
102
|
+
uv tool install .
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
The installed command has a small preflight check and a dedicated launch command:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
zbook check
|
|
109
|
+
zbook run
|
|
110
|
+
zbook run --workspace-dir /absolute/path/to/workspace
|
|
111
|
+
zbook run --ip 0.0.0.0 --port 8888
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
`zbook run` uses the current directory as its workspace and listens only on Jupyter's `localhost` default. Binding a wildcard or non-loopback address prints a highlighted security warning: remote clients that obtain access can execute notebook code and reach the selected workspace and Codex. `0.0.0.0` listens on every network interface, though actual reachability still depends on the host firewall and network configuration. Keep Jupyter authentication enabled.
|
|
115
|
+
|
|
116
|
+
The default kernel environment is a disposable uv venv under `/tmp`; a persistent uv environment can be selected from the environment panel while the app is running.
|
|
117
|
+
|
|
118
|
+
Jupyter Server options go after a `--` passthrough boundary:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
zbook run --workspace-dir /absolute/path/to/workspace --port 8890 -- \
|
|
122
|
+
--ServerApp.open_browser=False
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Startup environment traits can be passed the same way when needed:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
zbook run --workspace-dir /absolute/path/to/workspace -- \
|
|
129
|
+
--ZbookApp.venv=/absolute/path/to/project/.venv
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
For compatibility, Jupyter flags supplied without `--` are still forwarded, but Zbook prints a highlighted warning showing the preferred form. The old direct form (`zbook --ZbookApp.workspace=…`) also remains available with a migration warning. During development, prefix these commands with `uv run`, such as `uv run zbook check`.
|
|
133
|
+
|
|
134
|
+
## Releasing
|
|
135
|
+
|
|
136
|
+
Releases are built and published by `.github/workflows/release.yml` through PyPI Trusted Publishing. The PyPI publisher must match the `honglu2875/zbook` repository, the `release.yml` workflow, and the `pypi` GitHub environment.
|
|
137
|
+
|
|
138
|
+
For the first release, tag the current `0.1.0` commit after configuring the `pypi` environment and pending PyPI publisher:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
git tag -a v0.1.0 -m "zbook 0.1.0"
|
|
142
|
+
git push origin v0.1.0
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
For subsequent releases, update the sole package-version source in `pyproject.toml`, review the lockfile, commit, and push the matching tag:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
uv version 0.1.1
|
|
149
|
+
git add pyproject.toml uv.lock
|
|
150
|
+
git commit -m "Release 0.1.1"
|
|
151
|
+
git tag -a v0.1.1 -m "zbook 0.1.1"
|
|
152
|
+
git push origin main v0.1.1
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
The workflow rejects a tag that does not match the package version, rebuilds and verifies the committed web client, tests both distribution formats in isolated environments, and grants the publishing credential only to the final PyPI job. Published PyPI versions cannot be replaced; use a new version for every changed release.
|
|
156
|
+
|
|
157
|
+
## Notebook key model
|
|
158
|
+
|
|
159
|
+
- `Shift-Escape` leaves an editor and enters notebook navigation mode.
|
|
160
|
+
- `j` / `k` or the arrow keys move between cells in navigation mode.
|
|
161
|
+
- `Enter` or `i` edits the selected cell.
|
|
162
|
+
- `a` inserts a code cell above; `b` or `o` inserts one below. Hover or keyboard-focus the space between cells to choose Code or Markdown explicitly.
|
|
163
|
+
- `Ctrl-Enter` runs in place, `Shift-Enter` runs and advances, and `Alt-Enter` runs and inserts.
|
|
164
|
+
- Vim bindings can be toggled from the status bar. Vim receives its keymap before the standard CodeMirror keymaps.
|
|
165
|
+
|
|
166
|
+
This two-level model avoids the classic conflict between Vim's modes and notebook-level commands: notebook navigation is a separate outer mode, and Vim operates only inside the active editor.
|
|
167
|
+
|
|
168
|
+
## License
|
|
169
|
+
|
|
170
|
+
Zbook is released under the [MIT License](LICENSE). The bundled Inter and JetBrains Mono fonts remain under the SIL Open Font License 1.1; their [notices](frontend/public/font-licenses.txt) ship with the frontend.
|
zbook-0.1.0/README.md
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# Zbook
|
|
2
|
+
|
|
3
|
+
Zbook is an intentionally small, keyboard-first notebook application. It keeps the useful core of Jupyter—real `.ipynb` files, IPython kernels, markdown, rich outputs, and a workspace tree—then adds a first-class local Codex panel and a focused `uv` environment workflow.
|
|
4
|
+
|
|
5
|
+
The design target is closer to Zed than JupyterLab: flat surfaces, restrained color, minimal persistent chrome, fast keyboard navigation, and no extension ecosystem to carry.
|
|
6
|
+
|
|
7
|
+
## Working checkpoint
|
|
8
|
+
|
|
9
|
+
The main notebook loop is functional:
|
|
10
|
+
|
|
11
|
+
- the file tree is served by Jupyter's Contents API and is rooted at the configured workspace;
|
|
12
|
+
- notebooks can be created, opened in closable tabs, renamed inline by double-clicking a tab, deleted, uploaded, autosaved, and exported as `.ipynb`;
|
|
13
|
+
- open tabs, the active notebook, selected cell, panel visibility, and Vim preference are restored per workspace;
|
|
14
|
+
- `Ctrl/Cmd-P` opens a workspace file picker and `Ctrl/Cmd-Shift-P` opens the command palette;
|
|
15
|
+
- the workspace and Codex panes are draggable, keyboard-resizable, and remember their widths across reloads;
|
|
16
|
+
- refreshing the workspace also reloads the active notebook from disk (after confirming before discarding local unsaved changes);
|
|
17
|
+
- folders can be selected and created, and arbitrary files can be uploaded;
|
|
18
|
+
- code cells execute on a real IPython kernel with streamed text, errors, HTML, and PNG output;
|
|
19
|
+
- Markdown cells render in place; code and Markdown editors have syntax highlighting, bundled JetBrains Mono typography, and optional Vim bindings; the UI and prose use bundled Inter;
|
|
20
|
+
- long outputs can be height-limited from the gutter without shrinking their code, scaled images expand to their native resolution on double-click with two-axis scrolling, and `#@title …` gives a code cell a dedicated title row above its execution gutter and a whole-cell collapse toggle; these view preferences persist per workspace without changing the notebook file;
|
|
21
|
+
- **Run all**, execution counts, interrupt, and keyboard execution commands work;
|
|
22
|
+
- the environment panel lists packages and installs or uninstalls them through serialized `uv` operations;
|
|
23
|
+
- a fresh launch defaults to a scratch uv environment under `/tmp`, prepares `ipykernel`, and removes the scratch environment on shutdown;
|
|
24
|
+
- workspace `.venv` folders are detected and can be selected live; a project folder or uv-venv path can also be entered manually;
|
|
25
|
+
- the Codex panel uses the locally signed-in Codex CLI and ChatGPT subscription—no application API key—and streams turns through Codex App Server;
|
|
26
|
+
- Codex receives optional notebook/cell context and exposes live command/file activity plus any required approvals;
|
|
27
|
+
- Codex gets dedicated read/lock/apply cell tools: the read response advertises the current action inventory, relevant cells become visibly read-only across the full reasoning-and-editing turn, remaining locks release automatically at turn end, and edits are revision-checked, atomic, undoable, and saved without a shell/edit/refresh round trip; source-light reads plus `move_after` and `swap` operations make reordering inexpensive;
|
|
28
|
+
- each Codex cell edit gets an in-notebook review marker and a safe one-step undo until the notebook changes again;
|
|
29
|
+
- the Codex pane reads the installed CLI's model catalog and subscription rate limits, defaults to GPT-5.6-Luna with medium reasoning when available, and provides model/effort pickers, quota refresh, sign-in, and sign-out.
|
|
30
|
+
- Zbook-created Codex threads persist through App Server, are remembered per workspace, and can be resumed from the compact thread switcher with command/file/notebook activity restored and Zbook's private context augmentation kept out of the visible transcript.
|
|
31
|
+
|
|
32
|
+
This is still a focused checkpoint, not a JupyterLab replacement. Tabs share one workspace kernel and save before switching; non-notebook files are managed but not edited; and Jupyter widgets and arbitrary JavaScript outputs are not supported.
|
|
33
|
+
|
|
34
|
+
## Architecture
|
|
35
|
+
|
|
36
|
+
```text
|
|
37
|
+
React + CodeMirror 6
|
|
38
|
+
├─ Jupyter Contents / Kernel WebSocket APIs
|
|
39
|
+
├─ Zbook package-management API ── uv ── selected .venv
|
|
40
|
+
└─ Zbook Codex WebSocket ── codex app-server (stdio JSONL)
|
|
41
|
+
└─ dynamic cell tools ── revision-locked React notebook state
|
|
42
|
+
|
|
43
|
+
Jupyter Server ExtensionApp
|
|
44
|
+
├─ file boundary: configured workspace
|
|
45
|
+
├─ kernel: exact <venv>/bin/python
|
|
46
|
+
└─ static production frontend
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Python owns processes, filesystem boundaries, and Jupyter integration. TypeScript owns interaction state and rendering. The selected notebook environment is deliberately separate from the app's own environment so installing a package cannot destabilize the server. Codex runs with workspace-write scope, while commands that need broader filesystem or network access still use the CLI's approval flow. The bridge follows the official [Codex App Server](https://developers.openai.com/codex/app-server) protocol over a private authenticated WebSocket.
|
|
50
|
+
|
|
51
|
+
## Run the checks
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
uv run ruff check src tests
|
|
55
|
+
uv run pytest -q
|
|
56
|
+
cd frontend && npm run build
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Build the web client
|
|
60
|
+
|
|
61
|
+
Use Node.js 20.19 or newer:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
cd frontend
|
|
65
|
+
npm install
|
|
66
|
+
npm run build
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
The Vite build is emitted into `src/zbook/static/`, where the Python application serves it.
|
|
70
|
+
|
|
71
|
+
## Install and launch
|
|
72
|
+
|
|
73
|
+
Build the web client once, then install the local package as a uv tool:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
uv sync --dev
|
|
77
|
+
cd frontend && npm install && npm run build && cd ..
|
|
78
|
+
uv tool install .
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The installed command has a small preflight check and a dedicated launch command:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
zbook check
|
|
85
|
+
zbook run
|
|
86
|
+
zbook run --workspace-dir /absolute/path/to/workspace
|
|
87
|
+
zbook run --ip 0.0.0.0 --port 8888
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
`zbook run` uses the current directory as its workspace and listens only on Jupyter's `localhost` default. Binding a wildcard or non-loopback address prints a highlighted security warning: remote clients that obtain access can execute notebook code and reach the selected workspace and Codex. `0.0.0.0` listens on every network interface, though actual reachability still depends on the host firewall and network configuration. Keep Jupyter authentication enabled.
|
|
91
|
+
|
|
92
|
+
The default kernel environment is a disposable uv venv under `/tmp`; a persistent uv environment can be selected from the environment panel while the app is running.
|
|
93
|
+
|
|
94
|
+
Jupyter Server options go after a `--` passthrough boundary:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
zbook run --workspace-dir /absolute/path/to/workspace --port 8890 -- \
|
|
98
|
+
--ServerApp.open_browser=False
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Startup environment traits can be passed the same way when needed:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
zbook run --workspace-dir /absolute/path/to/workspace -- \
|
|
105
|
+
--ZbookApp.venv=/absolute/path/to/project/.venv
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
For compatibility, Jupyter flags supplied without `--` are still forwarded, but Zbook prints a highlighted warning showing the preferred form. The old direct form (`zbook --ZbookApp.workspace=…`) also remains available with a migration warning. During development, prefix these commands with `uv run`, such as `uv run zbook check`.
|
|
109
|
+
|
|
110
|
+
## Releasing
|
|
111
|
+
|
|
112
|
+
Releases are built and published by `.github/workflows/release.yml` through PyPI Trusted Publishing. The PyPI publisher must match the `honglu2875/zbook` repository, the `release.yml` workflow, and the `pypi` GitHub environment.
|
|
113
|
+
|
|
114
|
+
For the first release, tag the current `0.1.0` commit after configuring the `pypi` environment and pending PyPI publisher:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
git tag -a v0.1.0 -m "zbook 0.1.0"
|
|
118
|
+
git push origin v0.1.0
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
For subsequent releases, update the sole package-version source in `pyproject.toml`, review the lockfile, commit, and push the matching tag:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
uv version 0.1.1
|
|
125
|
+
git add pyproject.toml uv.lock
|
|
126
|
+
git commit -m "Release 0.1.1"
|
|
127
|
+
git tag -a v0.1.1 -m "zbook 0.1.1"
|
|
128
|
+
git push origin main v0.1.1
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
The workflow rejects a tag that does not match the package version, rebuilds and verifies the committed web client, tests both distribution formats in isolated environments, and grants the publishing credential only to the final PyPI job. Published PyPI versions cannot be replaced; use a new version for every changed release.
|
|
132
|
+
|
|
133
|
+
## Notebook key model
|
|
134
|
+
|
|
135
|
+
- `Shift-Escape` leaves an editor and enters notebook navigation mode.
|
|
136
|
+
- `j` / `k` or the arrow keys move between cells in navigation mode.
|
|
137
|
+
- `Enter` or `i` edits the selected cell.
|
|
138
|
+
- `a` inserts a code cell above; `b` or `o` inserts one below. Hover or keyboard-focus the space between cells to choose Code or Markdown explicitly.
|
|
139
|
+
- `Ctrl-Enter` runs in place, `Shift-Enter` runs and advances, and `Alt-Enter` runs and inserts.
|
|
140
|
+
- Vim bindings can be toggled from the status bar. Vim receives its keymap before the standard CodeMirror keymaps.
|
|
141
|
+
|
|
142
|
+
This two-level model avoids the classic conflict between Vim's modes and notebook-level commands: notebook navigation is a separate outer mode, and Vim operates only inside the active editor.
|
|
143
|
+
|
|
144
|
+
## License
|
|
145
|
+
|
|
146
|
+
Zbook is released under the [MIT License](LICENSE). The bundled Inter and JetBrains Mono fonts remain under the SIL Open Font License 1.1; their [notices](frontend/public/font-licenses.txt) ship with the frontend.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<meta name="theme-color" content="#17191b" />
|
|
7
|
+
<title>Zbook</title>
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<div id="root"></div>
|
|
11
|
+
<script type="module" src="/src/main.tsx"></script>
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|