Update name to gitlore instead of gitlab-inbox
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -30,7 +30,7 @@ yarn-debug.log*
|
|||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
|
|
||||||
# Local config files
|
# Local config files
|
||||||
gi.config.json
|
lore.config.json
|
||||||
|
|
||||||
# beads
|
# beads
|
||||||
.bv/
|
.bv/
|
||||||
|
|||||||
32
AGENTS.md
32
AGENTS.md
@@ -25,46 +25,46 @@ If you aren't 100% sure how to use a third-party library, **SEARCH ONLINE** to f
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## GitLab Inbox Robot Mode
|
## Gitlore Robot Mode
|
||||||
|
|
||||||
The `gi` CLI has a robot mode optimized for AI agent consumption with structured JSON output, meaningful exit codes, and TTY auto-detection.
|
The `lore` CLI has a robot mode optimized for AI agent consumption with structured JSON output, meaningful exit codes, and TTY auto-detection.
|
||||||
|
|
||||||
### Activation
|
### Activation
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Explicit flag
|
# Explicit flag
|
||||||
gi --robot list issues
|
lore --robot list issues
|
||||||
|
|
||||||
# Auto-detection (when stdout is not a TTY)
|
# Auto-detection (when stdout is not a TTY)
|
||||||
gi list issues | jq .
|
lore list issues | jq .
|
||||||
|
|
||||||
# Environment variable
|
# Environment variable
|
||||||
GI_ROBOT=1 gi list issues
|
LORE_ROBOT=true lore list issues
|
||||||
```
|
```
|
||||||
|
|
||||||
### Robot Mode Commands
|
### Robot Mode Commands
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# List issues/MRs with JSON output
|
# List issues/MRs with JSON output
|
||||||
gi --robot list issues --limit=10
|
lore --robot list issues --limit=10
|
||||||
gi --robot list mrs --state=opened
|
lore --robot list mrs --state=opened
|
||||||
|
|
||||||
# Count entities
|
# Count entities
|
||||||
gi --robot count issues
|
lore --robot count issues
|
||||||
gi --robot count discussions --type=mr
|
lore --robot count discussions --type=mr
|
||||||
|
|
||||||
# Show detailed entity info
|
# Show detailed entity info
|
||||||
gi --robot show issue 123
|
lore --robot show issue 123
|
||||||
gi --robot show mr 456 --project=group/repo
|
lore --robot show mr 456 --project=group/repo
|
||||||
|
|
||||||
# Check sync status
|
# Check sync status
|
||||||
gi --robot sync-status
|
lore --robot sync-status
|
||||||
|
|
||||||
# Run ingestion (quiet, JSON summary)
|
# Run ingestion (quiet, JSON summary)
|
||||||
gi --robot ingest --type=issues
|
lore --robot ingest --type=issues
|
||||||
|
|
||||||
# Check environment health
|
# Check environment health
|
||||||
gi --robot doctor
|
lore --robot doctor
|
||||||
```
|
```
|
||||||
|
|
||||||
### Response Format
|
### Response Format
|
||||||
@@ -78,7 +78,7 @@ All commands return consistent JSON:
|
|||||||
Errors return structured JSON to stderr:
|
Errors return structured JSON to stderr:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{"error":{"code":"CONFIG_NOT_FOUND","message":"...","suggestion":"Run 'gi init'"}}
|
{"error":{"code":"CONFIG_NOT_FOUND","message":"...","suggestion":"Run 'lore init'"}}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exit Codes
|
### Exit Codes
|
||||||
@@ -102,7 +102,7 @@ Errors return structured JSON to stderr:
|
|||||||
|
|
||||||
### Best Practices
|
### Best Practices
|
||||||
|
|
||||||
- Use `gi --robot` for all agent interactions
|
- Use `lore --robot` for all agent interactions
|
||||||
- Check exit codes for error handling
|
- Check exit codes for error handling
|
||||||
- Parse JSON errors from stderr
|
- Parse JSON errors from stderr
|
||||||
- Use `--limit` to control response size
|
- Use `--limit` to control response size
|
||||||
|
|||||||
66
Cargo.lock
generated
66
Cargo.lock
generated
@@ -630,39 +630,6 @@ dependencies = [
|
|||||||
"wasip2",
|
"wasip2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "gi"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"async-stream",
|
|
||||||
"chrono",
|
|
||||||
"clap",
|
|
||||||
"comfy-table",
|
|
||||||
"console",
|
|
||||||
"dialoguer",
|
|
||||||
"dirs",
|
|
||||||
"flate2",
|
|
||||||
"futures",
|
|
||||||
"indicatif",
|
|
||||||
"open",
|
|
||||||
"reqwest",
|
|
||||||
"rusqlite",
|
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"sha2",
|
|
||||||
"sqlite-vec",
|
|
||||||
"tempfile",
|
|
||||||
"thiserror",
|
|
||||||
"tokio",
|
|
||||||
"tracing",
|
|
||||||
"tracing-indicatif",
|
|
||||||
"tracing-subscriber",
|
|
||||||
"url",
|
|
||||||
"urlencoding",
|
|
||||||
"uuid",
|
|
||||||
"wiremock",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "h2"
|
name = "h2"
|
||||||
version = "0.4.13"
|
version = "0.4.13"
|
||||||
@@ -1111,6 +1078,39 @@ version = "0.4.29"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lore"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"async-stream",
|
||||||
|
"chrono",
|
||||||
|
"clap",
|
||||||
|
"comfy-table",
|
||||||
|
"console",
|
||||||
|
"dialoguer",
|
||||||
|
"dirs",
|
||||||
|
"flate2",
|
||||||
|
"futures",
|
||||||
|
"indicatif",
|
||||||
|
"open",
|
||||||
|
"reqwest",
|
||||||
|
"rusqlite",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"sha2",
|
||||||
|
"sqlite-vec",
|
||||||
|
"tempfile",
|
||||||
|
"thiserror",
|
||||||
|
"tokio",
|
||||||
|
"tracing",
|
||||||
|
"tracing-indicatif",
|
||||||
|
"tracing-subscriber",
|
||||||
|
"url",
|
||||||
|
"urlencoding",
|
||||||
|
"uuid",
|
||||||
|
"wiremock",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "matchers"
|
name = "matchers"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "gi"
|
name = "lore"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
description = "GitLab Knowledge Engine - semantic search for GitLab issues, MRs, and discussions"
|
description = "Gitlore - Local GitLab data management with semantic search"
|
||||||
authors = ["Taylor Eernisse"]
|
authors = ["Taylor Eernisse"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "gi"
|
name = "lore"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
6
PRD.md
6
PRD.md
@@ -1,8 +1,10 @@
|
|||||||
# GitLab Inbox - Product Requirements Document
|
# Gitlore - Product Requirements Document
|
||||||
|
|
||||||
|
> **Note:** The project was renamed from "gitlab-inbox" to "gitlore" and the CLI from "gi" to "lore".
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
**Product Name**: GitLab Inbox
|
**Product Name**: Gitlore (formerly GitLab Inbox)
|
||||||
**Version**: 1.0
|
**Version**: 1.0
|
||||||
**Author**: Taylor Eernisse
|
**Author**: Taylor Eernisse
|
||||||
**Date**: January 16, 2026
|
**Date**: January 16, 2026
|
||||||
|
|||||||
208
README.md
208
README.md
@@ -1,6 +1,6 @@
|
|||||||
# gi - GitLab Inbox
|
# Gitlore
|
||||||
|
|
||||||
A command-line tool for managing GitLab issues and merge requests locally. Syncs issues, MRs, discussions, and notes from GitLab to a local SQLite database for fast, offline-capable querying and filtering.
|
Local GitLab data management with semantic search. Syncs issues, MRs, discussions, and notes from GitLab to a local SQLite database for fast, offline-capable querying and filtering.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
@@ -22,40 +22,40 @@ Or build from source:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
cargo build --release
|
cargo build --release
|
||||||
./target/release/gi --help
|
./target/release/lore --help
|
||||||
```
|
```
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Initialize configuration (interactive)
|
# Initialize configuration (interactive)
|
||||||
gi init
|
lore init
|
||||||
|
|
||||||
# Verify authentication
|
# Verify authentication
|
||||||
gi auth-test
|
lore auth-test
|
||||||
|
|
||||||
# Sync issues from GitLab
|
# Sync issues from GitLab
|
||||||
gi ingest --type issues
|
lore ingest --type issues
|
||||||
|
|
||||||
# Sync merge requests from GitLab
|
# Sync merge requests from GitLab
|
||||||
gi ingest --type mrs
|
lore ingest --type mrs
|
||||||
|
|
||||||
# List recent issues
|
# List recent issues
|
||||||
gi list issues --limit 10
|
lore list issues --limit 10
|
||||||
|
|
||||||
# List open merge requests
|
# List open merge requests
|
||||||
gi list mrs --state opened
|
lore list mrs --state opened
|
||||||
|
|
||||||
# Show issue details
|
# Show issue details
|
||||||
gi show issue 123 --project group/repo
|
lore show issue 123 --project group/repo
|
||||||
|
|
||||||
# Show MR details with discussions
|
# Show MR details with discussions
|
||||||
gi show mr 456 --project group/repo
|
lore show mr 456 --project group/repo
|
||||||
```
|
```
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
Configuration is stored in `~/.config/gi/config.json` (or `$XDG_CONFIG_HOME/gi/config.json`).
|
Configuration is stored in `~/.config/lore/config.json` (or `$XDG_CONFIG_HOME/lore/config.json`).
|
||||||
|
|
||||||
### Example Configuration
|
### Example Configuration
|
||||||
|
|
||||||
@@ -96,8 +96,8 @@ Configuration is stored in `~/.config/gi/config.json` (or `$XDG_CONFIG_HOME/gi/c
|
|||||||
| `sync` | `cursorRewindSeconds` | `2` | Seconds to rewind cursor for overlap safety |
|
| `sync` | `cursorRewindSeconds` | `2` | Seconds to rewind cursor for overlap safety |
|
||||||
| `sync` | `primaryConcurrency` | `4` | Concurrent GitLab requests for primary resources |
|
| `sync` | `primaryConcurrency` | `4` | Concurrent GitLab requests for primary resources |
|
||||||
| `sync` | `dependentConcurrency` | `2` | Concurrent requests for dependent resources |
|
| `sync` | `dependentConcurrency` | `2` | Concurrent requests for dependent resources |
|
||||||
| `storage` | `dbPath` | `~/.local/share/gi/gi.db` | Database file path |
|
| `storage` | `dbPath` | `~/.local/share/lore/lore.db` | Database file path |
|
||||||
| `storage` | `backupDir` | `~/.local/share/gi/backups` | Backup directory |
|
| `storage` | `backupDir` | `~/.local/share/lore/backups` | Backup directory |
|
||||||
| `storage` | `compressRawPayloads` | `true` | Compress stored API responses with gzip |
|
| `storage` | `compressRawPayloads` | `true` | Compress stored API responses with gzip |
|
||||||
| `embedding` | `provider` | `ollama` | Embedding provider |
|
| `embedding` | `provider` | `ollama` | Embedding provider |
|
||||||
| `embedding` | `model` | `nomic-embed-text` | Model name for embeddings |
|
| `embedding` | `model` | `nomic-embed-text` | Model name for embeddings |
|
||||||
@@ -108,9 +108,9 @@ Configuration is stored in `~/.config/gi/config.json` (or `$XDG_CONFIG_HOME/gi/c
|
|||||||
|
|
||||||
The config file is resolved in this order:
|
The config file is resolved in this order:
|
||||||
1. `--config` CLI flag
|
1. `--config` CLI flag
|
||||||
2. `GI_CONFIG_PATH` environment variable
|
2. `LORE_CONFIG_PATH` environment variable
|
||||||
3. `~/.config/gi/config.json` (XDG default)
|
3. `~/.config/lore/config.json` (XDG default)
|
||||||
4. `./gi.config.json` (local fallback for development)
|
4. `./lore.config.json` (local fallback for development)
|
||||||
|
|
||||||
### GitLab Token
|
### GitLab Token
|
||||||
|
|
||||||
@@ -125,40 +125,40 @@ Create a personal access token with `read_api` scope:
|
|||||||
| Variable | Purpose | Required |
|
| Variable | Purpose | Required |
|
||||||
|----------|---------|----------|
|
|----------|---------|----------|
|
||||||
| `GITLAB_TOKEN` | GitLab API authentication token (name configurable via `gitlab.tokenEnvVar`) | Yes |
|
| `GITLAB_TOKEN` | GitLab API authentication token (name configurable via `gitlab.tokenEnvVar`) | Yes |
|
||||||
| `GI_CONFIG_PATH` | Override config file location | No |
|
| `LORE_CONFIG_PATH` | Override config file location | No |
|
||||||
| `XDG_CONFIG_HOME` | XDG Base Directory for config (fallback: `~/.config`) | No |
|
| `XDG_CONFIG_HOME` | XDG Base Directory for config (fallback: `~/.config`) | No |
|
||||||
| `XDG_DATA_HOME` | XDG Base Directory for data (fallback: `~/.local/share`) | No |
|
| `XDG_DATA_HOME` | XDG Base Directory for data (fallback: `~/.local/share`) | No |
|
||||||
| `RUST_LOG` | Logging level filter (e.g., `gi=debug`) | No |
|
| `RUST_LOG` | Logging level filter (e.g., `lore=debug`) | No |
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
### `gi init`
|
### `lore init`
|
||||||
|
|
||||||
Initialize configuration and database interactively.
|
Initialize configuration and database interactively.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
gi init # Interactive setup
|
lore init # Interactive setup
|
||||||
gi init --force # Overwrite existing config
|
lore init --force # Overwrite existing config
|
||||||
gi init --non-interactive # Fail if prompts needed
|
lore init --non-interactive # Fail if prompts needed
|
||||||
```
|
```
|
||||||
|
|
||||||
### `gi auth-test`
|
### `lore auth-test`
|
||||||
|
|
||||||
Verify GitLab authentication is working.
|
Verify GitLab authentication is working.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
gi auth-test
|
lore auth-test
|
||||||
# Authenticated as @username (Full Name)
|
# Authenticated as @username (Full Name)
|
||||||
# GitLab: https://gitlab.com
|
# GitLab: https://gitlab.com
|
||||||
```
|
```
|
||||||
|
|
||||||
### `gi doctor`
|
### `lore doctor`
|
||||||
|
|
||||||
Check environment health and configuration.
|
Check environment health and configuration.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
gi doctor # Human-readable output
|
lore doctor # Human-readable output
|
||||||
gi doctor --json # JSON output for scripting
|
lore doctor --json # JSON output for scripting
|
||||||
```
|
```
|
||||||
|
|
||||||
Checks performed:
|
Checks performed:
|
||||||
@@ -168,21 +168,21 @@ Checks performed:
|
|||||||
- Project accessibility
|
- Project accessibility
|
||||||
- Ollama connectivity (optional)
|
- Ollama connectivity (optional)
|
||||||
|
|
||||||
### `gi ingest`
|
### `lore ingest`
|
||||||
|
|
||||||
Sync data from GitLab to local database.
|
Sync data from GitLab to local database.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Issues
|
# Issues
|
||||||
gi ingest --type issues # Sync all projects
|
lore ingest --type issues # Sync all projects
|
||||||
gi ingest --type issues --project group/repo # Single project
|
lore ingest --type issues --project group/repo # Single project
|
||||||
gi ingest --type issues --force # Override stale lock
|
lore ingest --type issues --force # Override stale lock
|
||||||
gi ingest --type issues --full # Full re-sync (reset cursors)
|
lore ingest --type issues --full # Full re-sync (reset cursors)
|
||||||
|
|
||||||
# Merge Requests
|
# Merge Requests
|
||||||
gi ingest --type mrs # Sync all projects
|
lore ingest --type mrs # Sync all projects
|
||||||
gi ingest --type mrs --project group/repo # Single project
|
lore ingest --type mrs --project group/repo # Single project
|
||||||
gi ingest --type mrs --full # Full re-sync (reset cursors)
|
lore ingest --type mrs --full # Full re-sync (reset cursors)
|
||||||
```
|
```
|
||||||
|
|
||||||
The `--full` flag resets sync cursors and discussion watermarks, then fetches all data from scratch. Useful when:
|
The `--full` flag resets sync cursors and discussion watermarks, then fetches all data from scratch. Useful when:
|
||||||
@@ -190,103 +190,103 @@ The `--full` flag resets sync cursors and discussion watermarks, then fetches al
|
|||||||
- You want to ensure complete data after schema changes
|
- You want to ensure complete data after schema changes
|
||||||
- Troubleshooting sync issues
|
- Troubleshooting sync issues
|
||||||
|
|
||||||
### `gi list issues`
|
### `lore list issues`
|
||||||
|
|
||||||
Query issues from local database.
|
Query issues from local database.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
gi list issues # Recent issues (default 50)
|
lore list issues # Recent issues (default 50)
|
||||||
gi list issues --limit 100 # More results
|
lore list issues --limit 100 # More results
|
||||||
gi list issues --state opened # Only open issues
|
lore list issues --state opened # Only open issues
|
||||||
gi list issues --state closed # Only closed issues
|
lore list issues --state closed # Only closed issues
|
||||||
gi list issues --author username # By author (@ prefix optional)
|
lore list issues --author username # By author (@ prefix optional)
|
||||||
gi list issues --assignee username # By assignee (@ prefix optional)
|
lore list issues --assignee username # By assignee (@ prefix optional)
|
||||||
gi list issues --label bug # By label (AND logic)
|
lore list issues --label bug # By label (AND logic)
|
||||||
gi list issues --label bug --label urgent # Multiple labels
|
lore list issues --label bug --label urgent # Multiple labels
|
||||||
gi list issues --milestone "v1.0" # By milestone title
|
lore list issues --milestone "v1.0" # By milestone title
|
||||||
gi list issues --since 7d # Updated in last 7 days
|
lore list issues --since 7d # Updated in last 7 days
|
||||||
gi list issues --since 2w # Updated in last 2 weeks
|
lore list issues --since 2w # Updated in last 2 weeks
|
||||||
gi list issues --since 2024-01-01 # Updated since date
|
lore list issues --since 2024-01-01 # Updated since date
|
||||||
gi list issues --due-before 2024-12-31 # Due before date
|
lore list issues --due-before 2024-12-31 # Due before date
|
||||||
gi list issues --has-due-date # Only issues with due dates
|
lore list issues --has-due-date # Only issues with due dates
|
||||||
gi list issues --project group/repo # Filter by project
|
lore list issues --project group/repo # Filter by project
|
||||||
gi list issues --sort created --order asc # Sort options
|
lore list issues --sort created --order asc # Sort options
|
||||||
gi list issues --open # Open first result in browser
|
lore list issues --open # Open first result in browser
|
||||||
gi list issues --json # JSON output
|
lore list issues --json # JSON output
|
||||||
```
|
```
|
||||||
|
|
||||||
Output includes: IID, title, state, author, assignee, labels, and update time.
|
Output includes: IID, title, state, author, assignee, labels, and update time.
|
||||||
|
|
||||||
### `gi list mrs`
|
### `lore list mrs`
|
||||||
|
|
||||||
Query merge requests from local database.
|
Query merge requests from local database.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
gi list mrs # Recent MRs (default 50)
|
lore list mrs # Recent MRs (default 50)
|
||||||
gi list mrs --limit 100 # More results
|
lore list mrs --limit 100 # More results
|
||||||
gi list mrs --state opened # Only open MRs
|
lore list mrs --state opened # Only open MRs
|
||||||
gi list mrs --state merged # Only merged MRs
|
lore list mrs --state merged # Only merged MRs
|
||||||
gi list mrs --state closed # Only closed MRs
|
lore list mrs --state closed # Only closed MRs
|
||||||
gi list mrs --state locked # Only locked MRs
|
lore list mrs --state locked # Only locked MRs
|
||||||
gi list mrs --state all # All states
|
lore list mrs --state all # All states
|
||||||
gi list mrs --author username # By author (@ prefix optional)
|
lore list mrs --author username # By author (@ prefix optional)
|
||||||
gi list mrs --assignee username # By assignee (@ prefix optional)
|
lore list mrs --assignee username # By assignee (@ prefix optional)
|
||||||
gi list mrs --reviewer username # By reviewer (@ prefix optional)
|
lore list mrs --reviewer username # By reviewer (@ prefix optional)
|
||||||
gi list mrs --draft # Only draft/WIP MRs
|
lore list mrs --draft # Only draft/WIP MRs
|
||||||
gi list mrs --no-draft # Exclude draft MRs
|
lore list mrs --no-draft # Exclude draft MRs
|
||||||
gi list mrs --target-branch main # By target branch
|
lore list mrs --target-branch main # By target branch
|
||||||
gi list mrs --source-branch feature/foo # By source branch
|
lore list mrs --source-branch feature/foo # By source branch
|
||||||
gi list mrs --label needs-review # By label (AND logic)
|
lore list mrs --label needs-review # By label (AND logic)
|
||||||
gi list mrs --since 7d # Updated in last 7 days
|
lore list mrs --since 7d # Updated in last 7 days
|
||||||
gi list mrs --project group/repo # Filter by project
|
lore list mrs --project group/repo # Filter by project
|
||||||
gi list mrs --sort created --order asc # Sort options
|
lore list mrs --sort created --order asc # Sort options
|
||||||
gi list mrs --open # Open first result in browser
|
lore list mrs --open # Open first result in browser
|
||||||
gi list mrs --json # JSON output
|
lore list mrs --json # JSON output
|
||||||
```
|
```
|
||||||
|
|
||||||
Output includes: IID, title (with [DRAFT] prefix if applicable), state, author, assignee, labels, and update time.
|
Output includes: IID, title (with [DRAFT] prefix if applicable), state, author, assignee, labels, and update time.
|
||||||
|
|
||||||
### `gi show issue`
|
### `lore show issue`
|
||||||
|
|
||||||
Display detailed issue information.
|
Display detailed issue information.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
gi show issue 123 # Show issue #123
|
lore show issue 123 # Show issue #123
|
||||||
gi show issue 123 --project group/repo # Disambiguate if needed
|
lore show issue 123 --project group/repo # Disambiguate if needed
|
||||||
```
|
```
|
||||||
|
|
||||||
Shows: title, description, state, author, assignees, labels, milestone, due date, web URL, and threaded discussions.
|
Shows: title, description, state, author, assignees, labels, milestone, due date, web URL, and threaded discussions.
|
||||||
|
|
||||||
### `gi show mr`
|
### `lore show mr`
|
||||||
|
|
||||||
Display detailed merge request information.
|
Display detailed merge request information.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
gi show mr 456 # Show MR !456
|
lore show mr 456 # Show MR !456
|
||||||
gi show mr 456 --project group/repo # Disambiguate if needed
|
lore show mr 456 --project group/repo # Disambiguate if needed
|
||||||
```
|
```
|
||||||
|
|
||||||
Shows: title, description, state, draft status, author, assignees, reviewers, labels, source/target branches, merge status, web URL, and threaded discussions. Inline code review comments (DiffNotes) display file context in the format `[src/file.ts:45]`.
|
Shows: title, description, state, draft status, author, assignees, reviewers, labels, source/target branches, merge status, web URL, and threaded discussions. Inline code review comments (DiffNotes) display file context in the format `[src/file.ts:45]`.
|
||||||
|
|
||||||
### `gi count`
|
### `lore count`
|
||||||
|
|
||||||
Count entities in local database.
|
Count entities in local database.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
gi count issues # Total issues
|
lore count issues # Total issues
|
||||||
gi count mrs # Total MRs (with state breakdown)
|
lore count mrs # Total MRs (with state breakdown)
|
||||||
gi count discussions # Total discussions
|
lore count discussions # Total discussions
|
||||||
gi count discussions --type issue # Issue discussions only
|
lore count discussions --type issue # Issue discussions only
|
||||||
gi count discussions --type mr # MR discussions only
|
lore count discussions --type mr # MR discussions only
|
||||||
gi count notes # Total notes (shows system vs user breakdown)
|
lore count notes # Total notes (shows system vs user breakdown)
|
||||||
```
|
```
|
||||||
|
|
||||||
### `gi sync-status`
|
### `lore sync-status`
|
||||||
|
|
||||||
Show current sync state and watermarks.
|
Show current sync state and watermarks.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
gi sync-status
|
lore sync-status
|
||||||
```
|
```
|
||||||
|
|
||||||
Displays:
|
Displays:
|
||||||
@@ -294,40 +294,40 @@ Displays:
|
|||||||
- Cursor positions per project and resource type (issues and MRs)
|
- Cursor positions per project and resource type (issues and MRs)
|
||||||
- Data summary counts
|
- Data summary counts
|
||||||
|
|
||||||
### `gi migrate`
|
### `lore migrate`
|
||||||
|
|
||||||
Run pending database migrations.
|
Run pending database migrations.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
gi migrate
|
lore migrate
|
||||||
```
|
```
|
||||||
|
|
||||||
Shows current schema version and applies any pending migrations.
|
Shows current schema version and applies any pending migrations.
|
||||||
|
|
||||||
### `gi version`
|
### `lore version`
|
||||||
|
|
||||||
Show version information.
|
Show version information.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
gi version
|
lore version
|
||||||
```
|
```
|
||||||
|
|
||||||
### `gi backup`
|
### `lore backup`
|
||||||
|
|
||||||
Create timestamped database backup.
|
Create timestamped database backup.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
gi backup
|
lore backup
|
||||||
```
|
```
|
||||||
|
|
||||||
*Note: Not yet implemented.*
|
*Note: Not yet implemented.*
|
||||||
|
|
||||||
### `gi reset`
|
### `lore reset`
|
||||||
|
|
||||||
Delete database and reset all state.
|
Delete database and reset all state.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
gi reset --confirm
|
lore reset --confirm
|
||||||
```
|
```
|
||||||
|
|
||||||
*Note: Not yet implemented.*
|
*Note: Not yet implemented.*
|
||||||
@@ -356,12 +356,12 @@ Data is stored in SQLite with WAL mode and foreign keys enabled. Main tables:
|
|||||||
| `raw_payloads` | Compressed original API responses |
|
| `raw_payloads` | Compressed original API responses |
|
||||||
| `schema_version` | Migration version tracking |
|
| `schema_version` | Migration version tracking |
|
||||||
|
|
||||||
The database is stored at `~/.local/share/gi/gi.db` by default (XDG compliant).
|
The database is stored at `~/.local/share/lore/lore.db` by default (XDG compliant).
|
||||||
|
|
||||||
## Global Options
|
## Global Options
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
gi --config /path/to/config.json <command> # Use alternate config
|
lore --config /path/to/config.json <command> # Use alternate config
|
||||||
```
|
```
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
@@ -371,10 +371,10 @@ gi --config /path/to/config.json <command> # Use alternate config
|
|||||||
cargo test
|
cargo test
|
||||||
|
|
||||||
# Run with debug logging
|
# Run with debug logging
|
||||||
RUST_LOG=gi=debug gi list issues
|
RUST_LOG=lore=debug lore list issues
|
||||||
|
|
||||||
# Run with trace logging
|
# Run with trace logging
|
||||||
RUST_LOG=gi=trace gi ingest --type issues
|
RUST_LOG=lore=trace lore ingest --type issues
|
||||||
|
|
||||||
# Check formatting
|
# Check formatting
|
||||||
cargo fmt --check
|
cargo fmt --check
|
||||||
@@ -396,7 +396,7 @@ cargo clippy
|
|||||||
|
|
||||||
## Current Status
|
## Current Status
|
||||||
|
|
||||||
This is Checkpoint 2 (CP2) of the GitLab Knowledge Engine project. Currently implemented:
|
This is Checkpoint 2 (CP2) of the Gitlore project. Currently implemented:
|
||||||
|
|
||||||
- Issue ingestion with cursor-based incremental sync
|
- Issue ingestion with cursor-based incremental sync
|
||||||
- Merge request ingestion with cursor-based incremental sync
|
- Merge request ingestion with cursor-based incremental sync
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# SPEC.md Revision Document - Round 2
|
# SPEC.md Revision Document - Round 2
|
||||||
|
|
||||||
|
> **Note:** The project was renamed from "gitlab-inbox" to "gitlore" and the CLI from "gi" to "lore". References to "gi" in this document should be read as "lore".
|
||||||
|
|
||||||
This document provides git-diff style changes for the second round of improvements from ChatGPT's review. These are primarily correctness fixes and optimizations.
|
This document provides git-diff style changes for the second round of improvements from ChatGPT's review. These are primarily correctness fixes and optimizations.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# SPEC.md Revisions - First-Time User Experience
|
# SPEC.md Revisions - First-Time User Experience
|
||||||
|
|
||||||
|
> **Note:** The project was renamed from "gitlab-inbox" to "gitlore" and the CLI from "gi" to "lore". References to "gi" in this document should be read as "lore".
|
||||||
|
|
||||||
**Date:** 2026-01-21
|
**Date:** 2026-01-21
|
||||||
**Purpose:** Document all changes adding installation, setup, and user flow documentation to SPEC.md
|
**Purpose:** Document all changes adding installation, setup, and user flow documentation to SPEC.md
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# SPEC.md Revision Document
|
# SPEC.md Revision Document
|
||||||
|
|
||||||
|
> **Note:** The project was renamed from "gitlab-inbox" to "gitlore" and the CLI from "gi" to "lore". References to "gi" in this document should be read as "lore".
|
||||||
|
|
||||||
This document provides git-diff style changes to integrate improvements from ChatGPT's review into the original SPEC.md. The goal is a "best of all worlds" hybrid that maintains the original architecture while adding production-grade hardening.
|
This document provides git-diff style changes to integrate improvements from ChatGPT's review into the original SPEC.md. The goal is a "best of all worlds" hybrid that maintains the original architecture while adding production-grade hardening.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
4
SPEC.md
4
SPEC.md
@@ -1,6 +1,6 @@
|
|||||||
# GitLab Knowledge Engine - Spec Document
|
# Gitlore - Spec Document
|
||||||
|
|
||||||
> **Note:** This is a historical planning document. The actual implementation uses Rust instead of TypeScript/Node.js. See [README.md](README.md) for current documentation.
|
> **Note:** This is a historical planning document. The actual implementation uses Rust instead of TypeScript/Node.js. See [README.md](README.md) for current documentation. The project was renamed from "gitlab-inbox" to "gitlore" and the CLI from "gi" to "lore".
|
||||||
|
|
||||||
## Executive Summary
|
## Executive Summary
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# Checkpoint 0: Project Setup - PRD
|
# Checkpoint 0: Project Setup - PRD
|
||||||
|
|
||||||
|
> **Note:** The project was renamed from "gitlab-inbox" to "gitlore" and the CLI from "gi" to "lore". References to "gi" in this document should be read as "lore".
|
||||||
|
|
||||||
**Version:** 1.0
|
**Version:** 1.0
|
||||||
**Status:** Ready for Implementation
|
**Status:** Ready for Implementation
|
||||||
**Depends On:** None (first checkpoint)
|
**Depends On:** None (first checkpoint)
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# Checkpoint 1: Issue Ingestion - PRD
|
# Checkpoint 1: Issue Ingestion - PRD
|
||||||
|
|
||||||
|
> **Note:** The project was renamed from "gitlab-inbox" to "gitlore" and the CLI from "gi" to "lore". References to "gi" in this document should be read as "lore".
|
||||||
|
|
||||||
**Version:** 2.0
|
**Version:** 2.0
|
||||||
**Status:** Ready for Implementation
|
**Status:** Ready for Implementation
|
||||||
**Depends On:** Checkpoint 0 (Project Setup)
|
**Depends On:** Checkpoint 0 (Project Setup)
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# Checkpoint 2: MR Ingestion - PRD
|
# Checkpoint 2: MR Ingestion - PRD
|
||||||
|
|
||||||
|
> **Note:** The project was renamed from "gitlab-inbox" to "gitlore" and the CLI from "gi" to "lore". References to "gi" in this document should be read as "lore".
|
||||||
|
|
||||||
**Version:** 1.3
|
**Version:** 1.3
|
||||||
**Status:** Ready for Implementation
|
**Status:** Ready for Implementation
|
||||||
**Depends On:** Checkpoint 1 (Issue Ingestion)
|
**Depends On:** Checkpoint 1 (Issue Ingestion)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,7 @@
|
|||||||
# CP1 ↔ CP2 Alignment Audit
|
# CP1 ↔ CP2 Alignment Audit
|
||||||
|
|
||||||
|
> **Note:** The project was renamed from "gitlab-inbox" to "gitlore" and the CLI from "gi" to "lore". References to "gi" in this document should be read as "lore".
|
||||||
|
|
||||||
**Created:** 2026-01-26
|
**Created:** 2026-01-26
|
||||||
**Purpose:** Document deviations between CP1 (Issue Ingestion) and CP2 (MR Ingestion) PRDs that could cause implementation drift. Use this checklist to verify alignment before CP2 implementation.
|
**Purpose:** Document deviations between CP1 (Issue Ingestion) and CP2 (MR Ingestion) PRDs that could cause implementation drift. Use this checklist to verify alignment before CP2 implementation.
|
||||||
|
|
||||||
|
|||||||
@@ -2,19 +2,19 @@
|
|||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
Robot mode optimizes the `gi` CLI for AI agent consumption with structured JSON output, meaningful exit codes, and token-efficient responses.
|
Robot mode optimizes the `lore` CLI for AI agent consumption with structured JSON output, meaningful exit codes, and token-efficient responses.
|
||||||
|
|
||||||
## Activation
|
## Activation
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Explicit flag
|
# Explicit flag
|
||||||
gi --robot list issues
|
lore --robot list issues
|
||||||
|
|
||||||
# Auto-detection (when stdout is not a TTY)
|
# Auto-detection (when stdout is not a TTY)
|
||||||
gi list issues | jq .
|
lore list issues | jq .
|
||||||
|
|
||||||
# Environment variable
|
# Environment variable
|
||||||
GI_ROBOT=1 gi list issues
|
LORE_ROBOT=true lore list issues
|
||||||
```
|
```
|
||||||
|
|
||||||
## Global Flags
|
## Global Flags
|
||||||
@@ -51,8 +51,8 @@ When `--robot` is active, errors are JSON on stderr:
|
|||||||
{
|
{
|
||||||
"error": {
|
"error": {
|
||||||
"code": "CONFIG_NOT_FOUND",
|
"code": "CONFIG_NOT_FOUND",
|
||||||
"message": "Config file not found at ~/.config/gi/config.toml",
|
"message": "Config file not found at ~/.config/lore/config.toml",
|
||||||
"suggestion": "Run 'gi init' to create configuration"
|
"suggestion": "Run 'lore init' to create configuration"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -75,7 +75,7 @@ All commands return consistent JSON structure:
|
|||||||
|
|
||||||
## Command-Specific Output
|
## Command-Specific Output
|
||||||
|
|
||||||
### gi list issues --robot
|
### lore list issues --robot
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -100,7 +100,7 @@ All commands return consistent JSON structure:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### gi show issue 123 --robot
|
### lore show issue 123 --robot
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -134,7 +134,7 @@ All commands return consistent JSON structure:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### gi ingest --type issues --robot
|
### lore ingest --type issues --robot
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -157,7 +157,7 @@ All commands return consistent JSON structure:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### gi count issues --robot
|
### lore count issues --robot
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -173,7 +173,7 @@ All commands return consistent JSON structure:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### gi doctor --robot
|
### lore doctor --robot
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -181,7 +181,7 @@ All commands return consistent JSON structure:
|
|||||||
"data": {
|
"data": {
|
||||||
"success": true,
|
"success": true,
|
||||||
"checks": {
|
"checks": {
|
||||||
"config": { "status": "ok", "path": "~/.config/gi/config.toml" },
|
"config": { "status": "ok", "path": "~/.config/lore/config.toml" },
|
||||||
"database": { "status": "ok", "version": 6 },
|
"database": { "status": "ok", "version": 6 },
|
||||||
"gitlab": { "status": "ok", "user": "username" },
|
"gitlab": { "status": "ok", "user": "username" },
|
||||||
"projects": [
|
"projects": [
|
||||||
@@ -192,7 +192,7 @@ All commands return consistent JSON structure:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### gi sync-status --robot
|
### lore sync-status --robot
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ fn check_database(config: Option<&Config>) -> DatabaseCheck {
|
|||||||
return DatabaseCheck {
|
return DatabaseCheck {
|
||||||
result: CheckResult {
|
result: CheckResult {
|
||||||
status: CheckStatus::Error,
|
status: CheckStatus::Error,
|
||||||
message: Some("Database file not found. Run \"gi init\" first.".to_string()),
|
message: Some("Database file not found. Run \"lore init\" first.".to_string()),
|
||||||
},
|
},
|
||||||
path: Some(db_path.display().to_string()),
|
path: Some(db_path.display().to_string()),
|
||||||
schema_version: None,
|
schema_version: None,
|
||||||
@@ -302,7 +302,7 @@ fn check_projects(config: Option<&Config>) -> ProjectsCheck {
|
|||||||
return ProjectsCheck {
|
return ProjectsCheck {
|
||||||
result: CheckResult {
|
result: CheckResult {
|
||||||
status: CheckStatus::Error,
|
status: CheckStatus::Error,
|
||||||
message: Some("Database not found. Run \"gi init\" first.".to_string()),
|
message: Some("Database not found. Run \"lore init\" first.".to_string()),
|
||||||
},
|
},
|
||||||
configured: Some(configured),
|
configured: Some(configured),
|
||||||
resolved: Some(0),
|
resolved: Some(0),
|
||||||
@@ -320,7 +320,7 @@ fn check_projects(config: Option<&Config>) -> ProjectsCheck {
|
|||||||
result: CheckResult {
|
result: CheckResult {
|
||||||
status: CheckStatus::Error,
|
status: CheckStatus::Error,
|
||||||
message: Some(format!(
|
message: Some(format!(
|
||||||
"{configured} configured, 0 resolved. Run \"gi init\" to resolve projects."
|
"{configured} configured, 0 resolved. Run \"lore init\" to resolve projects."
|
||||||
)),
|
)),
|
||||||
},
|
},
|
||||||
configured: Some(configured),
|
configured: Some(configured),
|
||||||
@@ -459,7 +459,7 @@ async fn check_ollama(config: Option<&Config>) -> OllamaCheck {
|
|||||||
|
|
||||||
/// Format and print doctor results to console.
|
/// Format and print doctor results to console.
|
||||||
pub fn print_doctor_results(result: &DoctorResult) {
|
pub fn print_doctor_results(result: &DoctorResult) {
|
||||||
println!("\ngi doctor\n");
|
println!("\nlore doctor\n");
|
||||||
|
|
||||||
print_check("Config", &result.checks.config.result);
|
print_check("Config", &result.checks.config.result);
|
||||||
print_check("Database", &result.checks.database.result);
|
print_check("Database", &result.checks.database.result);
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ pub async fn run_ingest(
|
|||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
return Err(GiError::Other(
|
return Err(GiError::Other(
|
||||||
"No projects configured. Run 'gi init' first.".to_string(),
|
"No projects configured. Run 'lore init' first.".to_string(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ pub async fn run_init(inputs: InitInputs, options: InitOptions) -> Result<InitRe
|
|||||||
// 7. Create data directory and initialize database
|
// 7. Create data directory and initialize database
|
||||||
fs::create_dir_all(&data_dir)?;
|
fs::create_dir_all(&data_dir)?;
|
||||||
|
|
||||||
let db_path = data_dir.join("gi.db");
|
let db_path = data_dir.join("lore.db");
|
||||||
let conn = create_connection(&db_path)?;
|
let conn = create_connection(&db_path)?;
|
||||||
|
|
||||||
// Run embedded migrations
|
// Run embedded migrations
|
||||||
|
|||||||
@@ -298,7 +298,7 @@ pub fn print_sync_status(result: &SyncStatusResult) {
|
|||||||
println!(" {}", style("No sync runs recorded yet.").dim());
|
println!(" {}", style("No sync runs recorded yet.").dim());
|
||||||
println!(
|
println!(
|
||||||
" {}",
|
" {}",
|
||||||
style("Run 'gi ingest --type=issues' to start.").dim()
|
style("Run 'lore ingest --type=issues' to start.").dim()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ pub mod commands;
|
|||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use std::io::IsTerminal;
|
use std::io::IsTerminal;
|
||||||
|
|
||||||
/// GitLab Inbox - Unified notification management
|
/// Gitlore - Local GitLab data management with semantic search
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[command(name = "gi")]
|
#[command(name = "lore")]
|
||||||
#[command(version, about, long_about = None)]
|
#[command(version, about, long_about = None)]
|
||||||
pub struct Cli {
|
pub struct Cli {
|
||||||
/// Path to config file
|
/// Path to config file
|
||||||
@@ -15,7 +15,7 @@ pub struct Cli {
|
|||||||
pub config: Option<String>,
|
pub config: Option<String>,
|
||||||
|
|
||||||
/// Machine-readable JSON output (auto-enabled when piped)
|
/// Machine-readable JSON output (auto-enabled when piped)
|
||||||
#[arg(long, global = true, env = "GI_ROBOT")]
|
#[arg(long, global = true, env = "LORE_ROBOT")]
|
||||||
pub robot: bool,
|
pub robot: bool,
|
||||||
|
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ pub fn run_migrations_from_dir(conn: &Connection, migrations_dir: &Path) -> Resu
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Verify database pragmas are set correctly.
|
/// Verify database pragmas are set correctly.
|
||||||
/// Used by gi doctor command.
|
/// Used by lore doctor command.
|
||||||
pub fn verify_pragmas(conn: &Connection) -> (bool, Vec<String>) {
|
pub fn verify_pragmas(conn: &Connection) -> (bool, Vec<String>) {
|
||||||
let mut issues = Vec::new();
|
let mut issues = Vec::new();
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//! Custom error types for gitlab-inbox.
|
//! Custom error types for gitlore.
|
||||||
//!
|
//!
|
||||||
//! Uses thiserror for ergonomic error definitions with structured error codes.
|
//! Uses thiserror for ergonomic error definitions with structured error codes.
|
||||||
|
|
||||||
@@ -65,10 +65,10 @@ impl ErrorCode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Main error type for gitlab-inbox.
|
/// Main error type for gitlore.
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum GiError {
|
pub enum GiError {
|
||||||
#[error("Config file not found at {path}. Run \"gi init\" first.")]
|
#[error("Config file not found at {path}. Run \"lore init\" first.")]
|
||||||
ConfigNotFound { path: String },
|
ConfigNotFound { path: String },
|
||||||
|
|
||||||
#[error("Invalid config: {details}")]
|
#[error("Invalid config: {details}")]
|
||||||
@@ -158,18 +158,18 @@ impl GiError {
|
|||||||
/// Get a suggestion for how to fix this error.
|
/// Get a suggestion for how to fix this error.
|
||||||
pub fn suggestion(&self) -> Option<&'static str> {
|
pub fn suggestion(&self) -> Option<&'static str> {
|
||||||
match self {
|
match self {
|
||||||
Self::ConfigNotFound { .. } => Some("Run 'gi init' to create configuration"),
|
Self::ConfigNotFound { .. } => Some("Run 'lore init' to create configuration"),
|
||||||
Self::ConfigInvalid { .. } => Some("Check config file syntax or run 'gi init' to recreate"),
|
Self::ConfigInvalid { .. } => Some("Check config file syntax or run 'lore init' to recreate"),
|
||||||
Self::GitLabAuthFailed => Some("Verify token has read_api scope and is not expired"),
|
Self::GitLabAuthFailed => Some("Verify token has read_api scope and is not expired"),
|
||||||
Self::GitLabNotFound { .. } => Some("Check the resource path exists and you have access"),
|
Self::GitLabNotFound { .. } => Some("Check the resource path exists and you have access"),
|
||||||
Self::GitLabRateLimited { .. } => Some("Wait and retry, or reduce request frequency"),
|
Self::GitLabRateLimited { .. } => Some("Wait and retry, or reduce request frequency"),
|
||||||
Self::GitLabNetworkError { .. } => Some("Check network connection and GitLab URL"),
|
Self::GitLabNetworkError { .. } => Some("Check network connection and GitLab URL"),
|
||||||
Self::DatabaseLocked { .. } => Some("Wait for other sync to complete or use --force"),
|
Self::DatabaseLocked { .. } => Some("Wait for other sync to complete or use --force"),
|
||||||
Self::MigrationFailed { .. } => Some("Check database file permissions or reset with 'gi reset'"),
|
Self::MigrationFailed { .. } => Some("Check database file permissions or reset with 'lore reset'"),
|
||||||
Self::TokenNotSet { .. } => Some("Export the token environment variable"),
|
Self::TokenNotSet { .. } => Some("Export the token environment variable"),
|
||||||
Self::Database(_) => Some("Check database file permissions or reset with 'gi reset'"),
|
Self::Database(_) => Some("Check database file permissions or reset with 'lore reset'"),
|
||||||
Self::Http(_) => Some("Check network connection"),
|
Self::Http(_) => Some("Check network connection"),
|
||||||
Self::NotFound(_) => Some("Verify the entity exists using 'gi list'"),
|
Self::NotFound(_) => Some("Verify the entity exists using 'lore list'"),
|
||||||
Self::Ambiguous(_) => Some("Use --project flag to disambiguate"),
|
Self::Ambiguous(_) => Some("Use --project flag to disambiguate"),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ use std::path::PathBuf;
|
|||||||
///
|
///
|
||||||
/// Resolution order:
|
/// Resolution order:
|
||||||
/// 1. CLI flag override (if provided)
|
/// 1. CLI flag override (if provided)
|
||||||
/// 2. GI_CONFIG_PATH environment variable
|
/// 2. LORE_CONFIG_PATH environment variable
|
||||||
/// 3. XDG default (~/.config/gi/config.json)
|
/// 3. XDG default (~/.config/lore/config.json)
|
||||||
/// 4. Local fallback (./gi.config.json) if exists
|
/// 4. Local fallback (./lore.config.json) if exists
|
||||||
/// 5. Returns XDG default even if not exists
|
/// 5. Returns XDG default even if not exists
|
||||||
pub fn get_config_path(cli_override: Option<&str>) -> PathBuf {
|
pub fn get_config_path(cli_override: Option<&str>) -> PathBuf {
|
||||||
// 1. CLI flag override
|
// 1. CLI flag override
|
||||||
@@ -17,18 +17,18 @@ pub fn get_config_path(cli_override: Option<&str>) -> PathBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2. Environment variable
|
// 2. Environment variable
|
||||||
if let Ok(path) = std::env::var("GI_CONFIG_PATH") {
|
if let Ok(path) = std::env::var("LORE_CONFIG_PATH") {
|
||||||
return PathBuf::from(path);
|
return PathBuf::from(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. XDG default
|
// 3. XDG default
|
||||||
let xdg_path = get_xdg_config_dir().join("gi").join("config.json");
|
let xdg_path = get_xdg_config_dir().join("lore").join("config.json");
|
||||||
if xdg_path.exists() {
|
if xdg_path.exists() {
|
||||||
return xdg_path;
|
return xdg_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Local fallback (for development)
|
// 4. Local fallback (for development)
|
||||||
let local_path = PathBuf::from("gi.config.json");
|
let local_path = PathBuf::from("lore.config.json");
|
||||||
if local_path.exists() {
|
if local_path.exists() {
|
||||||
return local_path;
|
return local_path;
|
||||||
}
|
}
|
||||||
@@ -38,9 +38,9 @@ pub fn get_config_path(cli_override: Option<&str>) -> PathBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the data directory path.
|
/// Get the data directory path.
|
||||||
/// Uses XDG_DATA_HOME or defaults to ~/.local/share/gi
|
/// Uses XDG_DATA_HOME or defaults to ~/.local/share/lore
|
||||||
pub fn get_data_dir() -> PathBuf {
|
pub fn get_data_dir() -> PathBuf {
|
||||||
get_xdg_data_dir().join("gi")
|
get_xdg_data_dir().join("lore")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the database file path.
|
/// Get the database file path.
|
||||||
@@ -49,7 +49,7 @@ pub fn get_db_path(config_override: Option<&str>) -> PathBuf {
|
|||||||
if let Some(path) = config_override {
|
if let Some(path) = config_override {
|
||||||
return PathBuf::from(path);
|
return PathBuf::from(path);
|
||||||
}
|
}
|
||||||
get_data_dir().join("gi.db")
|
get_data_dir().join("lore.db")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the backup directory path.
|
/// Get the backup directory path.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
//! GitLab Inbox - Semantic search for GitLab issues, MRs, and discussions.
|
//! Gitlore - Semantic search for GitLab issues, MRs, and discussions.
|
||||||
//!
|
//!
|
||||||
//! A self-hosted CLI tool that consolidates GitLab notifications into a unified inbox
|
//! A self-hosted CLI tool that syncs GitLab data to a local SQLite database
|
||||||
//! with semantic search capabilities.
|
//! with fast querying and semantic search capabilities.
|
||||||
|
|
||||||
pub mod cli;
|
pub mod cli;
|
||||||
pub mod core;
|
pub mod core;
|
||||||
|
|||||||
30
src/main.rs
30
src/main.rs
@@ -1,4 +1,4 @@
|
|||||||
//! GitLab Inbox CLI entry point.
|
//! Gitlore CLI entry point.
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use console::style;
|
use console::style;
|
||||||
@@ -8,8 +8,8 @@ use tracing_subscriber::EnvFilter;
|
|||||||
use tracing_subscriber::layer::SubscriberExt;
|
use tracing_subscriber::layer::SubscriberExt;
|
||||||
use tracing_subscriber::util::SubscriberInitExt;
|
use tracing_subscriber::util::SubscriberInitExt;
|
||||||
|
|
||||||
use gi::Config;
|
use lore::Config;
|
||||||
use gi::cli::commands::{
|
use lore::cli::commands::{
|
||||||
InitInputs, InitOptions, ListFilters, MrListFilters, open_issue_in_browser, open_mr_in_browser,
|
InitInputs, InitOptions, ListFilters, MrListFilters, open_issue_in_browser, open_mr_in_browser,
|
||||||
print_count, print_count_json, print_doctor_results, print_ingest_summary,
|
print_count, print_count_json, print_doctor_results, print_ingest_summary,
|
||||||
print_ingest_summary_json, print_list_issues, print_list_issues_json, print_list_mrs,
|
print_ingest_summary_json, print_list_issues, print_list_issues_json, print_list_mrs,
|
||||||
@@ -18,11 +18,11 @@ use gi::cli::commands::{
|
|||||||
run_doctor, run_ingest, run_init, run_list_issues, run_list_mrs, run_show_issue, run_show_mr,
|
run_doctor, run_ingest, run_init, run_list_issues, run_list_mrs, run_show_issue, run_show_mr,
|
||||||
run_sync_status,
|
run_sync_status,
|
||||||
};
|
};
|
||||||
use gi::cli::{Cli, Commands};
|
use lore::cli::{Cli, Commands};
|
||||||
use gi::core::db::{create_connection, get_schema_version, run_migrations};
|
use lore::core::db::{create_connection, get_schema_version, run_migrations};
|
||||||
use gi::core::error::{GiError, RobotErrorOutput};
|
use lore::core::error::{GiError, RobotErrorOutput};
|
||||||
use gi::core::paths::get_config_path;
|
use lore::core::paths::get_config_path;
|
||||||
use gi::core::paths::get_db_path;
|
use lore::core::paths::get_db_path;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
@@ -37,7 +37,7 @@ async fn main() {
|
|||||||
)
|
)
|
||||||
.with(
|
.with(
|
||||||
EnvFilter::from_default_env()
|
EnvFilter::from_default_env()
|
||||||
.add_directive("gi=info".parse().unwrap())
|
.add_directive("lore=info".parse().unwrap())
|
||||||
.add_directive("warn".parse().unwrap()),
|
.add_directive("warn".parse().unwrap()),
|
||||||
)
|
)
|
||||||
.with(indicatif_layer)
|
.with(indicatif_layer)
|
||||||
@@ -326,7 +326,7 @@ async fn handle_init(
|
|||||||
);
|
);
|
||||||
println!(
|
println!(
|
||||||
"{}",
|
"{}",
|
||||||
style("\nSetup complete! Run 'gi doctor' to verify.").blue()
|
style("\nSetup complete! Run 'lore doctor' to verify.").blue()
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -612,7 +612,7 @@ fn handle_version(robot_mode: bool) -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
};
|
};
|
||||||
println!("{}", serde_json::to_string(&output)?);
|
println!("{}", serde_json::to_string(&output)?);
|
||||||
} else {
|
} else {
|
||||||
println!("gi version {}", version);
|
println!("lore version {}", version);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -641,7 +641,7 @@ fn handle_backup(robot_mode: bool) -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
};
|
};
|
||||||
println!("{}", serde_json::to_string(&output)?);
|
println!("{}", serde_json::to_string(&output)?);
|
||||||
} else {
|
} else {
|
||||||
println!("gi backup - not yet implemented");
|
println!("lore backup - not yet implemented");
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -657,7 +657,7 @@ fn handle_reset(robot_mode: bool) -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
};
|
};
|
||||||
println!("{}", serde_json::to_string(&output)?);
|
println!("{}", serde_json::to_string(&output)?);
|
||||||
} else {
|
} else {
|
||||||
println!("gi reset - not yet implemented");
|
println!("lore reset - not yet implemented");
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -702,7 +702,7 @@ async fn handle_migrate(
|
|||||||
error: RobotErrorSuggestionData {
|
error: RobotErrorSuggestionData {
|
||||||
code: "DB_ERROR".to_string(),
|
code: "DB_ERROR".to_string(),
|
||||||
message: format!("Database not found at {}", db_path.display()),
|
message: format!("Database not found at {}", db_path.display()),
|
||||||
suggestion: "Run 'gi init' first".to_string(),
|
suggestion: "Run 'lore init' first".to_string(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
eprintln!("{}", serde_json::to_string(&output)?);
|
eprintln!("{}", serde_json::to_string(&output)?);
|
||||||
@@ -713,7 +713,7 @@ async fn handle_migrate(
|
|||||||
);
|
);
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"{}",
|
"{}",
|
||||||
style("Run 'gi init' first to create the database.").yellow()
|
style("Run 'lore init' first to create the database.").yellow()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
std::process::exit(10); // DB_ERROR exit code
|
std::process::exit(10); // DB_ERROR exit code
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
//! Tests for DiffNote position extraction in note transformer.
|
//! Tests for DiffNote position extraction in note transformer.
|
||||||
|
|
||||||
use gi::gitlab::transformers::discussion::transform_notes_with_diff_position;
|
use lore::gitlab::transformers::discussion::transform_notes_with_diff_position;
|
||||||
use gi::gitlab::types::{
|
use lore::gitlab::types::{
|
||||||
GitLabAuthor, GitLabDiscussion, GitLabLineRange, GitLabLineRangePoint, GitLabNote,
|
GitLabAuthor, GitLabDiscussion, GitLabLineRange, GitLabLineRangePoint, GitLabNote,
|
||||||
GitLabNotePosition,
|
GitLabNotePosition,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
//! Tests for test fixtures - verifies they deserialize correctly.
|
//! Tests for test fixtures - verifies they deserialize correctly.
|
||||||
|
|
||||||
use gi::gitlab::types::{GitLabDiscussion, GitLabIssue};
|
use lore::gitlab::types::{GitLabDiscussion, GitLabIssue};
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
//! Tests for GitLab API response type deserialization.
|
//! Tests for GitLab API response type deserialization.
|
||||||
|
|
||||||
use gi::gitlab::types::{
|
use lore::gitlab::types::{
|
||||||
GitLabAuthor, GitLabDiscussion, GitLabIssue, GitLabMergeRequest, GitLabMilestone, GitLabNote,
|
GitLabAuthor, GitLabDiscussion, GitLabIssue, GitLabMergeRequest, GitLabMilestone, GitLabNote,
|
||||||
GitLabNotePosition, GitLabReferences, GitLabReviewer,
|
GitLabNotePosition, GitLabReferences, GitLabReviewer,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
//! Tests for MR discussion transformer.
|
//! Tests for MR discussion transformer.
|
||||||
|
|
||||||
use gi::gitlab::transformers::discussion::transform_mr_discussion;
|
use lore::gitlab::transformers::discussion::transform_mr_discussion;
|
||||||
use gi::gitlab::types::{GitLabAuthor, GitLabDiscussion, GitLabNote};
|
use lore::gitlab::types::{GitLabAuthor, GitLabDiscussion, GitLabNote};
|
||||||
|
|
||||||
fn make_author() -> GitLabAuthor {
|
fn make_author() -> GitLabAuthor {
|
||||||
GitLabAuthor {
|
GitLabAuthor {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
//! Tests for MR transformer module.
|
//! Tests for MR transformer module.
|
||||||
|
|
||||||
use gi::gitlab::transformers::merge_request::transform_merge_request;
|
use lore::gitlab::transformers::merge_request::transform_merge_request;
|
||||||
use gi::gitlab::types::{GitLabAuthor, GitLabMergeRequest, GitLabReferences, GitLabReviewer};
|
use lore::gitlab::types::{GitLabAuthor, GitLabMergeRequest, GitLabReferences, GitLabReviewer};
|
||||||
|
|
||||||
fn make_test_mr() -> GitLabMergeRequest {
|
fn make_test_mr() -> GitLabMergeRequest {
|
||||||
GitLabMergeRequest {
|
GitLabMergeRequest {
|
||||||
|
|||||||
Reference in New Issue
Block a user