docforge-cli 0.2.0__py3-none-any.whl
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.
- docforge/__init__.py +0 -0
- docforge/__main__.py +5 -0
- docforge/api.py +266 -0
- docforge/cli.py +296 -0
- docforge/config.py +99 -0
- docforge/crawlers/__init__.py +1 -0
- docforge/crawlers/confluence.py +109 -0
- docforge/crawlers/git.py +79 -0
- docforge/db.py +57 -0
- docforge/ingest.py +401 -0
- docforge/lint.py +92 -0
- docforge/mcp_server.py +188 -0
- docforge/processors/__init__.py +1 -0
- docforge/processors/chunker.py +141 -0
- docforge/processors/embedder.py +78 -0
- docforge/processors/parser.py +143 -0
- docforge/query_log.py +45 -0
- docforge/ranking.py +20 -0
- docforge/scripts/__init__.py +1 -0
- docforge/scripts/eval_search.py +226 -0
- docforge/scripts/latency_report.py +142 -0
- docforge/sources.py +46 -0
- docforge/sql/migrations/001_add_source_identifier.sql +3 -0
- docforge/sql/migrations/002_add_status_index.sql +1 -0
- docforge/sql/migrations/003_add_source_tags.sql +4 -0
- docforge/sql/migrations/004_add_query_log.sql +11 -0
- docforge/sql/migrations/005_add_query_log_user_oid.sql +2 -0
- docforge/sql/migrations/006_add_query_log_request_ms.sql +1 -0
- docforge/sql/schema.sql +29 -0
- docforge/templates/docforge.yml +11 -0
- docforge/templates/docker-compose.yml +14 -0
- docforge/templates/mcp_client.py +83 -0
- docforge/templates/sources.yml +21 -0
- docforge_cli-0.2.0.dist-info/METADATA +178 -0
- docforge_cli-0.2.0.dist-info/RECORD +39 -0
- docforge_cli-0.2.0.dist-info/WHEEL +5 -0
- docforge_cli-0.2.0.dist-info/entry_points.txt +2 -0
- docforge_cli-0.2.0.dist-info/licenses/LICENSE +21 -0
- docforge_cli-0.2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: docforge-cli
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Forge searchable context from Confluence and git repos for AI coding assistants
|
|
5
|
+
License: MIT
|
|
6
|
+
Requires-Python: >=3.12
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Requires-Dist: typer>=0.12
|
|
10
|
+
Requires-Dist: asyncpg>=0.30
|
|
11
|
+
Requires-Dist: httpx>=0.27
|
|
12
|
+
Requires-Dist: pydantic>=2.9
|
|
13
|
+
Requires-Dist: pydantic-settings>=2.6
|
|
14
|
+
Requires-Dist: beautifulsoup4>=4.12
|
|
15
|
+
Requires-Dist: sentence-transformers>=5.0
|
|
16
|
+
Requires-Dist: pgvector>=0.3
|
|
17
|
+
Requires-Dist: pyyaml>=6.0
|
|
18
|
+
Requires-Dist: fastmcp>=2.0
|
|
19
|
+
Requires-Dist: fastapi>=0.115
|
|
20
|
+
Requires-Dist: uvicorn>=0.34
|
|
21
|
+
Requires-Dist: numpy>=1.26
|
|
22
|
+
Provides-Extra: dev
|
|
23
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
24
|
+
Requires-Dist: pytest-asyncio>=0.24; extra == "dev"
|
|
25
|
+
Requires-Dist: pytest-cov>=7.0; extra == "dev"
|
|
26
|
+
Requires-Dist: ruff>=0.8; extra == "dev"
|
|
27
|
+
Requires-Dist: testcontainers[postgres]>=4.0; extra == "dev"
|
|
28
|
+
Provides-Extra: entra
|
|
29
|
+
Requires-Dist: fastapi-azure-auth>=5.0; extra == "entra"
|
|
30
|
+
Requires-Dist: azure-identity>=1.19; extra == "entra"
|
|
31
|
+
Requires-Dist: aiohttp>=3.10; extra == "entra"
|
|
32
|
+
Dynamic: license-file
|
|
33
|
+
|
|
34
|
+
# docforge
|
|
35
|
+
|
|
36
|
+
**The self-hosted context engine for AI coding assistants.**
|
|
37
|
+
|
|
38
|
+
Point docforge at your Confluence spaces and local git repositories. It indexes, embeds, and serves them over MCP — so Claude Code, Cursor, Copilot, and any assistant that speaks MCP can search your team's knowledge without your data leaving your infrastructure.
|
|
39
|
+
|
|
40
|
+
docforge doesn't replace your AI assistant. It feeds it — turning Claude Code, Cursor, Copilot, and anything else that speaks MCP into tools that actually know your team's docs and code.
|
|
41
|
+
|
|
42
|
+
[](https://github.com/GranatenUdo/docforge/actions/workflows/ci.yml)
|
|
43
|
+
[](https://pypi.org/project/docforge-cli/)
|
|
44
|
+
[](https://www.python.org/downloads/)
|
|
45
|
+
[](LICENSE)
|
|
46
|
+
[](https://github.com/astral-sh/ruff)
|
|
47
|
+
|
|
48
|
+
## Why docforge
|
|
49
|
+
|
|
50
|
+
| Tool | Self-hosted | Integration | Confluence + code | Footprint | Complements AI assistants? |
|
|
51
|
+
|---|---|---|---|---|---|
|
|
52
|
+
| **docforge** | ✓ | MCP server | ✓ (Confluence + local git) | Minimal (PG + 1 container) | ✓ (any MCP client) |
|
|
53
|
+
| [Atlassian Rovo MCP](https://www.atlassian.com/blog/announcements/atlassian-rovo-mcp-ga) | ✗ (Cloud-only) | MCP server | Confluence only (Cloud) | SaaS | ✓ |
|
|
54
|
+
| [zilliztech/claude-context](https://github.com/zilliztech/claude-context) | ✓ | MCP server | Code only | Minimal | ✓ |
|
|
55
|
+
| [Onyx](https://github.com/onyx-dot-app/onyx) | ✓ | MCP + chat UI | ✓ (50+ connectors) | Heavy (Standard) / Minimal (Lite) | ✓ (+ its own UI) |
|
|
56
|
+
| Cursor codebase index + @Docs | ✗ | Proprietary | Code + public web docs | SaaS | — (built into Cursor only) |
|
|
57
|
+
| [Copilot Spaces](https://github.com/orgs/community/discussions/180894) | ✗ | Proprietary (MCP for actions) | Code + attachments | SaaS | — (built into Copilot only) |
|
|
58
|
+
| [Sourcegraph Cody](https://sourcegraph.com/docs/cody/enterprise/features) | ✓ (Enterprise) | OpenCtx / MCP | ✓ (via OpenCtx) | Heavy (Sourcegraph platform) | — (built into Cody only) |
|
|
59
|
+
| LangChain / LlamaIndex DIY | ✓ | Whatever you build | You wire it | Depends | Depends |
|
|
60
|
+
|
|
61
|
+
docforge is the narrow, focused option in this landscape: minimal footprint, MCP-native so it works with every assistant, and combines Confluence + code out of the box. It doesn't compete on connector count (Onyx wins there), visual UX (Cursor and Cody win), or SaaS convenience (Rovo). It competes on being **small, legible, vendor-neutral, and self-hosted** — four properties no commercial option offers together.
|
|
62
|
+
|
|
63
|
+
### ✅ When docforge fits
|
|
64
|
+
|
|
65
|
+
- You run Confluence Data Center/Server, or you want to self-host.
|
|
66
|
+
- Your team uses MCP-capable assistants (Claude Code, Cursor with MCP, Copilot with MCP, etc.).
|
|
67
|
+
- You want Confluence + git repos indexed together with one tool.
|
|
68
|
+
- Operational simplicity matters — one Postgres, one container, MIT-licensed code you can audit in an afternoon.
|
|
69
|
+
|
|
70
|
+
### ❌ When docforge is the wrong choice
|
|
71
|
+
|
|
72
|
+
- You need 50+ connectors (Slack, Jira, Gmail, Drive, Notion) → use **[Onyx](https://github.com/onyx-dot-app/onyx)** or **[Glean](https://www.glean.com/)**.
|
|
73
|
+
- You need per-document ACLs enforced at query time → not yet supported; use **Onyx**.
|
|
74
|
+
- You need a chat UI for non-developers → docforge has no UI; use **Onyx**, **Glean**, or **Cody**.
|
|
75
|
+
- You're on Atlassian Cloud and happy with SaaS → **[Atlassian Rovo MCP](https://www.atlassian.com/blog/announcements/atlassian-rovo-mcp-ga)** is free and official.
|
|
76
|
+
- You need SSO / SCIM / RBAC → out of scope; docforge authenticates but doesn't authorize per-resource.
|
|
77
|
+
- Your corpus is very large (>100K pages/chunks) → dense-only retrieval without hybrid starts to degrade; on the [roadmap](ROADMAP.md).
|
|
78
|
+
- You need near-real-time updates → ingest is batch; no webhook-driven continuous sync yet.
|
|
79
|
+
- You need multilingual search evaluated → EmbeddingGemma is multilingual, but docforge has no eval coverage on non-English corpora yet.
|
|
80
|
+
|
|
81
|
+
## Quick Start
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
pip install docforge-cli
|
|
85
|
+
docforge init my-project
|
|
86
|
+
cd my-project
|
|
87
|
+
# Edit docforge.yml with your Confluence URL
|
|
88
|
+
# Edit sources.yml with your page IDs and local git repo paths
|
|
89
|
+
# Edit .env with your credentials
|
|
90
|
+
docker compose up -d db
|
|
91
|
+
docforge init-db
|
|
92
|
+
docforge ingest
|
|
93
|
+
docforge serve
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**Note:** The git crawler indexes **local filesystem paths** — docforge does not clone GitHub URLs. Clone first, then point docforge at the checkout path in `sources.yml`.
|
|
97
|
+
|
|
98
|
+
## How It Works
|
|
99
|
+
|
|
100
|
+
1. **Configure** your Confluence URL, page IDs, and local git repo paths in `sources.yml`.
|
|
101
|
+
2. **Ingest** crawls pages and files, chunks text (~500 tokens), generates vector embeddings (768-dim).
|
|
102
|
+
3. **Serve** exposes an MCP server that AI assistants query automatically.
|
|
103
|
+
|
|
104
|
+
When an AI assistant needs cross-team context, it calls docforge's `search_documentation` MCP tool behind the scenes and gets relevant documentation chunks with source attribution.
|
|
105
|
+
|
|
106
|
+
### Architecture
|
|
107
|
+
|
|
108
|
+

|
|
109
|
+
|
|
110
|
+
## Commands
|
|
111
|
+
|
|
112
|
+
| Command | Description |
|
|
113
|
+
|---------|-------------|
|
|
114
|
+
| `docforge init <name>` | Scaffold a new project with config templates |
|
|
115
|
+
| `docforge init-db` | Initialize the PostgreSQL database schema |
|
|
116
|
+
| `docforge ingest` | Crawl all sources, embed, store in PostgreSQL |
|
|
117
|
+
| `docforge search "<query>"` | Test search from terminal |
|
|
118
|
+
| `docforge serve` | Run MCP server for AI assistants |
|
|
119
|
+
| `docforge serve --api` | Run FastAPI search API (for hosted deployment) |
|
|
120
|
+
| `docforge status` | Show index stats and health |
|
|
121
|
+
|
|
122
|
+
## Deploy to your infrastructure
|
|
123
|
+
|
|
124
|
+
For team-wide use, deploy the search API to Azure (~$35/month at default SKUs):
|
|
125
|
+
|
|
126
|
+
- PostgreSQL Flexible Server (Burstable B1ms, 32 GB) with pgvector.
|
|
127
|
+
- Container App running the FastAPI search API.
|
|
128
|
+
- Container Registry, Key Vault, Log Analytics, managed environment.
|
|
129
|
+
- Team members use a lightweight MCP client that calls the hosted API.
|
|
130
|
+
|
|
131
|
+
See [`deploy/azure/`](deploy/azure/) for Bicep templates and a full cost breakdown.
|
|
132
|
+
|
|
133
|
+
## Configuration
|
|
134
|
+
|
|
135
|
+
See `docs/` for the full configuration reference, including `docforge.yml` and `sources.yml` schemas.
|
|
136
|
+
|
|
137
|
+
## Contributing
|
|
138
|
+
|
|
139
|
+
Contributions welcome. See [`CONTRIBUTING.md`](CONTRIBUTING.md) for development setup, branch conventions, and PR expectations. Bug reports and feature requests go through [GitHub Issues](https://github.com/GranatenUdo/docforge/issues); open-ended questions and ideas live in [Discussions](https://github.com/GranatenUdo/docforge/discussions).
|
|
140
|
+
|
|
141
|
+
## Evaluation & retrieval quality
|
|
142
|
+
|
|
143
|
+
docforge ships with a retrieval-quality eval harness at [`docforge/scripts/eval_search.py`](docforge/scripts/eval_search.py). It measures recall@1, recall@k, and MRR against a ground-truth query set you maintain. The harness is designed for **drift detection** — run it after `sources.yml` changes, embedding-model updates, or ranking tweaks, and compare against your baseline. There is no absolute quality threshold; the metric magnitude depends on how closely your ground-truth queries match source titles. See [`docforge/scripts/README.md`](docforge/scripts/README.md) for details.
|
|
144
|
+
|
|
145
|
+
## FAQ
|
|
146
|
+
|
|
147
|
+
### "Cannot connect to PostgreSQL"
|
|
148
|
+
|
|
149
|
+
Check that the database is running: `docker compose up -d db`. Verify `DATABASE_URL` in `.env` points to `postgresql://docforge:localdev@localhost:5432/docforge` (or your custom value).
|
|
150
|
+
|
|
151
|
+
### "HF_TOKEN required" or model download fails
|
|
152
|
+
|
|
153
|
+
The embedding model `google/embeddinggemma-300m` requires a Hugging Face token with access to the gated model. Create one at https://huggingface.co/settings/tokens, accept the model license at https://huggingface.co/google/embeddinggemma-300m, and set `HF_TOKEN=hf_...` in `.env`.
|
|
154
|
+
|
|
155
|
+
### "No results found" after ingest
|
|
156
|
+
|
|
157
|
+
Run `docforge status` to confirm sources and chunks exist. If counts are zero, check the ingest logs for per-source failures — the summary at the end lists sources that failed.
|
|
158
|
+
|
|
159
|
+
### First ingest / first container start is very slow
|
|
160
|
+
|
|
161
|
+
The first run downloads the 300M embedding model (~1.2 GB) from Hugging Face. Locally, the model is cached at `~/.cache/huggingface/`. In the Docker image, it is cached at `/app/.cache/huggingface/` — **mount this as a volume** so container restarts do not re-download: `docker run -v docforge-hf-cache:/app/.cache/huggingface ...`.
|
|
162
|
+
|
|
163
|
+
### "Ingest skipped everything"
|
|
164
|
+
|
|
165
|
+
docforge skips sources whose `content_hash` matches the stored hash (no changes detected). To force re-ingest, clear the hash: `UPDATE sources SET content_hash = NULL;` then run `docforge ingest`.
|
|
166
|
+
|
|
167
|
+
## License
|
|
168
|
+
|
|
169
|
+
MIT. See [LICENSE](LICENSE).
|
|
170
|
+
|
|
171
|
+
## Credits
|
|
172
|
+
|
|
173
|
+
docforge stands on open shoulders:
|
|
174
|
+
|
|
175
|
+
- [EmbeddingGemma-300M](https://huggingface.co/google/embeddinggemma-300m) — open-weights embedding model under the Gemma license.
|
|
176
|
+
- [pgvector](https://github.com/pgvector/pgvector) — vector similarity for Postgres.
|
|
177
|
+
- [FastMCP](https://github.com/PrefectHQ/fastmcp) — MCP server framework.
|
|
178
|
+
- [FastAPI](https://fastapi.tiangolo.com/), [Typer](https://typer.tiangolo.com/), [asyncpg](https://magicstack.github.io/asyncpg/), [sentence-transformers](https://www.sbert.net/) — core infrastructure.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
docforge/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
docforge/__main__.py,sha256=cZeNOY01TCuT_v3-Rmgb2ehdG3nP_2BvCSOyR6F2HMI,115
|
|
3
|
+
docforge/api.py,sha256=RCAo0otKR-id29TZgo4wmHV1_silj7EMyU5f91qC6Jc,8780
|
|
4
|
+
docforge/cli.py,sha256=fN32vrmSBrF7F3HfMGRLiL4Xo0npo1wrQEUUCTaXT1Q,9480
|
|
5
|
+
docforge/config.py,sha256=UNveJ1ksWj9dIPtOdiE5Z1XXP21TdGyx968ykrOTIyU,3372
|
|
6
|
+
docforge/db.py,sha256=Q5wVCz6ltJgoINfUuIhwUeUmvuSmGYuw86fNIQEmECo,1643
|
|
7
|
+
docforge/ingest.py,sha256=XlGrdx7JedXo2b2DuZYL9F3RVNf-EUbwhvTAnI_ABAo,15102
|
|
8
|
+
docforge/lint.py,sha256=TU9OAYRdhqOH-_TiHfdZ43usIqK6Cr-SDnEv2BPfOxU,3030
|
|
9
|
+
docforge/mcp_server.py,sha256=k0i-Q-Gho8QUA2HDo7aAiPgGyrQNeOn_-p7JigyPIxI,5884
|
|
10
|
+
docforge/query_log.py,sha256=6mkEAhKS3Cge7EcfT31_Ye6TwdLDjWOmOjIHlTGXHqI,1294
|
|
11
|
+
docforge/ranking.py,sha256=KDD7WW2RlOKKU9BfJfDWMS_bwRDufUF-7h8qpp3eYfg,685
|
|
12
|
+
docforge/sources.py,sha256=hkXg5TXqTTKcKNuLRO1mRyDtbKZ9aAVUAjlfK9Xem_s,1097
|
|
13
|
+
docforge/crawlers/__init__.py,sha256=xoelR0ZwJ2TSCpUGqpV6Teu1ayrtwjVm1vCfqgaHpV8,79
|
|
14
|
+
docforge/crawlers/confluence.py,sha256=bMuqdHGz6A0EA-O69935d_fn2j0uvHzZfTAzdhCXOt8,3111
|
|
15
|
+
docforge/crawlers/git.py,sha256=l7WKDu_T7-w1AaYOC8S9EpiZ-_jkP441IJK-NGdndFQ,2242
|
|
16
|
+
docforge/processors/__init__.py,sha256=2iDniNCSBaXe0If4FHyb6cqq2twnLSD4XK0J_o1pKUE,70
|
|
17
|
+
docforge/processors/chunker.py,sha256=et7zFUylVa4UYfE6ehj0RQjHTE5k98dGBAan8YqOupg,4190
|
|
18
|
+
docforge/processors/embedder.py,sha256=7xvZEzd3Al96hwL8Ge0kjFF3GKxHy6EDJyllGHP16jI,2947
|
|
19
|
+
docforge/processors/parser.py,sha256=O43gidPROgjsdrcSUby4hoDmMlVDf8lDXaQxDEq8EzA,4469
|
|
20
|
+
docforge/scripts/__init__.py,sha256=DnOvKXALsxsGpGaDzHMvVAD3PuwIWBTTEgqoXNAQcR0,83
|
|
21
|
+
docforge/scripts/eval_search.py,sha256=xcn8JG5LTx5lGzSE0Umt4xJoAyJIdAFvQa3eRia0rQs,8518
|
|
22
|
+
docforge/scripts/latency_report.py,sha256=9imjMkl6nPIDknh8gWzaRjZlUzhy9fDxXyHheiWRIyk,5056
|
|
23
|
+
docforge/sql/schema.sql,sha256=ljoWstTWxzc2wVZNGacMBu5px2Gva2j17pO9TxEF__U,913
|
|
24
|
+
docforge/sql/migrations/001_add_source_identifier.sql,sha256=CmmleA8-gyOCSO1MsD8FjFuMgtAa5l5HdSjvgW6d0g4,208
|
|
25
|
+
docforge/sql/migrations/002_add_status_index.sql,sha256=mxImhHBTZomMHqzeBbGnX96M-iD62bbzZkU1ukV9lN0,67
|
|
26
|
+
docforge/sql/migrations/003_add_source_tags.sql,sha256=hhBYHHpXpoUKOyVmYmNJR3Zbn2PTT8IWKTRInbt1MwM,158
|
|
27
|
+
docforge/sql/migrations/004_add_query_log.sql,sha256=9ssAvsddQhELUaPMxFI_qWEFYi2fnqLlSVtlF5q6Gfc,357
|
|
28
|
+
docforge/sql/migrations/005_add_query_log_user_oid.sql,sha256=awceItGNTKcNYHtM9jyWNfBKOw6USiWMa5JUjlAtg-I,137
|
|
29
|
+
docforge/sql/migrations/006_add_query_log_request_ms.sql,sha256=9Z0KZRH2pYA5hlubMkeZRI9-5f7_Kh9Z8cKZ3MqXxMU,63
|
|
30
|
+
docforge/templates/docforge.yml,sha256=U8HgPM1maiizRjX2FA1fWDT547yQk6qEb9EHe-fGL8w,281
|
|
31
|
+
docforge/templates/docker-compose.yml,sha256=vStUTu7CALeV8gJU1tZuLuGOmGVcf3Xk68wTxhPe_sI,263
|
|
32
|
+
docforge/templates/mcp_client.py,sha256=hxycesqhYd40Vn6a5PICRjgFCHXBO0iupBzDByBRIf4,2452
|
|
33
|
+
docforge/templates/sources.yml,sha256=sjowhY815K3fMG-f2iSqXsniHYwC8PmI7SIVCrGZOYs,579
|
|
34
|
+
docforge_cli-0.2.0.dist-info/licenses/LICENSE,sha256=ptj0dMlIQCo0V543Y59JS-LS85XB0elflc8lzEkmBaY,1067
|
|
35
|
+
docforge_cli-0.2.0.dist-info/METADATA,sha256=rWfpmn9hyO2QmPVW9yr2cmirPU_pN9uk8zwCMEHLEsY,10615
|
|
36
|
+
docforge_cli-0.2.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
37
|
+
docforge_cli-0.2.0.dist-info/entry_points.txt,sha256=DEtuKPHBeq5uk_eq_faz2Y4pO9KApeP3UVWrcN72l4g,46
|
|
38
|
+
docforge_cli-0.2.0.dist-info/top_level.txt,sha256=B9iWib2I605hT4bJa5LqDE6RmAdd9ldaW75ODDg9inY,9
|
|
39
|
+
docforge_cli-0.2.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Tobias Ens
|
|
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.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
docforge
|