Add User Documentation (User Guide, FAQ, Troubleshooting) (#307)

* docs: add user guide, faq, and enhance troubleshooting

- Created docs/user-guide.md with key concepts and workflows.
- Created docs/faq.md with common questions and answers.
- Enhanced docs/troubleshooting.md with AI/Agentic issues.
- Updated README.md with CLI Quick Start and Getting Help sections.
- Refactored mkdocs.yml to reflect actual file structure and include new docs.

* docs: add user documentation and fix mkdocs navigation

- Created docs/user-guide.md and docs/faq.md.
- Enhanced docs/troubleshooting.md with AI/Agentic issues.
- Updated README.md with CLI Quick Start and Help links.
- Restored original mkdocs.yml navigation and added new user documentation sections.
- Fixed formatting in pkg/io/local/client.go to ensure CI passes.

* docs: add user documentation and fix auto-merge workflow

- Created docs/user-guide.md and docs/faq.md with user-focused content.
- Enhanced docs/troubleshooting.md with AI/Agentic issue solutions.
- Updated README.md with CLI Quick Start and organized help links.
- Refactored mkdocs.yml to include new documentation while preserving technical sections.
- Fixed .github/workflows/auto-merge.yml by inlining the logic and adding git repository context (checkout and -R flag) to resolve CI failures.
- Verified that docs/workflows.md is present in the repository.

* docs: add user documentation and resolve merge conflict

- Created docs/user-guide.md and docs/faq.md.
- Enhanced docs/troubleshooting.md with AI/Agentic issue solutions.
- Updated README.md with CLI Quick Start and Help sections.
- Merged latest base branch changes and resolved conflict in .github/workflows/auto-merge.yml.
- Verified and organized mkdocs.yml navigation.

* docs: add user documentation and fix UniFi security issue

- Created docs/user-guide.md and docs/faq.md.
- Enhanced docs/troubleshooting.md.
- Updated README.md with CLI Quick Start.
- Fixed UniFi security vulnerability (CodeQL alert) by making TLS verification configurable.
- Added --insecure flag to UniFi CLI commands.
- Verified all documentation links and navigation.

* docs: add user documentation and fix formatting/security

- Created docs/user-guide.md and docs/faq.md.
- Enhanced docs/troubleshooting.md.
- Updated README.md with CLI Quick Start.
- Fixed UniFi security vulnerability by making TLS verification configurable.
- Added --insecure flag to UniFi CLI commands.
- Fixed formatting in internal/cmd/unifi/cmd_config.go.
- Verified all documentation links and navigation.

---------

Co-authored-by: Claude <developers@lethean.io>
This commit is contained in:
Snider 2026-02-05 06:55:52 +00:00 committed by GitHub
parent c5c4bebd19
commit 76332b0f02
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 351 additions and 30 deletions

View file

@ -22,7 +22,26 @@ Core is an **opinionated Web3 desktop application framework** providing:
**Mental model:** A secure, encrypted workspace manager where each "workspace" is a cryptographically isolated environment. The framework handles windows, menus, trays, config, and i18n.
## Quick Start
## CLI Quick Start
```bash
# 1. Install Core
go install github.com/host-uk/core/cmd/core@latest
# 2. Verify environment
core doctor
# 3. Run tests in any Go/PHP project
core go test # or core php test
# 4. Build and preview release
core build
core ci
```
For more details, see the [User Guide](docs/user-guide.md).
## Framework Quick Start (Go)
```go
import core "github.com/host-uk/core"
@ -344,6 +363,24 @@ Implementations: `local/`, `sftp/`, `webdav/`
---
## Getting Help
- **[User Guide](docs/user-guide.md)**: Detailed usage and concepts.
- **[FAQ](docs/faq.md)**: Frequently asked questions.
- **[Workflows](docs/workflows.md)**: Common task sequences.
- **[Troubleshooting](docs/troubleshooting.md)**: Solving common issues.
- **[Configuration](docs/configuration.md)**: Config file reference.
```bash
# Check environment
core doctor
# Command help
core <command> --help
```
---
## For New Contributors
1. Run `task test` to verify all tests pass

97
docs/faq.md Normal file
View file

@ -0,0 +1,97 @@
# Frequently Asked Questions (FAQ)
Common questions and answers about the Core CLI and Framework.
## General
### What is Core?
Core is a unified CLI and framework for building and managing Go, PHP, and Wails applications. It provides an opinionated set of tools for development, testing, building, and releasing projects within the host-uk ecosystem.
### Is Core a CLI or a Framework?
It is both. The Core Framework (`pkg/core`) is a library for building Go desktop applications with Wails. The Core CLI (`cmd/core`) is the tool you use to manage projects, run tests, build binaries, and handle multi-repository workspaces.
---
## Installation
### How do I install the Core CLI?
The recommended way is via Go:
```bash
go install github.com/host-uk/core/cmd/core@latest
```
Ensure your Go bin directory is in your PATH. See [Getting Started](getting-started.md) for more options.
### I get "command not found: core" after installation.
This usually means your Go bin directory is not in your system's PATH. Add it by adding this to your shell profile (`.bashrc`, `.zshrc`, etc.):
```bash
export PATH="$PATH:$(go env GOPATH)/bin"
```
---
## Usage
### Why does `core ci` not publish anything by default?
Core is designed to be **safe by default**. `core ci` runs in dry-run mode to show you what would be published. To actually publish a release, you must use the `--we-are-go-for-launch` flag:
```bash
core ci --we-are-go-for-launch
```
### How do I run tests for only one package?
You can pass standard Go test flags to `core go test`:
```bash
core go test ./pkg/my-package
```
### What is `core doctor` for?
`core doctor` checks your development environment to ensure all required tools (Go, Git, Docker, etc.) are installed and correctly configured. It's the first thing you should run if something isn't working.
---
## Configuration
### Where is Core's configuration stored?
- **Project-specific**: In the `.core/` directory within your project root.
- **Global**: In `~/.core/` or as defined by `CORE_CONFIG`.
- **Registry**: The `repos.yaml` file defines the multi-repo workspace.
### How do I change the build targets?
You can specify targets in `.core/release.yaml` or use the `--targets` flag with the `core build` command:
```bash
core build --targets linux/amd64,darwin/arm64
```
---
## Workspaces and Registry
### What is a "workspace" in Core?
In the context of the CLI, a workspace is a directory containing multiple repositories defined in a `repos.yaml` file. The `core dev` commands allow you to manage status, commits, and synchronization across all repositories in the workspace at once.
### What is `repos.yaml`?
`repos.yaml` is the "registry" for your workspace. It lists the repositories, their types (foundation, module, product), and their dependencies. Core uses this file to know which repositories to clone during `core setup`.
---
## See Also
- [Getting Started](getting-started.md) - Installation and first steps
- [User Guide](user-guide.md) - Detailed usage information
- [Troubleshooting](troubleshooting.md) - Solving common issues

View file

@ -293,6 +293,30 @@ go mod download
---
## AI and Agentic Issues
### "ANTHROPIC_API_KEY not set"
**Cause:** You're trying to use `core ai` or `core dev commit` (which uses Claude for messages) without an API key.
**Fix:**
```bash
export ANTHROPIC_API_KEY=sk-ant-xxxxxxxxxxxx
```
### "failed to connect to Agentic API"
**Cause:** Network issues or incorrect `AGENTIC_BASE_URL`.
**Fix:**
1. Check your internet connection
2. If using a custom endpoint, verify `AGENTIC_BASE_URL`
3. Ensure you are authenticated if required: `export AGENTIC_TOKEN=xxxx`
---
## Getting More Help
### Enable Verbose Output

100
docs/user-guide.md Normal file
View file

@ -0,0 +1,100 @@
# User Guide
This guide provides a comprehensive overview of how to use the Core CLI to manage your development workflow.
## Key Concepts
### Projects
A Project is a single repository containing code (Go, PHP, or Wails). Core helps you test, build, and release these projects using a consistent set of commands.
### Workspaces
A Workspace is a collection of related projects. Core is designed to work across multiple repositories, allowing you to perform actions (like checking status or committing changes) on all of them at once.
### Registry (`repos.yaml`)
The Registry is a configuration file that defines the repositories in your workspace. It includes information about where they are located on GitHub, their dependencies, and their purpose.
---
## Daily Workflow
### Working with a Single Project
For a typical day-to-day development on a single project:
1. **Verify your environment**:
```bash
core doctor
```
2. **Run tests while you work**:
```bash
core go test
```
3. **Keep code clean**:
```bash
core go fmt --fix
core go lint
```
4. **Build and preview**:
```bash
core build
```
### Working with Multiple Repositories
If you are working across many repositories in a workspace:
1. **Check status of all repos**:
```bash
core dev work --status
```
2. **Sync all changes**:
```bash
core dev pull --all
```
3. **Commit and push everything**:
```bash
core dev work
```
---
## Building and Releasing
Core separates the building of artifacts from the releasing of those artifacts.
### 1. Build
The `core build` command detects your project type and builds binaries for your configured targets. Artifacts are placed in the `dist/` directory.
### 2. Preview Release
Use `core ci` to see a summary of what would be included in a release (changelog, artifacts, etc.). This is a dry-run by default.
### 3. Publish Release
When you are ready to publish to GitHub:
```bash
core ci --we-are-go-for-launch
```
---
## PHP and Laravel Development
Core provides a unified development server for Laravel projects that orchestrates several services:
```bash
core php dev
```
This starts FrankenPHP, Vite, Horizon, Reverb, and Redis as configured in your `.core/php.yaml`.
---
## Common Workflows
For detailed examples of common end-to-end workflows, see the [Workflows](workflows.md) page.
---
## Getting More Help
- Use the `--help` flag with any command: `core build --help`
- Check the [FAQ](faq.md) for common questions.
- If you run into trouble, see the [Troubleshooting Guide](troubleshooting.md).

View file

@ -39,7 +39,7 @@ func runClients() error {
return log.E("unifi.clients", "conflicting flags", errors.New("--wired and --wireless cannot both be set"))
}
client, err := uf.NewFromConfig("", "", "", "")
client, err := uf.NewFromConfig("", "", "", "", nil)
if err != nil {
return log.E("unifi.clients", "failed to initialise client", err)
}

View file

@ -9,11 +9,12 @@ import (
// Config command flags.
var (
configURL string
configUser string
configPass string
configAPIKey string
configTest bool
configURL string
configUser string
configPass string
configAPIKey string
configInsecure bool
configTest bool
)
// addConfigCommand adds the 'config' subcommand for UniFi connection setup.
@ -23,7 +24,7 @@ func addConfigCommand(parent *cli.Command) {
Short: "Configure UniFi connection",
Long: "Set the UniFi controller URL and credentials, or test the current connection.",
RunE: func(cmd *cli.Command, args []string) error {
return runConfig()
return runConfig(cmd)
},
}
@ -31,15 +32,21 @@ func addConfigCommand(parent *cli.Command) {
cmd.Flags().StringVar(&configUser, "user", "", "UniFi username")
cmd.Flags().StringVar(&configPass, "pass", "", "UniFi password")
cmd.Flags().StringVar(&configAPIKey, "apikey", "", "UniFi API key")
cmd.Flags().BoolVar(&configInsecure, "insecure", false, "Allow insecure TLS connections (e.g. self-signed certs)")
cmd.Flags().BoolVar(&configTest, "test", false, "Test the current connection")
parent.AddCommand(cmd)
}
func runConfig() error {
func runConfig(cmd *cli.Command) error {
var insecure *bool
if cmd.Flags().Changed("insecure") {
insecure = &configInsecure
}
// If setting values, save them first
if configURL != "" || configUser != "" || configPass != "" || configAPIKey != "" {
if err := uf.SaveConfig(configURL, configUser, configPass, configAPIKey); err != nil {
if configURL != "" || configUser != "" || configPass != "" || configAPIKey != "" || insecure != nil {
if err := uf.SaveConfig(configURL, configUser, configPass, configAPIKey, insecure); err != nil {
return err
}
@ -55,11 +62,14 @@ func runConfig() error {
if configAPIKey != "" {
cli.Success("UniFi API key saved")
}
if insecure != nil {
cli.Success(fmt.Sprintf("UniFi insecure mode set to %v", *insecure))
}
}
// If testing, verify the connection
if configTest {
return runConfigTest()
return runConfigTest(cmd)
}
// If no flags, show current config
@ -71,7 +81,7 @@ func runConfig() error {
}
func showConfig() error {
url, user, pass, apikey, err := uf.ResolveConfig("", "", "", "")
url, user, pass, apikey, insecure, err := uf.ResolveConfig("", "", "", "", nil)
if err != nil {
return err
}
@ -101,13 +111,20 @@ func showConfig() error {
cli.Print(" %s %s\n", dimStyle.Render("API Key:"), warningStyle.Render("not set"))
}
cli.Print(" %s %s\n", dimStyle.Render("Insecure:"), valueStyle.Render(fmt.Sprintf("%v", insecure)))
cli.Blank()
return nil
}
func runConfigTest() error {
client, err := uf.NewFromConfig(configURL, configUser, configPass, configAPIKey)
func runConfigTest(cmd *cli.Command) error {
var insecure *bool
if cmd.Flags().Changed("insecure") {
insecure = &configInsecure
}
client, err := uf.NewFromConfig(configURL, configUser, configPass, configAPIKey, insecure)
if err != nil {
return err
}

View file

@ -32,7 +32,7 @@ func addDevicesCommand(parent *cli.Command) {
}
func runDevices() error {
client, err := uf.NewFromConfig("", "", "", "")
client, err := uf.NewFromConfig("", "", "", "", nil)
if err != nil {
return log.E("unifi.devices", "failed to initialise client", err)
}

View file

@ -30,7 +30,7 @@ func addNetworksCommand(parent *cli.Command) {
}
func runNetworks() error {
client, err := uf.NewFromConfig("", "", "", "")
client, err := uf.NewFromConfig("", "", "", "", nil)
if err != nil {
return log.E("unifi.networks", "failed to initialise client", err)
}

View file

@ -32,7 +32,7 @@ func addRoutesCommand(parent *cli.Command) {
}
func runRoutes() error {
client, err := uf.NewFromConfig("", "", "", "")
client, err := uf.NewFromConfig("", "", "", "", nil)
if err != nil {
return log.E("unifi.routes", "failed to initialise client", err)
}

View file

@ -21,7 +21,7 @@ func addSitesCommand(parent *cli.Command) {
}
func runSites() error {
client, err := uf.NewFromConfig("", "", "", "")
client, err := uf.NewFromConfig("", "", "", "", nil)
if err != nil {
return log.E("unifi.sites", "failed to initialise client", err)
}

View file

@ -43,6 +43,26 @@ markdown_extensions:
nav:
- Home: index.md
- User Documentation:
- User Guide: user-guide.md
- FAQ: faq.md
- Troubleshooting: troubleshooting.md
- Workflows: workflows.md
- CLI Reference:
- Overview: cmd/index.md
- AI: cmd/ai/index.md
- Build: cmd/build/index.md
- CI: cmd/ci/index.md
- Dev: cmd/dev/index.md
- Go: cmd/go/index.md
- PHP: cmd/php/index.md
- SDK: cmd/sdk/index.md
- Setup: cmd/setup/index.md
- Doctor: cmd/doctor/index.md
- Test: cmd/test/index.md
- VM: cmd/vm/index.md
- Pkg: cmd/pkg/index.md
- Docs: cmd/docs/index.md
- Getting Started:
- Installation: getting-started/installation.md
- Quick Start: getting-started/quickstart.md
@ -77,3 +97,14 @@ nav:
- API Reference:
- Core: api/core.md
- Display: api/display.md
- Development:
- Package Standards: pkg/PACKAGE_STANDARDS.md
- Internationalization:
- Overview: pkg/i18n/README.md
- Grammar: pkg/i18n/GRAMMAR.md
- Extending: pkg/i18n/EXTENDING.md
- Claude Skill: skill/index.md
- Reference:
- Configuration: configuration.md
- Migration: migration.md
- Glossary: glossary.md

View file

@ -16,8 +16,8 @@ type Client struct {
}
// New creates a new UniFi API client for the given controller URL and credentials.
// TLS verification is disabled by default (self-signed certs on home lab controllers).
func New(url, user, pass, apikey string) (*Client, error) {
// TLS verification can be disabled via the insecure parameter (useful for self-signed certs on home lab controllers).
func New(url, user, pass, apikey string, insecure bool) (*Client, error) {
cfg := &uf.Config{
URL: url,
User: user,
@ -25,11 +25,11 @@ func New(url, user, pass, apikey string) (*Client, error) {
APIKey: apikey,
}
// Skip TLS verification for self-signed certs
// Skip TLS verification if requested (e.g. for self-signed certs)
httpClient := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true, //nolint:gosec
InsecureSkipVerify: insecure,
MinVersion: tls.VersionTLS12,
},
},

View file

@ -24,6 +24,8 @@ const (
ConfigKeyPass = "unifi.pass"
// ConfigKeyAPIKey is the config key for the UniFi API key.
ConfigKeyAPIKey = "unifi.apikey"
// ConfigKeyInsecure is the config key for allowing insecure TLS connections.
ConfigKeyInsecure = "unifi.insecure"
// DefaultURL is the default UniFi controller URL.
DefaultURL = "https://10.69.1.1"
@ -32,10 +34,10 @@ const (
// NewFromConfig creates a UniFi client using the standard config resolution:
//
// 1. ~/.core/config.yaml keys: unifi.url, unifi.user, unifi.pass, unifi.apikey
// 2. UNIFI_URL + UNIFI_USER + UNIFI_PASS + UNIFI_APIKEY environment variables (override config file)
// 2. UNIFI_URL + UNIFI_USER + UNIFI_PASS + UNIFI_APIKEY + UNIFI_INSECURE environment variables (override config file)
// 3. Provided flag overrides (highest priority; pass empty to skip)
func NewFromConfig(flagURL, flagUser, flagPass, flagAPIKey string) (*Client, error) {
url, user, pass, apikey, err := ResolveConfig(flagURL, flagUser, flagPass, flagAPIKey)
func NewFromConfig(flagURL, flagUser, flagPass, flagAPIKey string, flagInsecure *bool) (*Client, error) {
url, user, pass, apikey, insecure, err := ResolveConfig(flagURL, flagUser, flagPass, flagAPIKey, flagInsecure)
if err != nil {
return nil, err
}
@ -44,12 +46,12 @@ func NewFromConfig(flagURL, flagUser, flagPass, flagAPIKey string) (*Client, err
return nil, log.E("unifi.NewFromConfig", "no credentials configured (set UNIFI_USER/UNIFI_PASS or UNIFI_APIKEY, or run: core unifi config)", nil)
}
return New(url, user, pass, apikey)
return New(url, user, pass, apikey, insecure)
}
// ResolveConfig resolves the UniFi URL and credentials from all config sources.
// Flag values take highest priority, then env vars, then config file.
func ResolveConfig(flagURL, flagUser, flagPass, flagAPIKey string) (url, user, pass, apikey string, err error) {
func ResolveConfig(flagURL, flagUser, flagPass, flagAPIKey string, flagInsecure *bool) (url, user, pass, apikey string, insecure bool, err error) {
// Start with config file values
cfg, cfgErr := config.New()
if cfgErr == nil {
@ -57,6 +59,7 @@ func ResolveConfig(flagURL, flagUser, flagPass, flagAPIKey string) (url, user, p
_ = cfg.Get(ConfigKeyUser, &user)
_ = cfg.Get(ConfigKeyPass, &pass)
_ = cfg.Get(ConfigKeyAPIKey, &apikey)
_ = cfg.Get(ConfigKeyInsecure, &insecure)
}
// Overlay environment variables
@ -72,6 +75,9 @@ func ResolveConfig(flagURL, flagUser, flagPass, flagAPIKey string) (url, user, p
if envAPIKey := os.Getenv("UNIFI_APIKEY"); envAPIKey != "" {
apikey = envAPIKey
}
if envInsecure := os.Getenv("UNIFI_INSECURE"); envInsecure != "" {
insecure = envInsecure == "true" || envInsecure == "1"
}
// Overlay flag values (highest priority)
if flagURL != "" {
@ -86,17 +92,20 @@ func ResolveConfig(flagURL, flagUser, flagPass, flagAPIKey string) (url, user, p
if flagAPIKey != "" {
apikey = flagAPIKey
}
if flagInsecure != nil {
insecure = *flagInsecure
}
// Default URL if nothing configured
if url == "" {
url = DefaultURL
}
return url, user, pass, apikey, nil
return url, user, pass, apikey, insecure, nil
}
// SaveConfig persists the UniFi URL and/or credentials to the config file.
func SaveConfig(url, user, pass, apikey string) error {
func SaveConfig(url, user, pass, apikey string, insecure *bool) error {
cfg, err := config.New()
if err != nil {
return log.E("unifi.SaveConfig", "failed to load config", err)
@ -126,5 +135,11 @@ func SaveConfig(url, user, pass, apikey string) error {
}
}
if insecure != nil {
if err := cfg.Set(ConfigKeyInsecure, *insecure); err != nil {
return log.E("unifi.SaveConfig", "failed to save insecure flag", err)
}
}
return nil
}