Skip to content
Draft
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
113 changes: 11 additions & 102 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,109 +1,18 @@
# Local-only Cued environment overrides.
# Nothing here is required for a normal install. Prefer the app defaults unless
# you are developing, packaging, benchmarking, or isolating test state.
# Cued loads repo-local .env files through dotenv at Node process startup.
# Keep this file limited to secrets and credential file paths. Non-secret
# runtime tuning belongs in src/core/config.ts.

# Runtime metadata
CUED_RELEASE_CHANNEL=internal
CUED_APP_VERSION=

# Local state and secrets
CUED_HOME=
CUED_DB_PATH=
# Local database key override.
# Normal installs use the macOS Keychain instead.
CUED_DB_KEY=

# Gmail OAuth client JSON paths.
# The JSON contains a client_secret; official builds bundle this separately.
CUED_GOOGLE_OAUTH_CLIENT_FILE=
GOOGLE_OAUTH_CLIENT_FILE=

# Native helper and platform path overrides
CUED_APP_PATH=
CUED_AUTH_NATIVE_BINARY=
CUED_IMESSAGE_DB_PATH=
CUED_IMESSAGE_NATIVE_BINARY=
CUED_CALL_HISTORY_DB_PATH=
CUED_CONTACTS_NATIVE_BINARY=
CUED_CONTACTS_JSON_PATH=
CUED_SIGNAL_CLI_PATH=
CUED_SIGNAL_ACCOUNT=
CUED_WHATSAPP_HELPER_BINARY=
CUED_WHATSAPP_DESKTOP_SOURCE_PATH=
CUED_SLACK_APP_BINARY=
CUED_SLACK_HELPER_BINARY=
CUED_SLACK_USER_DATA_DIR=
CUED_SLACK_REMOTE_DEBUGGING_PORT=
CUED_CHROMIUM_EXECUTABLE_PATH=

# Daemon scheduling and projection tuning
CUED_AUTOSYNC_PLATFORMS=
CUED_REALTIME_PLATFORMS=
CUED_AUTOSYNC_INTERVAL_MS=
CUED_AUTOSYNC_INTERVAL_SIGNAL_MS=
CUED_AUTOSYNC_INTERVAL_WHATSAPP_MS=
CUED_AUTOSYNC_INTERVAL_DISCORD_MS=
CUED_AUTOSYNC_SCHEDULER_TICK_MS=
CUED_AUTOSYNC_PROJECTION_BACKLOG_PAUSE_EVENTS=
CUED_INGEST_CONCURRENCY=
CUED_PROJECTION_BATCH_SIZE=
CUED_MESSAGE_FTS_INDEX_BATCH_SIZE=
CUED_SYNC_CONTINUE_DELAY_MS=
CUED_PROJECTION_CONTINUE_DELAY_MS=
CUED_CONTINUATION_PROJECTION_INTERVAL_MS=
CUED_CONTINUATION_PROJECTION_BACKLOG_EVENTS=
CUED_DEFERRED_PROJECTION_COALESCE_MS=
CUED_REALTIME_PROJECTION_ENABLED=
CUED_REALTIME_PROJECTION_BATCH_SIZE=
CUED_SIGNAL_RECONNECT_SYNC_COOLDOWN_MS=
CUED_WHATSAPP_RESYNC_PAGE_BUDGET=

# Platform sync limits and realtime toggles
CUED_GMAIL_PAGE_SIZE=
CUED_GMAIL_PAGE_BUDGET=
CUED_GMAIL_FETCH_CONCURRENCY=
CUED_LINKEDIN_CONNECTION_PAGES=
CUED_LINKEDIN_CONVERSATION_PAGES=
CUED_LINKEDIN_MESSAGE_PAGES=
CUED_LINKEDIN_FETCH_CONCURRENCY=
CUED_DISCORD_REALTIME_ENABLED=
CUED_DISCORD_DM_POLL_MS=
CUED_DISCORD_SYNC_MESSAGE_CHANNEL_LIMIT=
CUED_DISCORD_SYNC_MESSAGES_PER_CHANNEL_LIMIT=
CUED_DISCORD_SYNC_BACKFILL_PAGE_LIMIT=
CUED_SLACK_REALTIME_ENABLED=
CUED_SLACK_REALTIME_POLL_MS=
CUED_SLACK_REALTIME_USER_REFRESH_MS=
CUED_SLACK_REALTIME_CONVERSATION_LIMIT=
CUED_SLACK_REALTIME_MESSAGE_LIMIT=
CUED_SLACK_API_PAGE_BUDGET=
CUED_SLACK_DESKTOP_IMPORT_TIMEOUT_MS=

# Local runtime limits
CUED_DAEMON_REQUEST_TIMEOUT_MS=
CUED_CHROMIUM_AUTH_TIMEOUT_MS=
CUED_OAUTH_TIMEOUT_MS=
CUED_ATTACHMENT_DISK_RESERVE_BYTES=
CUED_LOG_MAX_BYTES=

# Worker, cursor, and fixture overrides
CUED_ACCOUNT_KEY=
CUED_IMESSAGE_LAST_ROWID=
CUED_SIGNAL_LAST_SYNC_AT=
CUED_LINKEDIN_LAST_SYNC_AT=
CUED_LINKEDIN_SYNC_TOKEN=
CUED_DISCORD_SOURCE_CURSOR=
CUED_DISCORD_SYNC_PROOFS=
CUED_PROJECTION_WORKER_RUN=
CUED_WHATSAPP_SYNC_SOURCE=
CUED_FAKE_QR_AUTH_RESULT=
CUED_FAKE_CHROMIUM_AUTH_RESULT=

# Packaging and release
CUED_NODE_PATH=
CUED_DB_PATH_OVERRIDE=
CUED_BUNDLED_GOOGLE_OAUTH_CLIENT_FILE=

# Release signing credential handles.
# The underlying certificates and notary credentials live outside the repo.
CUED_CODESIGN_IDENTITY=
CUED_NOTARY_PROFILE=
CUED_RELEASE_REPO=Cue-d/cued
CUED_RELEASE_API_BASE=https://api.github.com
CUED_RELEASE_VERSION=
CUED_RELEASE_TAG=
CUED_RELEASE_PUBLISHED_AT=
CUED_DESTINATION=
CUED_OPEN_APP=1
10 changes: 0 additions & 10 deletions .github/workflows/release-cued-macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,6 @@ jobs:
- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Resolve release version
run: |
VERSION="$(node -p "require('./package.json').version")"
echo "CUED_RELEASE_VERSION=$VERSION" >> "$GITHUB_ENV"
echo "CUED_RELEASE_TAG=v$VERSION" >> "$GITHUB_ENV"

- name: Prepare bundled Google OAuth client
run: |
if [[ -z "${CUED_GOOGLE_OAUTH_CLIENT_JSON:-}" ]]; then
Expand Down Expand Up @@ -76,13 +70,9 @@ jobs:
env:
CUED_CODESIGN_IDENTITY: ${{ secrets.CUED_CODESIGN_IDENTITY }}
CUED_NOTARY_PROFILE: ${{ secrets.CUED_NOTARY_PROFILE }}
CUED_RELEASE_CHANNEL: stable

- name: Build release metadata
run: node scripts/build-cued-release-metadata.mjs
env:
CUED_RELEASE_CHANNEL: stable
CUED_RELEASE_REPO: Cue-d/cued

- name: Create or update release
run: |
Expand Down
20 changes: 12 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,16 +209,20 @@ Release packaging can inject the official client without committing it:
CUED_BUNDLED_GOOGLE_OAUTH_CLIENT_FILE=/private/path/google-oauth-client.json pnpm build:app:macos
```

### Idle performance controls
### Configuration

The daemon defaults to a low-idle scheduler tick and platform-specific sync intervals. Tune these only when debugging or benchmarking:
Cued loads repo-root `.env` files through dotenv at Node process startup.
`.env.example` is a short credential reference, not an inventory of every
internal `CUED_*` value. Normal installs use app defaults, `~/.cued`, Keychain,
and bundled helper discovery.

```bash
CUED_AUTOSYNC_SCHEDULER_TICK_MS=15000
CUED_AUTOSYNC_INTERVAL_MS=60000
CUED_AUTOSYNC_INTERVAL_SIGNAL_MS=300000
CUED_AUTOSYNC_INTERVAL_WHATSAPP_MS=300000
```
For packaged app launch overrides, the macOS host reads `~/.cued/daemon.env`.
Use that only for rare credential-path overrides. Non-secret defaults and
runtime path overrides live in `src/core/config.ts`; isolated local runs can pass
`--config path/to/config.json`.

See [docs/configuration.md](docs/configuration.md) for the configuration ownership
rules.

### Contributor workflow

Expand Down
2 changes: 1 addition & 1 deletion bin/cued-wrapper
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#!/bin/sh
SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
exec "${CUED_NODE_PATH:-node}" "$SCRIPT_DIR/../dist/cli.js" "$@"
exec node "$SCRIPT_DIR/../dist/cli.js" "$@"
94 changes: 94 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Configuration

Cued should run without local environment setup. A normal install gets its paths
from the app bundle, stores data under `~/.cued`, stores integration secrets in
Keychain, and uses source defaults for daemon behavior.

## What `.env.example` Is

Node entrypoints load repo-root `.env` files through dotenv before reading Cued
configuration. `.env.example` is still a credential reference, not a general app
configuration registry.

Keep `.env.example` limited to values that are secret-bearing or point at
secret-bearing credential files:

- `CUED_DB_KEY`, only for bypassing the normal Keychain database key path.
- Gmail OAuth client JSON paths, because those files contain `client_secret`.
- release signing/notary credential handles used by packaging.

Do not add daemon scheduling knobs, worker cursors, fixture flags, helper binary
paths, release metadata, or benchmark controls to `.env.example`.

## Runtime Configuration Owners

The runtime has a few existing configuration owners. Reuse these before adding a
new environment variable.

| Need | Owner |
| --- | --- |
| Normal app paths | `src/core/config.ts` plus the app bundle launcher |
| Local data directory | `src/core/config.ts`; isolated runs pass `--config path/to/config.json` |
| Database encryption | Keychain by default, `CUED_DB_KEY` only as an override |
| Daemon scheduling and projection defaults | `src/core/config.ts` |
| Platform sync limits | `src/core/config.ts` |
| Integration credentials and tokens | Keychain |
| User hooks | `~/.cued/hooks.toml` |
| Packaged app runtime path overrides | `~/.cued/config.json` |
| Packaged app credential env overrides | `~/.cued/daemon.env` |
| Worker cursors and sync proofs | structured stdin invocation from the parent daemon |
| Build, release, smoke, and benchmark settings | the script that consumes them |

## Runtime `config.json`

The default runtime data directory is `~/.cued`. For isolated local runs, write
a small JSON config and pass it as a CLI argument:

```json
{
"home": "/tmp/cued-home",
"dbPath": "/tmp/cued-home/local.db"
}
```

```bash
pnpm exec tsx src/cli.ts --config /tmp/cued-home/config.json status
```

The macOS host also reads this config shape and forwards the same config path
when it launches the bundled daemon.

## `~/.cued/daemon.env`

The macOS host reads `~/.cued/daemon.env` before launching the daemon. This file
is the packaged app override path for rare secret-bearing values that must enter
the daemon process environment. It accepts `KEY=value` lines for the explicit
credential allowlist in `RuntimeSupport.swift`.

Use it sparingly. It is appropriate for a local credential path or temporary
launch override that cannot live in the database or Keychain. It is not a
replacement for a checked-in defaults file.

Example:

```sh
CUED_GOOGLE_OAUTH_CLIENT_FILE=/Users/me/.cued/google-oauth-client.json
```

## Adding New Configuration

Before adding a new env var, answer these in order:

1. Can the value just be a source default in the current owner?
2. If it is a user-facing preference, should it be an app setting or CLI command
instead of a launch-time env var?
3. If it is a secret, can it live in Keychain rather than env?
4. If it is worker IPC, can the parent daemon inject it without documenting it
as user configuration?
5. If it is script-only, can it be documented next to that script instead of in
`.env.example`?

For local development, prefer editing `src/core/config.ts`, using `--config` for
isolated runtime paths, or using a targeted script invocation. Environment
variables are still useful for secrets and credential file paths, but they
should not become the public configuration surface for every tweakable constant.
2 changes: 1 addition & 1 deletion docs/integration-policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,6 @@ The future acceptable shape is:
- QR or phone login after app credentials are available
- Keychain/local storage for sessions
- documented rate-limit and auth-invalidation behavior
- clean `CUED_HOME` smoke coverage before public enablement
- clean config-file smoke coverage before public enablement

Do not expose Telegram in onboarding, README, or the public capability matrix until that path works.
24 changes: 21 additions & 3 deletions native/helpers/slack-go/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -599,18 +599,36 @@ func commandErrorEnvelope(err error) commandEnvelope {

func main() {
if len(os.Args) < 2 {
fmt.Fprintln(os.Stderr, "usage: cued-slack-helper <version|status|authTest|listUsers|listConversations|getConversationMembers|getHistory|getReplies|session>")
fmt.Fprintln(os.Stderr, "usage: cued-slack-helper [--api-url URL] <version|status|authTest|listUsers|listConversations|getConversationMembers|getHistory|getReplies|session>")
os.Exit(1)
}

command := os.Args[1]
args := os.Args[1:]
apiURL := ""
if strings.HasPrefix(args[0], "--api-url=") {
apiURL = strings.TrimSpace(strings.TrimPrefix(args[0], "--api-url="))
args = args[1:]
} else if args[0] == "--api-url" {
if len(args) < 3 {
fmt.Fprintln(os.Stderr, "--api-url requires a value and command")
os.Exit(1)
}
apiURL = strings.TrimSpace(args[1])
args = args[2:]
}
if len(args) < 1 {
fmt.Fprintln(os.Stderr, "missing helper command")
os.Exit(1)
}

command := args[0]
baseCtx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
ctx, cancel := context.WithTimeout(baseCtx, requestTimeout)
defer cancel()

runner := newHelperRunner(runnerOptions{
apiURL: os.Getenv("CUED_SLACK_HELPER_API_URL"),
apiURL: apiURL,
})

if command == "session" {
Expand Down
Loading