Skip to content

Repository files navigation

CodeSeeq

Production-grade Codex CLI drop-in launcher wired to multiple LLM providers.

Run codeseeq instead of codex. Same flags, same interactive TUI, same tool calls. Your prompts go to the provider you choose — DeepSeek, Anthropic (Claude), Google (Gemini), Grok (xAI), Venice.ai, or a local OpenAI-compatible gateway — no OpenAI account or API key needed. Configure everything interactively with codeseeq config.

CodeSeeq

Current version: v0.4.2 (from VERSION).

Release notes: RELEASE-NOTES.md

Quickstart

Prerequisites

  • An API key for your chosen provider — DeepSeek (DEEPSEEK_API_KEY), Anthropic (ANTHROPIC_API_KEY), Google (GOOGLE_API_KEY), Grok (GROK_API_KEY), or Venice (VENICE_API_KEY). Set it interactively with codeseeq config (local gateways need no key).
  • BRAVE_API_KEY (optional) — needed for web-search pings (ping-web).
  • UNSTRUCTURED_API_KEY (optional) — needed for doc-input pings (ping-docs).
  • VENICE_API_KEY (optional) — automatically enables Venice.ai image generation when set (no CODESEEQ_IMAGE_BACKEND needed).
  • Podman or Docker (optional — only needed for container mode).
  • Python 3 + pip install -r requirements-bridge.txt (optional — only needed for host/process mode).

Install

Option A — curl one-liner (recommended)

curl -fsSL https://raw.githubusercontent.com/illdynamics/codeseeq/main/scripts/install.sh | bash

Downloads the latest release zip, extracts it, and installs the codeseeq command to ~/.config/codeseeq with a launcher at ~/bin/codeseeq.

Option B — git clone

git clone https://github.com/illdynamics/codeseeq.git
cd codeseeq
./codeseeq install

Option C — download release zip manually

Download codeseeq-$(cat VERSION).zip from GitHub Releases, then:

unzip codeseeq-$(cat VERSION).zip
cd codeseeq-$(cat VERSION)# or wherever it extracted
./codeseeq install

Post-install

Make sure ~/bin is in your PATH:

export PATH="$HOME/bin:$PATH"

Set your provider, model, and API key interactively (recommended):

codeseeq config

codeseeq config walks you through three screens: provider (anthropic, google, grok, deepseek, venice, local) → model → API key, and writes ~/.config/codeseeq/config.json. Non-local providers pick a model from the catalog on screen two; the local provider takes any model name you type. The API-key screen is required for hosted providers and can be left empty for local gateways (an optional LOCAL_API_KEY is honoured when set). You can also copy the env template and set keys manually:

cp .env.example .env
# edit .env with your keysexport DEEPSEEK_API_KEY=sk-...

Use it

codeseeq -y "say hi"
codeseeq run "say hi"
codeseeq run -f task.md
codeseeq --model deepseek-v4-pro "review this repo"
codeseeq -p myprofile "say hi"

Host-native mode (no Docker/Podman needed)

pip3 install -r ~/.config/codeseeq/requirements-bridge.txt
codeseeq --bridge-mode process -y "say hi"

Uninstall

codeseeq nuke

Runtime Model

CodeSeeq separates where Codex runs from how the bridge is started.

Runtime Modes (where Codex runs)

Set via CODESEEQ_RUNTIME_MODE.

ModeBehavior
containerRun Codex inside a Docker/Podman container. Safe/isolated default.
hostRun Codex directly on the host. No container isolation.
auto (default)Use container for normal paths; use host when danger/yolo is requested.

Container Runtime (Safe Default)

host ./codeseeq
-> podman/docker run codeseeq:dev
-> Codex inside the container
-> local bridge inside the container
-> your provider (deepseek / anthropic / google / grok / venice / local)

Default Codex settings:

  • approval_policy = "on-request"
  • sandbox_mode = "workspace-write"

Host Runtime

Host runtime runs Codex directly on your host checkout. It does not provide container isolation.

# Host runtime with process bridge (no containers at all)
CODESEEQ_RUNTIME_MODE=host CODESEEQ_BRIDGE_MODE=process ./codeseeq run "hello"# Danger/yolo mode: host Codex with bypass flag
./codeseeq -y "fix the tests"
./codeseeq --yolo "fix the tests"

In host runtime with danger/yolo, CodeSeeq starts the bridge (process or container), runs local host codex directly on the current checkout with --dangerously-bypass-approvals-and-sandbox, and uses isolated repo-local CODEX_HOME=$PWD/.codeseeq — never the user's real ~/.codex.

If local codex is missing, install it:

npm install -g @openai/codex

How It Works

CodeSeeq does not fork or patch Codex. It launches the upstream Codex CLI with an isolated generated config.toml. That config points Codex at a local CodeSeeq bridge implementing the OpenAI Responses API. The bridge translates requests to the configured provider — OpenAI-compatible chat completions for DeepSeek, Google, Grok, Venice.ai, and local gateways, and the native Messages API for Anthropic — then converts responses back to the format Codex expects. The generated config includes privacy hardening settings: live web search, disabled analytics/feedback/OTel/history, and provider-only auth with no OpenAI key aliasing.

Bridge Modes

CodeSeeq controls how the translation bridge is started via CODESEEQ_BRIDGE_MODE.

ModeBehavior
processStart bin/codeseeq-bridge.py as a direct child process on the host. No Docker/Podman required.
containerStart the bridge inside a Docker/Podman container (legacy behavior).
externalAssume the bridge is already running. Use CODESEEQ_BRIDGE_BASE_URL.
auto (default)Prefer process mode when Python + dependencies are available. Fall back to container.

Process Mode (Recommended for Host Runtime)

# No container needed for the bridge
CODESEEQ_BRIDGE_MODE=process DEEPSEEK_API_KEY=sk-... ./codeseeq -y "inspect this repo"# Or just rely on auto-detection when deps are installed
pip3 install -r requirements-bridge.txt
DEEPSEEK_API_KEY=sk-... ./codeseeq -y "review the code"# Combined: host runtime + process bridge (zero containers)
CODESEEQ_RUNTIME_MODE=host CODESEEQ_BRIDGE_MODE=process DEEPSEEK_API_KEY=sk-... ./codeseeq run "hello"

Process mode is not a sandbox boundary — it only removes the bridge sidecar container. Use it when you want to avoid Docker-in-Docker or are already running inside a container.

Container Mode (Legacy)

# Force old container-bridge behavior
CODESEEQ_BRIDGE_MODE=container DEEPSEEK_API_KEY=sk-... ./codeseeq -y "hello"

External Mode

# Point at an already-running bridge
CODESEEQ_BRIDGE_MODE=external CODESEEQ_BRIDGE_BASE_URL=http://127.0.0.1:8080/v1 DEEPSEEK_API_KEY=sk-... ./codeseeq -y "hello"

Bridge Configuration

VariableDefaultDescription
CODESEEQ_BRIDGE_MODEautoauto, process, container, or external
CODESEEQ_BRIDGE_HOST127.0.0.1Bridge listen address
CODESEEQ_BRIDGE_PORTauto-selectFixed bridge port (omit for auto-select)
CODESEEQ_BRIDGE_PORT_FILE<pid-file>.portFile the bridge writes its chosen port to
CODESEEQ_BRIDGE_CONTAINER_PORT8080Internal port the bridge binds inside a container
CODESEEQ_BRIDGE_BASE_URLFull bridge URL override (external mode)
CODESEEQ_BRIDGE_LOG~/.config/codeseeq/log/bridge.logBridge log file
CODESEEQ_BRIDGE_STARTUP_TIMEOUT10Seconds to wait for health check
CODESEEQ_BRIDGE_REUSE0Reuse existing healthy bridge

When CODESEEQ_BRIDGE_PORT is omitted, the bridge performs a real bind for each candidate port starting at CODESEEQ_OPENRESPONSES_PORT (default 8080) and increments up to CODESEEQ_OPENRESPONSES_PORT_SCAN_LIMIT until an actually free port is found. This removes the old connect-probe race (TOCTOU) so multiple codeseeq invocations can run in parallel and reliably get distinct ports. The chosen port is written to CODESEEQ_BRIDGE_PORT_FILE.

Container Runtime

Podman is preferred. Docker is supported as a compatible fallback. Docker Compose is not supported.

Selection order:

  1. CONTAINER=... override, if set.
  2. podman
  3. docker

Examples:

CONTAINER=podman ./codeseeq models
CONTAINER=docker ./codeseeq models
make CONTAINER=docker build

Podman bind mounts use :Z by default for SELinux. Docker uses no suffix by default. Override advanced mount behavior with:

CODESEEQ_VOLUME_SUFFIX=:z ./codeseeq run "say hi"
CODESEEQ_VOLUME_SUFFIX= ./codeseeq run "say hi"

Workspace Paths

In container runtime, Codex works in /workspace inside the container. That path is a bind mount of the directory where you launched ./codeseeq, so writes land in your host checkout.

Before Codex starts, CodeSeeq prints a stderr banner:

CodeSeeq workspace:
host: /home/user/project
container: /workspace

The host path is only for operator clarity. Codex still writes to /workspace inside the container.

Disable the banner:

CODESEEQ_WORKSPACE_BANNER=false ./codeseeq run "say hi"

Persistent System Prompt

CodeSeeq can store a user-level persistent system prompt:

./codeseeq system add "You are terse and practical."
./codeseeq system add -f prompts/system.md
./codeseeq system add --file prompts/system.md
./codeseeq system view
./codeseeq system remove

Aliases:

  • view, show, cat
  • remove, rm, clear

Storage path:

~/.config/codeseeq/system-prompt.md

The prompt is injected into Codex config as developer_instructions, which Codex sends as a developer instruction while preserving Codex's built-in base instructions. It applies to normal Codex request paths including interactive sessions, bare direct prompts, run, run -f/--file, explicit codex passthrough, container runtime, and host runtime.

Do not put secrets in the system prompt unless you understand that prompt text is sent to the model and stored in user-level config state.

Prompt Files

Run a task file directly:

./codeseeq run -f task.md
./codeseeq run --file task.md
./codeseeq run --file=task.md
./codeseeq run -f ./tasks/build-feature.md --model deepseek-v4-pro
./codeseeq run -f task.md --thinking
./codeseeq run -f task.md --yolo

run -f/--file reads the file as the prompt, preserving markdown, newlines, indentation, and code fences. Missing files fail clearly. Providing both a file and inline prompt text fails clearly.

Large prompt files are copied through .codeseeq/tmp/ for container mode instead of being expanded into a huge shell argument.

Commands

CodeSeeq-specific commands remain available:

./codeseeq build
./codeseeq install
./codeseeq nuke
./codeseeq doctor
./codeseeq models
./codeseeq config
./codeseeq ping
./codeseeq ping-stream
./codeseeq ping-web
./codeseeq ping-docs
./codeseeq ping-image
./codeseeq shell
./codeseeq smoke
./codeseeq system --help
./codeseeq package

Explicit passthrough:

./codeseeq codex --help
./codeseeq codex exec"say hi"

Unknown non-CodeSeeq arguments are passed to Codex as much as possible. CodeSeeq does not use -p or --prompt as prompt aliases. -p and --profile are Codex profile-selection flags and are forwarded unchanged. Direct prompt execution is ./codeseeq "prompt" or ./codeseeq run "prompt".

Environment Variables

All supported variables are documented in .env.example. Key ones:

VariableDefaultDescription
DEEPSEEK_API_KEY— (required for deepseek)DeepSeek model API key
ANTHROPIC_API_KEY— (required for anthropic)Anthropic Claude API key
GOOGLE_API_KEY— (required for google)Google Gemini API key
GROK_API_KEY— (required for grok)Grok / xAI API key
BRAVE_API_KEYWeb search API key (for ping-web)
UNSTRUCTURED_API_KEYDoc input API key (for ping-docs)
RESPONSES_API_KEYResponses API key (advanced)
CODESEEQ_MODELdeepseek-v4-flashDefault model (provider@model, e.g. anthropic@claude-sonnet-4, local@my-model)
CODESEEQ_PROVIDEROptional explicit provider override (deepseek, anthropic, google, grok, venice, local)
CODESEEQ_THINKINGfalseEnable thinking mode
CODESEEQ_APPROVAL_POLICYon-requestCodex approval policy
CODESEEQ_SANDBOX_MODEworkspace-writeCodex sandbox mode
CODESEEQ_YOLOfalseBypass approvals and sandbox (equivalent to -y)
CODESEEQ_IMAGE_BACKENDnoneImage backend: none or venice (auto-set when VENICE_API_KEY present)
VENICE_API_KEYVenice API key (image generation)
CODESEEQ_VENICE_IMAGE_MODELz-image-turboVenice image model
CODESEEQ_RUNTIME_MODEautoauto, container, or host
CODESEEQ_BRIDGE_MODEautoauto, process, container, or external
CONTAINERpodmanContainer runtime (podman or docker)
IMAGEcodeseeq:devContainer image tag

JSON configuration (optional alternative to environment variables)

Every CodeSeeq setting can be supplied through a JSON config file instead of (and in addition to) environment variables. JSON keys are the literal environment-variable names (CODESEEQ_MODEL, DEEPSEEK_API_KEY, CODESEEQ_QWIBUS_QWIKK_BASE_URL, etc.). Precedence is always:

  1. explicit environment variable
  2. JSON config value
  3. built-in default

So a value set in the environment always overrides the same key in JSON. JSON config is read from CODESEEQ_CONFIG_JSON if set, otherwise ~/.config/codeseeq/config.json (host) or /home/codeseeq/.config/codeseeq/config.json (container).

{
"CODESEEQ_MODEL": "anthropic@claude-sonnet-4",
"CODESEEQ_PROVIDER": "anthropic",
"ANTHROPIC_API_KEY": "sk-ant-...",
"CODESEEQ_BRIDGE_MODE": "process"
}

codeseeq config writes exactly this kind of file for you.

The full list of supported keys corresponds one-to-one with the environment variables documented in .env.example (any CODESEEQ_* variable plus the provider keys DEEPSEEK_API_KEY, ANTHROPIC_API_KEY, GOOGLE_API_KEY, GROK_API_KEY, VENICE_API_KEY, LOCAL_API_KEY, BRAVE_API_KEY, UNSTRUCTURED_API_KEY, RESPONSES_API_KEY, CONTAINER, IMAGE, OPENAI_BASE_URL, DEEPSEEK_BASE_URL, DEEPSEEK_CHAT_URL, ANTHROPIC_BASE_URL, GOOGLE_BASE_URL, GROK_BASE_URL, VENICE_BASE_URL, LOCAL_BASE_URL, UNSTRUCTURED_API_URL, and QWIBUS_NO_API_KEY).

Clean Packages

Release zips must be produced by the official package command only:

./scripts/package.sh
./codeseeq package
make package

Validate a generated or uploaded archive:

./scripts/package.sh --check
./scripts/package.sh --check-archive dist/codeseeq-YYYYMMDD-HHMMSS.zip
./scripts/package.sh --check-archive /mnt/data/codeseeq.zip

Do not create release zips manually in Finder or macOS Archive Utility. Manual zips can include __MACOSX, .DS_Store, .git/, .codeseeq/, nested zips, or .env files. .env.example is the only env-style file intended for release archives.

Image Generation Backend

CodeSeeq supports an optional image generation backend via Venice.ai — a privacy-first, uncensored AI platform.

Auto-detection: When VENICE_API_KEY is set, CodeSeeq automatically enables the Venice backend. No explicit CODESEEQ_IMAGE_BACKEND=venice is required.

Configuration

VariableDefaultDescription
VENICE_API_KEYVenice API key — setting this auto-enables the Venice image backend
CODESEEQ_IMAGE_BACKENDnoneImage backend: none or venice (auto-set when key present)
CODESEEQ_VENICE_IMAGE_MODELz-image-turboModel (e.g. z-image-turbo, gpt-image-2)
CODESEEQ_VENICE_IMAGE_ASPECT_RATIO1:1Aspect ratio: 1:1, 16:9, 9:16, 4:3, 3:4
CODESEEQ_VENICE_IMAGE_RESOLUTION1KResolution: 1K, 2K, 4K
CODESEEQ_VENICE_IMAGE_FORMATwebpOutput format: jpeg, png, webp
CODESEEQ_VENICE_IMAGE_VARIANTS1Number of variants: 1–4
CODESEEQ_VENICE_IMAGE_SAFE_MODEtrueBlur adult content
CODESEEQ_VENICE_IMAGE_HIDE_WATERMARKfalseHide Venice watermark

Usage

# Auto-detection: just set VENICE_API_KEY, no backend config neededexport VENICE_API_KEY=your-key-here
# Test connectivity
./codeseeq ping-image
# Use auto model selection (default)
./codeseeq run "generate a picture of a cat"# Specify model and aspect ratio
CODESEEQ_VENICE_IMAGE_MODEL=z-image-turbo \
CODESEEQ_VENICE_IMAGE_ASPECT_RATIO=16:9 \
CODESEEQ_VENICE_IMAGE_RESOLUTION=4K \
./codeseeq run "generate a cinematic wide shot of venice at sunset"# Direct CLI usage (no Codex needed) — outputs to current directory
python3 bin/codeseeq-venice-image.py --prompt "a beautiful sunset" --out sunset.png

Supported Models

CodeSeeq supports these providers (choose them with codeseeq config):

ProviderKey env varExample models
DeepSeekDEEPSEEK_API_KEYdeepseek-v4-flash (default), deepseek-v4-pro (+ -thinking variants)
AnthropicANTHROPIC_API_KEYclaude-sonnet-4, claude-opus-4, claude-haiku-4 (+ thinking variants)
GoogleGOOGLE_API_KEYgemini-2.5-pro, gemini-2.5-flash, gemini-2.0-flash, gemini-1.5-pro
Grok (xAI)GROK_API_KEYgrok-4, grok-3, grok-3-mini, grok-3-fast (+ thinking variants)
Venice.aiVENICE_API_KEYvenice-qwen-3-32b, venice-qwen-3-14b, venice-deepseek-r1-0528, venice-llama-3.3-70b, venice-qwen-2.5-coder-32b
Localnone (optional LOCAL_API_KEY)any OpenAI-compatible model name typed manually, e.g. local@llama-4-maverick
Qwibusnoneqwibus-qwikk, qwibus-qmplx (legacy local gateway)

Model slugs use the provider@model form (deepseek@deepseek-v4-flash, anthropic@claude-sonnet-4, local@my-model, ...). Legacy aliases remain:

  • deepseek-v4-flash, deepseek-v4-flash-thinking, deepseek-v4-pro, deepseek-v4-pro-thinking
  • qwibus-qwikk, qwibus-qmplx, qwibus@qwibus-qwikk, qwibus@qwibus-qmplx

Note on Anthropic -thinking variants: extended thinking works for single-turn requests. Anthropic requires the assistant thinking signature to be passed back across turns when tools are used, which a stateless bridge cannot persist — so multi-turn agentic runs with claude-*-thinking may fail at the API. Use the non-thinking Claude variants for multi-turn tool-driven work.

Model catalogs

CodeSeeq ships two catalogs in config/, and both are used for distinct consumers:

FileConsumerPurpose
config/codex-model-catalog.jsonCodex CLIPassed via model_catalog_json in the generated config.toml for TUI model selection (slug schema).
config/model-catalog.jsonCodeSeeq bridgeRead via CODESEEQ_MODEL_CATALOG_JSON to supply endpoint/sampling defaults (provider_model schema).

They are intentionally not redundant, so neither is deleted. Either path can be overridden with CODESEEQ_HOST_MODEL_CATALOG_JSON (host) or CODESEEQ_MODEL_CATALOG_JSON (bridge). Per-model CODESEEQ_<MODEL>_* env vars (or their JSON-config equivalents) always override the bridge catalog.

Diagnostics

Load .env for local live tests without modifying it:

set -a
source .env
set +a

Then run:

./codeseeq doctor
./codeseeq config
./codeseeq ping
./codeseeq ping-stream
./codeseeq ping-web
./codeseeq ping-docs

doctor reports system prompt status, storage path, byte count, line count, and injection mechanism without printing the prompt content. codeseeq config runs the interactive provider/model/key wizard; codeseeq config status prints the current stored LLM configuration without revealing keys.

Interactive Menu Notes

Codex's normal interactive menu and slash commands run inside CodeSeeq's isolated CODEX_HOME.

Manual check:

./codeseeq

Open the Codex menu or use slash commands such as /model where supported by your Codex version. Approval and sandbox toggles use upstream Codex behavior. The model menu is backed by the generated Codex catalog (config/codex-model-catalog.json merged with your configured model) where Codex honors model_catalog_json; wrapper and bridge validation remain authoritative if upstream Codex shows additional models.

CI / Release Pipeline

CodeSeeq uses a single GitHub Actions workflow (ci.yml) that runs on every push and pull request:

  1. static — shell syntax checks, shellcheck, secret scanning, whitespace checks
  2. project — bridge extraction tests, config generation validation, version consistency
  3. bridge-smoke — bridge process smoke tests, package build & validation
  4. docker — Docker image build and all container smoke tests
  5. 🚀 Release — runs only on tag pushes (v*) and only after all four checks pass. Builds the package and creates a GitHub Release with the zip artifact attached.

The release job is gated behind needs: [static, project, bridge-smoke, docker] and if: startsWith(github.ref, 'refs/tags/v').

Makefile Targets

TargetDescription
installRun ./codeseeq install
buildBuild container image (podman build)
modelsList available models
doctorRun diagnostics
ping / ping-streamTest model connectivity
ping-web / ping-docs / ping-imageTest web search / doc input / image generation connectivity
promptRun a one-shot prompt (PROMPT=...)
runStart interactive Codex session
shellStart Codex shell mode
smokeRun the full smoke-test suite
package / package-checkBuild / validate release archive
bridge-checkCheck bridge Python syntax and imports
bridge-process-smokeRun bridge process smoke tests
inspect-bridgeDisplay bridge runtime info
clean-artifactsRemove build artifacts (__pycache__, etc.)
cleanRemove container image
checkRun all project checks

Architecture and Security

Local reference paths mentioned by older docs, such as ./codex and ./open-responses, may be absent from a minimal checkout. This repository's runtime does not depend on Docker Compose or the upstream open-responses npm package.

Privacy Hardening

CodeSeeq applies privacy hardening by default:

SettingValue
Model providerYour choice (deepseek / anthropic / google / grok / venice / local), always via the local bridge
Web searchLive (not cached)
AnalyticsDisabled
FeedbackDisabled
OpenTelemetry log exporterNone
OpenTelemetry metrics exporterNone
OpenTelemetry trace exporterNone
Raw user prompt loggingDisabled
History persistenceNone
Upstream OpenAI/Codex commandsBlocked (login, logout, cloud, app, app-server, plugin, update, features)
OPENAI_API_KEY from DEEPSEEK_API_KEYNot auto-populated
Codex versionPinned (no auto-update)
Latest release auto-fetchEnabled by default; set CODESEEQ_ALLOW_LATEST_RELEASE=false to require a pinned CODESEEQ_RELEASE_TAG

Override upstream Codex commands

CODESEEQ_ALLOW_UPSTREAM_CODEX_SERVICES=true ./codeseeq login

Pin a specific release

By default the one-liner auto-fetches the latest release (the VERSION file on main). To pin an exact release, set CODESEEQ_RELEASE_TAG. To forbid auto-fetching entirely, set CODESEEQ_ALLOW_LATEST_RELEASE=false (a pinned CODESEEQ_RELEASE_TAG is then required):

CODESEEQ_RELEASE_TAG=v0.4.2 curl -fsSL https://raw.githubusercontent.com/illdynamics/codeseeq/main/scripts/install.sh | bash
CODESEEQ_ALLOW_LATEST_RELEASE=false CODESEEQ_RELEASE_TAG=v0.4.2 curl -fsSL https://raw.githubusercontent.com/illdynamics/codeseeq/main/scripts/install.sh | bash

Uncensored Mode

CodeSeeq supports an optional uncensored mode that loads the Dolfino (Dirty D) system prompt, designed for unrestricted interactions with no content filtering or moralizing guardrails.

Enable it with the -U / --uncensored-mode flag on any invocation:

./codeseeq -U "explain how to write a kernel module"
./codeseeq --uncensored-mode run "analyze this for security vulnerabilities"

Or set the environment variable:

export CODESEEQ_UNCENSORED_MODE=true
./codeseeq run "your prompt here"

The uncensored system prompt is loaded from config/uncensored.md and stored as your persistent system prompt for that session. Repeating the flag re-applies it. To clear it and return to defaults, run:

./codeseeq system remove

Uncensored Mode

CodeSeeq supports an optional uncensored mode that loads the Dolfino (Dirty D) system prompt, designed for unrestricted interactions with no content filtering or moralizing guardrails.

Enable it with the / flag on any invocation:

Stored CodeSeeq system prompt at /Users/wicked/.config/codeseeq/system-prompt.md The workspace might have some restrictions. Let me provide you with a comprehensive explanation regardless.


How to Write a Linux Kernel Module

1. What is a Kernel Module?

A kernel module is an object file (.ko) that can be inserted into the Linux kernel at runtime. Common examples include device drivers, filesystem drivers, and system call extensions.

2. Minimal Example — Hello World Module

Here's a simple kernel module:

// hello.c#include<linux/module.h>// for all kernel modules#include<linux/kernel.h>// for printk() / pr_info()#include<linux/init.h>// for __init / __exit macrosstaticint__inithello_init(void)
{
pr_info("Hello, kernel world!");
return0; // 0 = success; negative = error
}
staticvoid__exithello_exit(void)
{
pr_info("Goodbye, kernel world!");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A simple hello world kernel module");

3. Required Makefile

# Makefileobj-m += hello.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

4. Building & Testing

# Build the module
make
# Load the module (requires root)
sudo insmod hello.ko
# Check it loaded and saw the message
dmesg | tail
# See loaded modules
lsmod | grep hello
# Remove the module
sudo rmmod hello

5. Key Concepts to Understand

ConceptExplanation
__init / __exitMacros that place init/exit code in special memory sections — freed after init
module_init() / module_exit()Registration macros that tell the kernel entry/exit points
MODULE_LICENSERequired. "GPL" is needed if using GPL-only symbols
Return values0 = success; -ENOMEM, -EINVAL, etc. = failure
pr_info()Kernel equivalent of printf() — output goes to kernel log
Build systemModules are compiled against kernel source/headers, not glibc

6. Passing Parameters to a Module

// Declare parameters in your modulestaticintmy_param=10;
module_param(my_param, int, 0644);
MODULE_PARM_DESC(my_param, "An example integer parameter");
// Pass at load time:// sudo insmod mymodule.ko my_param=42// Or see/set at runtime via sysfs:// cat /sys/module/mymodule/parameters/my_param// echo 99 | sudo tee /sys/module/mymodule/parameters/my_param

7. Common Module Types — What to Build Next

  1. Character device driverregister_chrdev() → create /dev/mydevice
  2. Misc device driver — simpler char device, misc_register()
  3. Platform driver — for hardware on a platform bus (embedded systems, Device Tree)
  4. PCI/USB driver — for PCI/USB devices
  5. File operationsstruct file_operations with .open, .read, .write, .ioctl
  6. Sysfs / procfs entries — expose data via kobject_create_and_add()
  7. Timers & workqueues — deferred work with schedule_work() or kernel timers

8. Debugging Tips

ToolPurpose
dmesg -wWatch kernel log in real time
cat /proc/modulesList loaded modules
/sys/module/<name>/Runtime module info
printk() with KERN_DEBUG / pr_debug()Debug output (needs DEBUG defined or dyndbg)
KGDB / KDBKernel debugger
ftraceTrace function calls inside the kernel

9. Important Rules & Pitfalls

  • Use kernel API — never link against libc; use kmalloc() not malloc()
  • Check return values from all kernel functions
  • Use proper lockingspin_lock(), mutex_lock() for shared data
  • Handle module reference counting (try_module_get() / module_put())
  • Don't sleep in atomic context (spinlock held, interrupt handler)
  • Don't use floating point in kernel space
  • Don't block for long in module init (use probe() properly)
  • Never crash — a kernel oops brings down the whole system

10. Learning Path (Recommended Order)

  1. ✅ Hello World (above)
  2. ✅ Parameters & sysfs interactions
  3. ✅ Character device with struct file_operations
  4. ✅ Wait queues (wait_event_interruptible)
  5. ✅ Timers & workqueues
  6. ioctl interface
  7. ✅ Platform driver (DT-based)
  8. ✅ Memory-mapped I/O (ioremap)
  9. ✅ PCI driver skeleton

⚠️ Note: The workspace appears to have sandbox restrictions preventing compilation. To actually build and test kernel modules, you'll need a full Linux system with kernel headers installed (apt install linux-headers-$(uname -r) or equivalent) and root access for insmod/rmmod.

Would you like me to expand on any specific part — like a character device example, parameters, or a specific driver type? Stored CodeSeeq system prompt at /Users/wicked/.config/codeseeq/system-prompt.md I'd be happy to help analyze for security vulnerabilities! However, I need to know what you'd like me to analyze. Could you please specify:

  1. A file or directory in the workspace you want me to scan (e.g., a codebase, configuration file, script)
  2. A repository URL you'd like me to clone and analyze
  3. Specific code or configuration you want reviewed

For example, you could say:

  • "Analyze the /workspace/my-app directory for security vulnerabilities"
  • "Scan this Python file at /workspace/auth.py"
  • "Check /workspace/package.json for security issues"

What would you like me to examine?

Or set the environment variable:

Stored CodeSeeq system prompt at /Users/wicked/.config/codeseeq/system-prompt.md I see you've sent a placeholder message. How can I help you today? If you have a task or question, please go ahead and share it!

The uncensored system prompt is loaded from and stored as your persistent system prompt for that session. Repeating the flag re-applies it. To clear it and return to defaults, run:

Removed CodeSeeq system prompt at /Users/wicked/.config/codeseeq/system-prompt.md

## License
Licensed under the Apache License, Version 2.0 (Apache-2.0).
- Full license text: [`LICENSE`](./LICENSE)
- Copyright notices: [`COPYRIGHT`](./COPYRIGHT)

About

The Codex CLI tool, wired to Deepseek as the brain. Your favourite workflow up to 200x cheaper and fully functional!

Topics

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Contributors

Languages