Skip to main content
Artemis City is split across a Python core, a TypeScript Express API, and a memory-layer MCP server. Each layer reads its own .env file from a different location, and several keys (notably MCP_API_KEY) must match across files for cross-service authentication to work. The setup_secrets.sh script in the repository root provisions every .env the codebase actually reads, generates fresh keys, and places each key in the file its consumer expects.

When to use this

  • You just cloned the repo and need to bring up a working local stack.
  • You rotated keys and want all .env files reissued with matching values.
  • You’re wiring up the TypeScript Express API (app/api) for the first time and need its auth tuple set correctly.
If you only run the Python core and never touch the Express API or the memory-layer MCP server, you can still use this script — files for absent components are skipped silently.

What it provisions

The script writes up to four .env files, each next to the consumer that reads it:

Generated keys

The script generates three secrets with openssl rand -hex 32 (falling back to Python’s secrets.token_hex(32) if openssl is unavailable): MCP_API_KEY is the only key that must match across files. The other two are scoped to a single layer.

Running the script

From the repository root:
The script:
  1. Generates MCP_API_KEY, FASTAPI_API_KEY, and ARTEMIS_API_KEY_DEFAULT.
  2. For each target, copies the matching .env.example, substitutes placeholders with the generated values, and chmod 600s the result.
  3. Verifies each written file is matched by .gitignore and warns if it is not.
  4. Prints the generated keys at the end so you can copy them into a password manager.
Re-running is safe: each existing .env prompts before overwrite, defaulting to No. Missing example files are skipped without error.

TypeScript API key format

The TS Express API supports multiple keys, one per logical caller. Each key is configured as an environment variable named ARTEMIS_API_KEY_<NAME>, with the value being a colon-separated tuple:
For example, the default admin key written by the script looks like:
To add a read-only service account, append another variable to app/api/.env:
If no ARTEMIS_API_KEY_* variable is set, the TS API falls back to MCP_API_KEY and assigns it the admin role.

app/api/.env reference

The TypeScript API reads the following variables (see app/api/.env.example for the full template):

After the script runs

  1. Add your Obsidian REST API key to the root .env:
  2. If your Obsidian vault is not at <repo>/obsidian_vault, set OBSIDIAN_VAULT_PATH in the root .env.
  3. The ARTEMIS_API_KEY_DEFAULT and MCP_API_KEY values in app/api/.env already match the Python core — no extra wiring needed.

Security notes

  • Every file written by the script is chmod 600 — readable and writable only by the owner.
  • .gitignore covers .env at any depth. The script runs git check-ignore per file and warns if any are not ignored.
  • The script never overwrites a file without prompting. Re-running it on a working checkout will not silently rotate keys.
  • Production secrets belong in per-environment GitHub Environment secrets (see Environments) — not in committed .env files or repo-wide secrets.
Last modified on July 16, 2026