Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 119 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,125 @@ if err := runtimesetup.RegisterAll(manager); err != nil {

This automatically registers all runtimes from `pkg/runtimesetup/register.go` that report as available (e.g., only registers Podman if `podman` CLI is installed).

### Config System

The config system manages workspace configuration stored in the `.kortex` directory. It provides an interface for reading and validating workspace settings including environment variables and mount points.

**Key Components:**
- **Config Interface** (`pkg/config/config.go`): Interface for managing configuration directories
- **WorkspaceConfiguration Model**: Imported from `github.com/kortex-hub/kortex-cli-api/workspace-configuration/go`
- **Configuration File**: `workspace.json` within the `.kortex` directory

**Configuration Structure:**

The `workspace.json` file follows the nested JSON structure pattern:

```json
{
"environment": [
{
"name": "DEBUG",
"value": "true"
},
{
"name": "API_KEY",
"secret": "github-token"
}
],
"mounts": {
"dependencies": ["../main"],
"configs": [".ssh", ".gitconfig"]
}
}
```

**Model Fields:**
- `environment` - Environment variables with either hardcoded `value` or `secret` reference (optional)
- `name` - Variable name (must be valid Unix environment variable name)
- `value` - Hardcoded value (mutually exclusive with `secret`, empty strings allowed)
- `secret` - Secret reference (mutually exclusive with `value`, cannot be empty)
- `mounts.dependencies` - Additional source directories to mount (optional)
- Paths must be relative (not absolute)
- Paths cannot be empty
- Relative to workspace sources directory
- `mounts.configs` - Configuration directories to mount (optional)
- Paths must be relative (not absolute)
- Paths cannot be empty
- Relative to `$HOME`

**Using the Config Interface:**

```go
import (
"github.com/kortex-hub/kortex-cli/pkg/config"
workspace "github.com/kortex-hub/kortex-cli-api/workspace-configuration/go"
)

// Create a config manager for a workspace
cfg, err := config.NewConfig("/path/to/workspace/.kortex")
if err != nil {
return err
}

// Load and validate the workspace configuration
workspaceCfg, err := cfg.Load()
if err != nil {
if errors.Is(err, config.ErrConfigNotFound) {
// workspace.json doesn't exist, use defaults
} else if errors.Is(err, config.ErrInvalidConfig) {
// Configuration validation failed
} else {
return err
}
}

// Access configuration values (note: fields are pointers)
if workspaceCfg.Environment != nil {
for _, env := range *workspaceCfg.Environment {
// Use env.Name, env.Value, env.Secret
}
}

if workspaceCfg.Mounts != nil {
if workspaceCfg.Mounts.Dependencies != nil {
// Use dependency paths
}
if workspaceCfg.Mounts.Configs != nil {
// Use config paths
}
}
```

**Configuration Validation:**

The `Load()` method automatically validates the configuration and returns `ErrInvalidConfig` if any of these rules are violated:

**Environment Variables:**
- Name cannot be empty
- Name must be a valid Unix environment variable name (starts with letter or underscore, followed by letters, digits, or underscores)
- Exactly one of `value` or `secret` must be defined
- Secret references cannot be empty strings
- Empty values are allowed (valid use case: set env var to empty string)

**Mount Paths:**
- Dependency paths cannot be empty
- Dependency paths must be relative (not absolute)
- Config paths cannot be empty
- Config paths must be relative (not absolute)

**Error Handling:**
- `config.ErrInvalidPath` - Configuration path is empty or invalid
- `config.ErrConfigNotFound` - The `workspace.json` file is not found
- `config.ErrInvalidConfig` - Configuration validation failed (includes detailed error message)

**Design Principles:**
- Configuration directory is NOT automatically created
- Missing configuration directory is treated as empty/default configuration
- All configurations are validated on load to catch errors early
- Follows the module design pattern with interface-based API
- Uses nested JSON structure for clarity and extensibility
- Model types are imported from external API package for consistency

### Skills System
Skills are reusable capabilities that can be discovered and executed by AI agents:
- **Location**: `skills/<skill-name>/SKILL.md`
Expand Down
205 changes: 205 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,211 @@ kortex-cli list
kortex-cli list --storage /tmp/kortex-storage
```

## Workspace Configuration

Each workspace can optionally include a configuration file that customizes the environment and mount behavior for that specific workspace. The configuration is stored in a `workspace.json` file within the workspace's configuration directory (typically `.kortex` in the sources directory).

### Configuration File Location

By default, workspace configuration is stored at:
```text
<sources-directory>/.kortex/workspace.json
```

The configuration directory (containing `workspace.json`) can be customized using the `--workspace-configuration` flag when registering a workspace with `init`. The flag accepts a directory path, not the file path itself.

### Configuration Structure

The `workspace.json` file uses a nested JSON structure:

```json
{
"environment": [
{
"name": "DEBUG",
"value": "true"
},
{
"name": "API_KEY",
"secret": "github-token"
}
],
"mounts": {
"dependencies": ["../main", "../../lib"],
"configs": [".ssh", ".gitconfig"]
}
}
```

### Environment Variables

Define environment variables that will be set in the workspace runtime environment.

**Structure:**
```json
{
"environment": [
{
"name": "VAR_NAME",
"value": "hardcoded-value"
},
{
"name": "SECRET_VAR",
"secret": "secret-reference"
}
]
}
```

**Fields:**
- `name` (required) - Environment variable name
- Must be a valid Unix environment variable name
- Must start with a letter or underscore
- Can contain letters, digits, and underscores
- `value` (optional) - Hardcoded value for the variable
- Mutually exclusive with `secret`
- Empty strings are allowed
- `secret` (optional) - Reference to a secret containing the value
- Mutually exclusive with `value`
- Cannot be empty

**Validation Rules:**
- Variable name cannot be empty
- Exactly one of `value` or `secret` must be defined
- Variable names must follow Unix conventions (e.g., `DEBUG`, `API_KEY`, `MY_VAR_123`)
- Invalid names include those starting with digits (`1INVALID`) or containing special characters (`INVALID-NAME`, `INVALID@NAME`)

### Mount Paths

Configure additional directories to mount in the workspace runtime.

**Structure:**
```json
{
"mounts": {
"dependencies": ["../main"],
"configs": [".claude", ".gitconfig"]
}
}
```

**Fields:**
- `dependencies` (optional) - Additional source directories to mount
- Paths are relative to the workspace sources directory
- Useful for git worktrees
- `configs` (optional) - Configuration directories to mount from the user's home directory
- Paths are relative to `$HOME`
- Useful for sharing Git configs, or tool configurations

**Validation Rules:**
- All paths must be relative (not absolute)
- Paths cannot be empty
- Absolute paths like `/absolute/path` are rejected

### Configuration Validation

When you register a workspace with `kortex-cli init`, the configuration is automatically validated. If `workspace.json` exists and contains invalid data, the registration will fail with a descriptive error message.

**Example - Invalid configuration (both value and secret set):**
```bash
$ kortex-cli init /path/to/project --runtime fake
```
```text
Error: workspace configuration validation failed: invalid workspace configuration:
environment variable "API_KEY" (index 0) has both value and secret set
```

**Example - Invalid configuration (absolute path in mounts):**
```bash
$ kortex-cli init /path/to/project --runtime fake
```
```text
Error: workspace configuration validation failed: invalid workspace configuration:
dependency mount "/absolute/path" (index 0) must be a relative path
```

### Configuration Examples

**Basic environment variables:**
```json
{
"environment": [
{
"name": "NODE_ENV",
"value": "development"
},
{
"name": "DEBUG",
"value": "true"
}
]
}
```

**Using secrets:**
```json
{
"environment": [
{
"name": "API_TOKEN",
"secret": "github-api-token"
}
]
}
```

**git worktree:**
```json
{
"mounts": {
"dependencies": [
"../main"
]
}
}
```

**Sharing user configurations:**
```json
{
"mounts": {
"configs": [
".claude",
".gitconfig",
".kube/config"
]
}
}
```

**Complete configuration:**
```json
{
"environment": [
{
"name": "NODE_ENV",
"value": "development"
},
{
"name": "DATABASE_URL",
"secret": "local-db-url"
}
],
"mounts": {
"dependencies": ["../main"],
"configs": [".claude", ".gitconfig"]
}
}
```

### Notes

- Configuration is **optional** - workspaces can be registered without a `workspace.json` file
- The configuration file is validated only when it exists
- Validation errors are caught early during workspace registration (`init` command)
- All validation rules are enforced to prevent runtime errors
- The configuration model is imported from the `github.com/kortex-hub/kortex-cli-api/workspace-configuration/go` package for consistency across tools

## Commands

### `init` - Register a New Workspace
Expand Down
9 changes: 4 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@ module github.com/kortex-hub/kortex-cli
go 1.25.7

require (
github.com/kortex-hub/kortex-cli-api/cli/go v0.0.0-20260312091024-8f627ff7db68
github.com/kortex-hub/kortex-cli-api/cli/go v0.0.0-20260319072318-abc0e6182754
github.com/kortex-hub/kortex-cli-api/workspace-configuration/go v0.0.0-20260319072318-abc0e6182754
github.com/spf13/cobra v1.10.2
github.com/spf13/pflag v1.0.9
)

require (
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/spf13/pflag v1.0.9 // indirect
)
require github.com/inconshreveable/mousetrap v1.1.0 // indirect
6 changes: 4 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/kortex-hub/kortex-cli-api/cli/go v0.0.0-20260312091024-8f627ff7db68 h1:+rG9db97UcYp3RvWwyd3yQQDghsJgEPp2bFZcqz8qfc=
github.com/kortex-hub/kortex-cli-api/cli/go v0.0.0-20260312091024-8f627ff7db68/go.mod h1:jWKudiw26CIjuOsROQ80FOuuk2m2/5BVkuATpmD5xQQ=
github.com/kortex-hub/kortex-cli-api/cli/go v0.0.0-20260319072318-abc0e6182754 h1:MXU+DtCo9nOQs/i4t9bLJvnOHnjdzYTtBXrXzqYVqBo=
github.com/kortex-hub/kortex-cli-api/cli/go v0.0.0-20260319072318-abc0e6182754/go.mod h1:jWKudiw26CIjuOsROQ80FOuuk2m2/5BVkuATpmD5xQQ=
github.com/kortex-hub/kortex-cli-api/workspace-configuration/go v0.0.0-20260319072318-abc0e6182754 h1:Igfvw+SfpmqApUWA4uBhMq4vmhuinJLAGk9YMtSdTr8=
github.com/kortex-hub/kortex-cli-api/workspace-configuration/go v0.0.0-20260319072318-abc0e6182754/go.mod h1:N4tLoDdBbAPYJ9ALLfYbqYScydJb546JgKQ6EjHswLw=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
Expand Down
Loading
Loading