kctl-outline 0.6.1__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.
- kctl_outline-0.6.1/.gitignore +33 -0
- kctl_outline-0.6.1/PKG-INFO +145 -0
- kctl_outline-0.6.1/README.md +116 -0
- kctl_outline-0.6.1/pyproject.toml +62 -0
- kctl_outline-0.6.1/skills/outline-admin/SKILL.md +158 -0
- kctl_outline-0.6.1/src/kctl_outline/__init__.py +3 -0
- kctl_outline-0.6.1/src/kctl_outline/__main__.py +5 -0
- kctl_outline-0.6.1/src/kctl_outline/cli.py +120 -0
- kctl_outline-0.6.1/src/kctl_outline/commands/__init__.py +0 -0
- kctl_outline-0.6.1/src/kctl_outline/commands/attachments.py +95 -0
- kctl_outline-0.6.1/src/kctl_outline/commands/collections.py +195 -0
- kctl_outline-0.6.1/src/kctl_outline/commands/comments.py +74 -0
- kctl_outline-0.6.1/src/kctl_outline/commands/config_cmd.py +490 -0
- kctl_outline-0.6.1/src/kctl_outline/commands/dashboard.py +141 -0
- kctl_outline-0.6.1/src/kctl_outline/commands/doctor_cmd.py +72 -0
- kctl_outline-0.6.1/src/kctl_outline/commands/documents.py +279 -0
- kctl_outline-0.6.1/src/kctl_outline/commands/events.py +78 -0
- kctl_outline-0.6.1/src/kctl_outline/commands/groups.py +152 -0
- kctl_outline-0.6.1/src/kctl_outline/commands/health.py +155 -0
- kctl_outline-0.6.1/src/kctl_outline/commands/revisions.py +73 -0
- kctl_outline-0.6.1/src/kctl_outline/commands/search.py +43 -0
- kctl_outline-0.6.1/src/kctl_outline/commands/shares.py +99 -0
- kctl_outline-0.6.1/src/kctl_outline/commands/stars.py +62 -0
- kctl_outline-0.6.1/src/kctl_outline/commands/sync.py +543 -0
- kctl_outline-0.6.1/src/kctl_outline/commands/templates.py +107 -0
- kctl_outline-0.6.1/src/kctl_outline/commands/tokens.py +80 -0
- kctl_outline-0.6.1/src/kctl_outline/commands/users.py +152 -0
- kctl_outline-0.6.1/src/kctl_outline/core/__init__.py +0 -0
- kctl_outline-0.6.1/src/kctl_outline/core/callbacks.py +42 -0
- kctl_outline-0.6.1/src/kctl_outline/core/client.py +104 -0
- kctl_outline-0.6.1/src/kctl_outline/core/config.py +219 -0
- kctl_outline-0.6.1/src/kctl_outline/core/exceptions.py +52 -0
- kctl_outline-0.6.1/src/kctl_outline/core/output.py +125 -0
- kctl_outline-0.6.1/src/kctl_outline/core/sync_config.py +106 -0
- kctl_outline-0.6.1/src/kctl_outline/core/sync_planner.py +171 -0
- kctl_outline-0.6.1/src/kctl_outline/core/sync_pull.py +199 -0
- kctl_outline-0.6.1/src/kctl_outline/core/sync_ssot.py +40 -0
- kctl_outline-0.6.1/src/kctl_outline/core/sync_state.py +127 -0
- kctl_outline-0.6.1/tests/__init__.py +0 -0
- kctl_outline-0.6.1/tests/conftest.py +156 -0
- kctl_outline-0.6.1/tests/test_sync_config.py +113 -0
- kctl_outline-0.6.1/tests/test_sync_planner.py +132 -0
- kctl_outline-0.6.1/tests/test_sync_pull.py +194 -0
- kctl_outline-0.6.1/tests/test_sync_run_integration.py +92 -0
- kctl_outline-0.6.1/tests/test_sync_ssot.py +50 -0
- kctl_outline-0.6.1/tests/test_sync_state_migration.py +111 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
*.egg
|
|
6
|
+
dist/
|
|
7
|
+
build/
|
|
8
|
+
.eggs/
|
|
9
|
+
|
|
10
|
+
# Virtual environments
|
|
11
|
+
.venv/
|
|
12
|
+
venv/
|
|
13
|
+
|
|
14
|
+
# IDE
|
|
15
|
+
.idea/
|
|
16
|
+
.vscode/
|
|
17
|
+
*.swp
|
|
18
|
+
*.swo
|
|
19
|
+
|
|
20
|
+
# Testing
|
|
21
|
+
.pytest_cache/
|
|
22
|
+
.coverage
|
|
23
|
+
htmlcov/
|
|
24
|
+
.mypy_cache/
|
|
25
|
+
.ruff_cache/
|
|
26
|
+
|
|
27
|
+
# OS
|
|
28
|
+
.DS_Store
|
|
29
|
+
Thumbs.db
|
|
30
|
+
|
|
31
|
+
# Environment
|
|
32
|
+
.env
|
|
33
|
+
.env.local
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: kctl-outline
|
|
3
|
+
Version: 0.6.1
|
|
4
|
+
Summary: Kodemeio Outline CLI — manage Outline wiki instances and sync markdown docs
|
|
5
|
+
Author-email: Kodemeio <dev@kodeme.io>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Keywords: cli,knowledge-base,kodemeio,outline,wiki
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Environment :: Console
|
|
10
|
+
Classifier: Intended Audience :: System Administrators
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Classifier: Topic :: System :: Systems Administration
|
|
15
|
+
Requires-Python: >=3.12
|
|
16
|
+
Requires-Dist: httpx>=0.28.0
|
|
17
|
+
Requires-Dist: kctl-lib>=0.7.0
|
|
18
|
+
Requires-Dist: pydantic>=2.10.0
|
|
19
|
+
Requires-Dist: pyyaml>=6.0.2
|
|
20
|
+
Requires-Dist: rich>=13.9.0
|
|
21
|
+
Requires-Dist: typer>=0.15.0
|
|
22
|
+
Provides-Extra: dev
|
|
23
|
+
Requires-Dist: mypy>=1.14.0; extra == 'dev'
|
|
24
|
+
Requires-Dist: pytest-httpx>=0.35.0; extra == 'dev'
|
|
25
|
+
Requires-Dist: pytest>=8.3.0; extra == 'dev'
|
|
26
|
+
Requires-Dist: ruff>=0.9.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: types-pyyaml>=6.0.0; extra == 'dev'
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# kctl-outline
|
|
31
|
+
|
|
32
|
+
Kodemeio Outline CLI — manages Outline wiki instances and syncs markdown documentation between git repositories and one or more Outline collections.
|
|
33
|
+
|
|
34
|
+
## Install
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
cd packages/kctl-outline
|
|
38
|
+
uv sync --extra dev
|
|
39
|
+
uv run kctl-outline --help
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Or via the workspace from the repo root:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
uv sync
|
|
46
|
+
uv run --package kctl-outline kctl-outline --help
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Configuration
|
|
50
|
+
|
|
51
|
+
Like other `kctl-*` tools, configuration lives at `~/.config/kodemeio/config.yaml`. Each profile may declare an `outline` service block:
|
|
52
|
+
|
|
53
|
+
```yaml
|
|
54
|
+
profiles:
|
|
55
|
+
kod:
|
|
56
|
+
outline:
|
|
57
|
+
url: https://outline.kodeme.io
|
|
58
|
+
token: env:OUTLINE_API_TOKEN_KOD
|
|
59
|
+
tpp:
|
|
60
|
+
outline:
|
|
61
|
+
url: https://outline.idtpp.com
|
|
62
|
+
token: env:OUTLINE_API_TOKEN_TPP
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Add a profile interactively:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
kctl-outline config init
|
|
69
|
+
kctl-outline config add tpp --url https://outline.idtpp.com --token <TOKEN>
|
|
70
|
+
kctl-outline config use kod
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Commands
|
|
74
|
+
|
|
75
|
+
| Group | Purpose |
|
|
76
|
+
|---|---|
|
|
77
|
+
| `documents` | List, create, update, delete, move documents |
|
|
78
|
+
| `collections` | Manage collections |
|
|
79
|
+
| `users`, `groups` | User and group management |
|
|
80
|
+
| `shares` | Public share links |
|
|
81
|
+
| `comments`, `events`, `revisions` | Read-only metadata |
|
|
82
|
+
| `templates`, `stars`, `tokens` | Misc admin |
|
|
83
|
+
| `health`, `dashboard`, `doctor` | Diagnostics (`doctor` checks URL + auth config) |
|
|
84
|
+
| `search` | Search across documents |
|
|
85
|
+
| `sync` | **Sync markdown docs between repos and Outline (see below)** |
|
|
86
|
+
|
|
87
|
+
## Sync subcommand
|
|
88
|
+
|
|
89
|
+
`kctl-outline sync` is the primary integration point with `kodemeio-docs`. It supports multi-mapping configs (`.outline-sync.yaml` v2) with three direction modes:
|
|
90
|
+
|
|
91
|
+
- **`push`** — git is the source of truth. Markdown files are pushed to Outline.
|
|
92
|
+
- **`pull`** — Outline is the source of truth. Documents are pulled into the repo.
|
|
93
|
+
- **`mixed`** — per-file `.ssot` markers decide direction.
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
# Dry-run a sync from a repo
|
|
97
|
+
kctl-outline sync run /path/to/kodemeio-docs --config .outline-sync.kod.yaml
|
|
98
|
+
|
|
99
|
+
# Apply
|
|
100
|
+
kctl-outline sync run /path/to/kodemeio-docs --config .outline-sync.kod.yaml --no-dry-run
|
|
101
|
+
|
|
102
|
+
# Filter to a specific direction
|
|
103
|
+
kctl-outline sync run . --config .outline-sync.kod.yaml --mode push --no-dry-run
|
|
104
|
+
|
|
105
|
+
# Inspect tracked state
|
|
106
|
+
kctl-outline sync status
|
|
107
|
+
kctl-outline sync diff /path/to/repo
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
The full spec lives in `kodemeio-docs/superpowers/specs/2026-04-10-docs-outline-restructure-design.md`.
|
|
111
|
+
|
|
112
|
+
## Profile-aware sync routing
|
|
113
|
+
|
|
114
|
+
When a sync config declares `profile: tpp`, `kctl-outline sync run` builds a fresh client using that profile's URL and token, regardless of the active CLI profile. This means the same machine can push to both `outline.kodeme.io` and `outline.idtpp.com` without switching profiles between commands.
|
|
115
|
+
|
|
116
|
+
## Layout
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
packages/kctl-outline/
|
|
120
|
+
├── pyproject.toml
|
|
121
|
+
├── README.md
|
|
122
|
+
├── src/kctl_outline/
|
|
123
|
+
│ ├── cli.py # Typer entry point
|
|
124
|
+
│ ├── commands/ # one module per Outline subresource
|
|
125
|
+
│ │ ├── sync.py # the Plan A/D sync subcommand
|
|
126
|
+
│ │ ├── documents.py
|
|
127
|
+
│ │ ├── collections.py
|
|
128
|
+
│ │ └── …
|
|
129
|
+
│ └── core/
|
|
130
|
+
│ ├── client.py # httpx wrapper
|
|
131
|
+
│ ├── config.py # profile resolution
|
|
132
|
+
│ ├── sync_config.py # SyncConfig v2 schema + v1 auto-upgrade
|
|
133
|
+
│ ├── sync_planner.py # pure plan_push_mapping
|
|
134
|
+
│ ├── sync_pull.py # pull direction (Outline → disk)
|
|
135
|
+
│ ├── sync_state.py # MappingSyncEntry + v1→v2 migration
|
|
136
|
+
│ └── sync_ssot.py # .ssot marker walker
|
|
137
|
+
└── tests/ # 30+ tests (pytest)
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Tests
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
cd packages/kctl-outline
|
|
144
|
+
uv run --extra dev pytest tests/ -v
|
|
145
|
+
```
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# kctl-outline
|
|
2
|
+
|
|
3
|
+
Kodemeio Outline CLI — manages Outline wiki instances and syncs markdown documentation between git repositories and one or more Outline collections.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
cd packages/kctl-outline
|
|
9
|
+
uv sync --extra dev
|
|
10
|
+
uv run kctl-outline --help
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or via the workspace from the repo root:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
uv sync
|
|
17
|
+
uv run --package kctl-outline kctl-outline --help
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Configuration
|
|
21
|
+
|
|
22
|
+
Like other `kctl-*` tools, configuration lives at `~/.config/kodemeio/config.yaml`. Each profile may declare an `outline` service block:
|
|
23
|
+
|
|
24
|
+
```yaml
|
|
25
|
+
profiles:
|
|
26
|
+
kod:
|
|
27
|
+
outline:
|
|
28
|
+
url: https://outline.kodeme.io
|
|
29
|
+
token: env:OUTLINE_API_TOKEN_KOD
|
|
30
|
+
tpp:
|
|
31
|
+
outline:
|
|
32
|
+
url: https://outline.idtpp.com
|
|
33
|
+
token: env:OUTLINE_API_TOKEN_TPP
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Add a profile interactively:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
kctl-outline config init
|
|
40
|
+
kctl-outline config add tpp --url https://outline.idtpp.com --token <TOKEN>
|
|
41
|
+
kctl-outline config use kod
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Commands
|
|
45
|
+
|
|
46
|
+
| Group | Purpose |
|
|
47
|
+
|---|---|
|
|
48
|
+
| `documents` | List, create, update, delete, move documents |
|
|
49
|
+
| `collections` | Manage collections |
|
|
50
|
+
| `users`, `groups` | User and group management |
|
|
51
|
+
| `shares` | Public share links |
|
|
52
|
+
| `comments`, `events`, `revisions` | Read-only metadata |
|
|
53
|
+
| `templates`, `stars`, `tokens` | Misc admin |
|
|
54
|
+
| `health`, `dashboard`, `doctor` | Diagnostics (`doctor` checks URL + auth config) |
|
|
55
|
+
| `search` | Search across documents |
|
|
56
|
+
| `sync` | **Sync markdown docs between repos and Outline (see below)** |
|
|
57
|
+
|
|
58
|
+
## Sync subcommand
|
|
59
|
+
|
|
60
|
+
`kctl-outline sync` is the primary integration point with `kodemeio-docs`. It supports multi-mapping configs (`.outline-sync.yaml` v2) with three direction modes:
|
|
61
|
+
|
|
62
|
+
- **`push`** — git is the source of truth. Markdown files are pushed to Outline.
|
|
63
|
+
- **`pull`** — Outline is the source of truth. Documents are pulled into the repo.
|
|
64
|
+
- **`mixed`** — per-file `.ssot` markers decide direction.
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# Dry-run a sync from a repo
|
|
68
|
+
kctl-outline sync run /path/to/kodemeio-docs --config .outline-sync.kod.yaml
|
|
69
|
+
|
|
70
|
+
# Apply
|
|
71
|
+
kctl-outline sync run /path/to/kodemeio-docs --config .outline-sync.kod.yaml --no-dry-run
|
|
72
|
+
|
|
73
|
+
# Filter to a specific direction
|
|
74
|
+
kctl-outline sync run . --config .outline-sync.kod.yaml --mode push --no-dry-run
|
|
75
|
+
|
|
76
|
+
# Inspect tracked state
|
|
77
|
+
kctl-outline sync status
|
|
78
|
+
kctl-outline sync diff /path/to/repo
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The full spec lives in `kodemeio-docs/superpowers/specs/2026-04-10-docs-outline-restructure-design.md`.
|
|
82
|
+
|
|
83
|
+
## Profile-aware sync routing
|
|
84
|
+
|
|
85
|
+
When a sync config declares `profile: tpp`, `kctl-outline sync run` builds a fresh client using that profile's URL and token, regardless of the active CLI profile. This means the same machine can push to both `outline.kodeme.io` and `outline.idtpp.com` without switching profiles between commands.
|
|
86
|
+
|
|
87
|
+
## Layout
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
packages/kctl-outline/
|
|
91
|
+
├── pyproject.toml
|
|
92
|
+
├── README.md
|
|
93
|
+
├── src/kctl_outline/
|
|
94
|
+
│ ├── cli.py # Typer entry point
|
|
95
|
+
│ ├── commands/ # one module per Outline subresource
|
|
96
|
+
│ │ ├── sync.py # the Plan A/D sync subcommand
|
|
97
|
+
│ │ ├── documents.py
|
|
98
|
+
│ │ ├── collections.py
|
|
99
|
+
│ │ └── …
|
|
100
|
+
│ └── core/
|
|
101
|
+
│ ├── client.py # httpx wrapper
|
|
102
|
+
│ ├── config.py # profile resolution
|
|
103
|
+
│ ├── sync_config.py # SyncConfig v2 schema + v1 auto-upgrade
|
|
104
|
+
│ ├── sync_planner.py # pure plan_push_mapping
|
|
105
|
+
│ ├── sync_pull.py # pull direction (Outline → disk)
|
|
106
|
+
│ ├── sync_state.py # MappingSyncEntry + v1→v2 migration
|
|
107
|
+
│ └── sync_ssot.py # .ssot marker walker
|
|
108
|
+
└── tests/ # 30+ tests (pytest)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Tests
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
cd packages/kctl-outline
|
|
115
|
+
uv run --extra dev pytest tests/ -v
|
|
116
|
+
```
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "kctl-outline"
|
|
7
|
+
version = "0.6.1"
|
|
8
|
+
description = "Kodemeio Outline CLI — manage Outline wiki instances and sync markdown docs"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.12"
|
|
12
|
+
authors = [{ name = "Kodemeio", email = "dev@kodeme.io" }]
|
|
13
|
+
keywords = ["outline", "wiki", "knowledge-base", "cli", "kodemeio"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Environment :: Console",
|
|
17
|
+
"Intended Audience :: System Administrators",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Programming Language :: Python :: 3.12",
|
|
20
|
+
"Programming Language :: Python :: 3.13",
|
|
21
|
+
"Topic :: System :: Systems Administration",
|
|
22
|
+
]
|
|
23
|
+
dependencies = [
|
|
24
|
+
"kctl-lib>=0.7.0",
|
|
25
|
+
"typer>=0.15.0",
|
|
26
|
+
"httpx>=0.28.0",
|
|
27
|
+
"rich>=13.9.0",
|
|
28
|
+
"pydantic>=2.10.0",
|
|
29
|
+
"pyyaml>=6.0.2",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[project.optional-dependencies]
|
|
33
|
+
dev = [
|
|
34
|
+
"pytest>=8.3.0",
|
|
35
|
+
"pytest-httpx>=0.35.0",
|
|
36
|
+
"ruff>=0.9.0",
|
|
37
|
+
"mypy>=1.14.0",
|
|
38
|
+
"types-PyYAML>=6.0.0",
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
[project.scripts]
|
|
42
|
+
kctl-outline = "kctl_outline.cli:_run"
|
|
43
|
+
|
|
44
|
+
[tool.uv.sources]
|
|
45
|
+
kctl-lib = { workspace = true }
|
|
46
|
+
|
|
47
|
+
[tool.hatch.build.targets.wheel]
|
|
48
|
+
packages = ["src/kctl_outline"]
|
|
49
|
+
|
|
50
|
+
[tool.ruff]
|
|
51
|
+
target-version = "py312"
|
|
52
|
+
line-length = 120
|
|
53
|
+
|
|
54
|
+
[tool.ruff.lint]
|
|
55
|
+
select = ["E", "F", "I", "W", "UP", "B", "SIM"]
|
|
56
|
+
|
|
57
|
+
[tool.mypy]
|
|
58
|
+
python_version = "3.12"
|
|
59
|
+
strict = true
|
|
60
|
+
|
|
61
|
+
[tool.pytest.ini_options]
|
|
62
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: outline-admin
|
|
3
|
+
description: >
|
|
4
|
+
Outline wiki/knowledge-base administration via kctl-outline CLI.
|
|
5
|
+
MUST use for ANY kctl-outline operation — documents, collections, users, groups,
|
|
6
|
+
shares, comments, events, health checks, AND markdown sync between repos and
|
|
7
|
+
one or more Outline instances.
|
|
8
|
+
Triggers on: "kctl-outline", "outline", "wiki", "knowledge base", "create document",
|
|
9
|
+
"collection", "share document", "outline.kodeme.io", "outline.idtpp.com",
|
|
10
|
+
"sync docs", "outline sync", "doc sync", ".outline-sync.yaml".
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# outline-admin — kctl-outline CLI Reference
|
|
14
|
+
|
|
15
|
+
## Overview
|
|
16
|
+
|
|
17
|
+
**CLI:** `kctl-outline`
|
|
18
|
+
**Workspace:** `kodemeio-platform/packages/kctl-outline/`
|
|
19
|
+
**Install:** `cd packages/kctl-outline && uv sync --extra dev`
|
|
20
|
+
**Standalone install:** `uv tool install kctl-outline` (when published to PyPI)
|
|
21
|
+
|
|
22
|
+
## Global Options
|
|
23
|
+
|
|
24
|
+
| Flag | Description |
|
|
25
|
+
|------|-------------|
|
|
26
|
+
| `--json` | JSON output |
|
|
27
|
+
| `--quiet`, `-q` | Suppress info messages |
|
|
28
|
+
| `--profile`, `-p` | Profile name (default from `~/.config/kodemeio/config.yaml`) |
|
|
29
|
+
| `--url` | Override API URL (e.g., `https://outline.idtpp.com`) |
|
|
30
|
+
| `--token` | Override API token |
|
|
31
|
+
| `--version`, `-V` | Show version |
|
|
32
|
+
|
|
33
|
+
## Profiles
|
|
34
|
+
|
|
35
|
+
Configure once per Outline instance:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
kctl-outline config init # interactive
|
|
39
|
+
kctl-outline config add kod --url https://outline.kodeme.io --token <T>
|
|
40
|
+
kctl-outline config add tpp --url https://outline.idtpp.com --token <T>
|
|
41
|
+
kctl-outline config use kod # default
|
|
42
|
+
kctl-outline config current # show active
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Command Groups
|
|
46
|
+
|
|
47
|
+
| Group | Purpose |
|
|
48
|
+
|---|---|
|
|
49
|
+
| `config` | Profile management (init, add, use, show, profiles, current, test) |
|
|
50
|
+
| `documents` | Create / list / update / delete / move documents |
|
|
51
|
+
| `collections` | Manage collections |
|
|
52
|
+
| `users` | User management |
|
|
53
|
+
| `groups` | Group management |
|
|
54
|
+
| `shares` | Public share links |
|
|
55
|
+
| `comments`, `events`, `revisions` | Read-only metadata |
|
|
56
|
+
| `templates`, `stars`, `tokens` | Misc admin |
|
|
57
|
+
| `search` | Search across documents |
|
|
58
|
+
| `health` | Health checks and diagnostics |
|
|
59
|
+
| `dashboard` | System overview |
|
|
60
|
+
| **`sync`** | **Markdown sync between git repos and Outline (primary integration)** |
|
|
61
|
+
|
|
62
|
+
## Sync subcommand — primary use case
|
|
63
|
+
|
|
64
|
+
`kctl-outline sync` is the integration point with `kodemeio-docs`. It supports multi-mapping `.outline-sync.yaml` v2 configs with three direction modes:
|
|
65
|
+
|
|
66
|
+
- **`push`** — git is the source of truth. Markdown files are pushed to Outline.
|
|
67
|
+
- **`pull`** — Outline is the source of truth. Documents are pulled into the repo. Reconciles deletions: docs removed in Outline are also removed from disk.
|
|
68
|
+
- **`mixed`** — per-file `.ssot` markers (containing `git` or `outline`) decide direction.
|
|
69
|
+
|
|
70
|
+
### Commands
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# Dry-run (default) against the kod instance
|
|
74
|
+
kctl-outline sync run /path/to/kodemeio-docs --config .outline-sync.kod.yaml
|
|
75
|
+
|
|
76
|
+
# Apply
|
|
77
|
+
kctl-outline sync run /path/to/kodemeio-docs --config .outline-sync.kod.yaml --no-dry-run
|
|
78
|
+
|
|
79
|
+
# Filter to one direction (push only, skip pull mappings)
|
|
80
|
+
kctl-outline sync run . --config .outline-sync.kod.yaml --mode push --no-dry-run
|
|
81
|
+
|
|
82
|
+
# Same syntax against the TPP instance
|
|
83
|
+
kctl-outline sync run /path/to/kodemeio-docs --config .outline-sync.tpp.yaml --no-dry-run
|
|
84
|
+
|
|
85
|
+
# Inspect tracked state
|
|
86
|
+
kctl-outline sync status
|
|
87
|
+
|
|
88
|
+
# What would change on next push?
|
|
89
|
+
kctl-outline sync diff /path/to/kodemeio-docs
|
|
90
|
+
|
|
91
|
+
# Bootstrap a config stub
|
|
92
|
+
kctl-outline sync init /path/to/repo --collection 'My Docs'
|
|
93
|
+
|
|
94
|
+
# Wipe state (does NOT delete from Outline)
|
|
95
|
+
kctl-outline sync reset --force
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Profile-aware client routing
|
|
99
|
+
|
|
100
|
+
When a sync config declares `profile: tpp`, `sync run` builds a fresh client using **that profile's URL+token**, regardless of the active CLI profile. So the same machine can push to both `outline.kodeme.io` and `outline.idtpp.com` without `--profile` switching:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
kctl-outline sync run . --config .outline-sync.kod.yaml --no-dry-run # → outline.kodeme.io
|
|
104
|
+
kctl-outline sync run . --config .outline-sync.tpp.yaml --no-dry-run # → outline.idtpp.com
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### .outline-sync.yaml v2 schema
|
|
108
|
+
|
|
109
|
+
```yaml
|
|
110
|
+
instance: outline.kodeme.io # human-readable, optional
|
|
111
|
+
profile: kod # selects the kctl-outline profile
|
|
112
|
+
|
|
113
|
+
mappings:
|
|
114
|
+
- src: shared/ # path relative to the config file
|
|
115
|
+
collection: "Shared — Engineering"
|
|
116
|
+
mode: push # push | pull | mixed
|
|
117
|
+
subpath: "" # optional: nest under a doc title
|
|
118
|
+
include: # optional gitignore-style globs
|
|
119
|
+
- "01-*/**"
|
|
120
|
+
- "02-*/**"
|
|
121
|
+
exclude: # optional
|
|
122
|
+
- "**/draft/**"
|
|
123
|
+
|
|
124
|
+
- src: shared/06-business-processes
|
|
125
|
+
collection: "Shared — Business"
|
|
126
|
+
mode: pull # nightly cron pulls + reconciles deletions
|
|
127
|
+
|
|
128
|
+
- src: tenants/kod
|
|
129
|
+
collection: "Kod — Internal"
|
|
130
|
+
mode: mixed # per-file .ssot markers
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### .ssot markers
|
|
134
|
+
|
|
135
|
+
Each leaf directory may contain a `.ssot` file with exactly one line: `git` or `outline`. In `mixed` mode the planner skips push actions for files under `outline`-marked directories (and vice versa). The kodemeio-docs pre-commit hook (`scripts/check_ssot.py`) enforces the same rule on commits.
|
|
136
|
+
|
|
137
|
+
## Live URLs
|
|
138
|
+
|
|
139
|
+
| Profile | URL | Audience |
|
|
140
|
+
|---|---|---|
|
|
141
|
+
| `kod` | https://outline.kodeme.io | Kodemeio staff, MAC, Provetics, Terakidz |
|
|
142
|
+
| `tpp` | https://outline.idtpp.com | TPP Group customer-facing |
|
|
143
|
+
|
|
144
|
+
## Tests
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
cd packages/kctl-outline
|
|
148
|
+
uv run --extra dev pytest tests/ -v
|
|
149
|
+
# Expected: 32 tests passing
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## See also
|
|
153
|
+
|
|
154
|
+
- Spec: `kodemeio-docs/superpowers/specs/2026-04-10-docs-outline-restructure-design.md`
|
|
155
|
+
- Plans: `kodemeio-docs/superpowers/plans/2026-04-10-{docs-restructure,kctl-outline-sync-enhancements,outline-tpp-instance}.md`
|
|
156
|
+
- Configs in use: `kodemeio-docs/.outline-sync.{kod,tpp}.yaml`
|
|
157
|
+
- Push CI: `kodemeio-docs/.github/workflows/outline-sync-push.yml`
|
|
158
|
+
- Nightly pull cron: `kodemeio-docs/scripts/cron/outline-sync-pull.sh`
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"""Main CLI entry point for kctl-outline."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Annotated
|
|
6
|
+
|
|
7
|
+
import typer
|
|
8
|
+
from kctl_lib.self_update import notify_if_outdated
|
|
9
|
+
from kctl_lib.tui import add_tui_command
|
|
10
|
+
|
|
11
|
+
from kctl_outline import __version__
|
|
12
|
+
from kctl_outline.commands.attachments import app as attachments_app
|
|
13
|
+
from kctl_outline.commands.collections import app as collections_app
|
|
14
|
+
from kctl_outline.commands.comments import app as comments_app
|
|
15
|
+
from kctl_outline.commands.config_cmd import app as config_app
|
|
16
|
+
from kctl_outline.commands.dashboard import app as dashboard_app
|
|
17
|
+
from kctl_outline.commands.doctor_cmd import app as doctor_app
|
|
18
|
+
from kctl_outline.commands.documents import app as documents_app
|
|
19
|
+
from kctl_outline.commands.events import app as events_app
|
|
20
|
+
from kctl_outline.commands.groups import app as groups_app
|
|
21
|
+
from kctl_outline.commands.health import app as health_app
|
|
22
|
+
from kctl_outline.commands.revisions import app as revisions_app
|
|
23
|
+
from kctl_outline.commands.search import search_command
|
|
24
|
+
from kctl_outline.commands.shares import app as shares_app
|
|
25
|
+
from kctl_outline.commands.stars import app as stars_app
|
|
26
|
+
from kctl_outline.commands.sync import app as sync_app
|
|
27
|
+
from kctl_outline.commands.templates import app as templates_app
|
|
28
|
+
from kctl_outline.commands.tokens import app as tokens_app
|
|
29
|
+
from kctl_outline.commands.users import app as users_app
|
|
30
|
+
from kctl_outline.core.callbacks import AppContext
|
|
31
|
+
from kctl_outline.core.exceptions import APIError, AuthenticationError, ConfigError, KctlError
|
|
32
|
+
from kctl_outline.core.exceptions import ConnectionError as KctlConnectionError
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def version_callback(value: bool) -> None:
|
|
36
|
+
if value:
|
|
37
|
+
typer.echo(f"kctl-outline {__version__}")
|
|
38
|
+
raise typer.Exit()
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
app = typer.Typer(
|
|
42
|
+
name="kctl-outline",
|
|
43
|
+
help="Kodemeio Outline CLI - manage your Outline wiki instances.",
|
|
44
|
+
no_args_is_help=True,
|
|
45
|
+
rich_markup_mode="rich",
|
|
46
|
+
pretty_exceptions_enable=False,
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@app.callback()
|
|
51
|
+
def main(
|
|
52
|
+
ctx: typer.Context,
|
|
53
|
+
json_output: Annotated[bool, typer.Option("--json", help="Output as JSON")] = False,
|
|
54
|
+
quiet: Annotated[bool, typer.Option("--quiet", "-q", help="Suppress info messages")] = False,
|
|
55
|
+
profile: Annotated[str | None, typer.Option("--profile", "-p", help="Config profile name")] = None,
|
|
56
|
+
url: Annotated[str | None, typer.Option("--url", help="API URL override")] = None,
|
|
57
|
+
token: Annotated[str | None, typer.Option("--token", help="API token override")] = None,
|
|
58
|
+
version: Annotated[
|
|
59
|
+
bool, typer.Option("--version", "-V", callback=version_callback, is_eager=True, help="Show version")
|
|
60
|
+
] = False,
|
|
61
|
+
) -> None:
|
|
62
|
+
"""Kodemeio Outline CLI."""
|
|
63
|
+
ctx.ensure_object(dict)
|
|
64
|
+
ctx.obj = AppContext(
|
|
65
|
+
json_mode=json_output,
|
|
66
|
+
quiet=quiet,
|
|
67
|
+
profile=profile,
|
|
68
|
+
url_override=url,
|
|
69
|
+
token_override=token,
|
|
70
|
+
)
|
|
71
|
+
notify_if_outdated(ctx.obj.output, "kctl-outline", __version__)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
# Register all command groups
|
|
75
|
+
app.add_typer(documents_app, name="documents")
|
|
76
|
+
app.add_typer(collections_app, name="collections")
|
|
77
|
+
app.add_typer(users_app, name="users")
|
|
78
|
+
app.add_typer(groups_app, name="groups")
|
|
79
|
+
app.add_typer(shares_app, name="shares")
|
|
80
|
+
app.add_typer(comments_app, name="comments")
|
|
81
|
+
app.add_typer(events_app, name="events")
|
|
82
|
+
app.add_typer(health_app, name="health")
|
|
83
|
+
app.add_typer(dashboard_app, name="dashboard")
|
|
84
|
+
app.add_typer(config_app, name="config")
|
|
85
|
+
app.add_typer(doctor_app, name="doctor")
|
|
86
|
+
app.add_typer(stars_app, name="stars")
|
|
87
|
+
app.add_typer(templates_app, name="templates")
|
|
88
|
+
app.add_typer(revisions_app, name="revisions")
|
|
89
|
+
app.add_typer(attachments_app, name="attachments")
|
|
90
|
+
app.add_typer(tokens_app, name="tokens")
|
|
91
|
+
app.add_typer(sync_app, name="sync")
|
|
92
|
+
add_tui_command(app, service_key="outline", version=__version__)
|
|
93
|
+
|
|
94
|
+
# Top-level search command
|
|
95
|
+
app.command("search")(search_command)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _run() -> None:
|
|
99
|
+
"""Entry point with error handling."""
|
|
100
|
+
try:
|
|
101
|
+
app()
|
|
102
|
+
except KctlConnectionError as e:
|
|
103
|
+
typer.echo(f"Connection error: {e}", err=True)
|
|
104
|
+
raise typer.Exit(1) from e
|
|
105
|
+
except AuthenticationError as e:
|
|
106
|
+
typer.echo(f"Auth error: {e}", err=True)
|
|
107
|
+
raise typer.Exit(1) from e
|
|
108
|
+
except APIError as e:
|
|
109
|
+
typer.echo(f"API error: {e}", err=True)
|
|
110
|
+
raise typer.Exit(1) from e
|
|
111
|
+
except ConfigError as e:
|
|
112
|
+
typer.echo(f"Config error: {e}", err=True)
|
|
113
|
+
raise typer.Exit(1) from e
|
|
114
|
+
except KctlError as e:
|
|
115
|
+
typer.echo(f"Error: {e}", err=True)
|
|
116
|
+
raise typer.Exit(1) from e
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
if __name__ == "__main__":
|
|
120
|
+
_run()
|
|
File without changes
|